Browse Source

Merge branch 'master' into gi_vrs

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
41c5bb40ed
100 changed files with 1804 additions and 1713 deletions
  1. 12 6
      .github/workflows/Android.yml
  2. 1 1
      .github/workflows/Linux.yml
  3. 2 1
      AnKi/CMakeLists.txt
  4. 4 3
      AnKi/Collision/CMakeLists.txt
  5. 3 1
      AnKi/Config.h.cmake
  6. 18 6
      AnKi/Core/App.cpp
  7. 3 2
      AnKi/Core/App.h
  8. 26 8
      AnKi/Core/CMakeLists.txt
  9. 1 1
      AnKi/Core/ConfigVars.defs.h
  10. 1 0
      AnKi/Core/NativeWindow.h
  11. 9 14
      AnKi/Core/NativeWindowSdl.cpp
  12. 19 14
      AnKi/Gr/CMakeLists.txt
  13. 0 3
      AnKi/Gr/CommandBuffer.h
  14. 5 2
      AnKi/Gr/Common.h
  15. 54 0
      AnKi/Gr/Enums.cpp
  16. 30 50
      AnKi/Gr/Enums.h
  17. 39 38
      AnKi/Gr/ShaderVariableDataType.defs.h
  18. 1 3
      AnKi/Gr/Texture.h
  19. 1 1
      AnKi/Gr/TextureView.h
  20. 2 25
      AnKi/Gr/Utils/Functions.cpp
  21. 1 4
      AnKi/Gr/Utils/Functions.h
  22. 4 9
      AnKi/Gr/Vulkan/BufferImpl.cpp
  23. 0 6
      AnKi/Gr/Vulkan/CommandBuffer.cpp
  24. 45 126
      AnKi/Gr/Vulkan/CommandBufferFactory.cpp
  25. 23 23
      AnKi/Gr/Vulkan/CommandBufferFactory.h
  26. 0 5
      AnKi/Gr/Vulkan/CommandBufferImpl.h
  27. 1 1
      AnKi/Gr/Vulkan/Common.cpp
  28. 2 2
      AnKi/Gr/Vulkan/Common.h
  29. 6 0
      AnKi/Gr/Vulkan/DeferredBarrierFactory.h
  30. 11 4
      AnKi/Gr/Vulkan/DescriptorSet.cpp
  31. 156 0
      AnKi/Gr/Vulkan/FrameGarbageCollector.cpp
  32. 90 0
      AnKi/Gr/Vulkan/FrameGarbageCollector.h
  33. 55 32
      AnKi/Gr/Vulkan/GrManagerImpl.cpp
  34. 19 0
      AnKi/Gr/Vulkan/GrManagerImpl.h
  35. 34 4
      AnKi/Gr/Vulkan/MicroObjectRecycler.h
  36. 106 47
      AnKi/Gr/Vulkan/MicroObjectRecycler.inl.h
  37. 15 0
      AnKi/Gr/Vulkan/Pipeline.cpp
  38. 12 1
      AnKi/Gr/Vulkan/Pipeline.h
  39. 1 1
      AnKi/Gr/Vulkan/PipelineCache.cpp
  40. 6 0
      AnKi/Gr/Vulkan/SemaphoreFactory.h
  41. 2 1
      AnKi/Gr/Vulkan/ShaderImpl.h
  42. 6 1
      AnKi/Gr/Vulkan/ShaderProgramImpl.cpp
  43. 2 1
      AnKi/Gr/Vulkan/ShaderProgramImpl.h
  44. 6 0
      AnKi/Gr/Vulkan/SwapchainFactory.h
  45. 34 52
      AnKi/Gr/Vulkan/TextureImpl.cpp
  46. 0 2
      AnKi/Gr/Vulkan/TextureImpl.h
  47. 4 2
      AnKi/Importer/CMakeLists.txt
  48. 12 12
      AnKi/Importer/GltfImporter.cpp
  49. 1 1
      AnKi/Importer/GltfImporter.h
  50. 40 39
      AnKi/Importer/GltfImporterMaterial.cpp
  51. 19 6
      AnKi/Importer/GltfImporterMesh.cpp
  52. 1 1
      AnKi/Importer/ImageImporter.cpp
  53. 2 0
      AnKi/Importer/TinyExr.cpp
  54. 6 8
      AnKi/Input/CMakeLists.txt
  55. 4 2
      AnKi/Math/CMakeLists.txt
  56. 4 2
      AnKi/Physics/CMakeLists.txt
  57. 1 1
      AnKi/Renderer/AccelerationStructureBuilder.cpp
  58. 5 4
      AnKi/Renderer/Bloom.cpp
  59. 4 2
      AnKi/Renderer/CMakeLists.txt
  60. 22 16
      AnKi/Renderer/ClusterBinning.cpp
  61. 1 1
      AnKi/Renderer/Common.h
  62. 10 5
      AnKi/Renderer/ConfigVars.defs.h
  63. 1 1
      AnKi/Renderer/Dbg.cpp
  64. 4 13
      AnKi/Renderer/DepthDownscale.cpp
  65. 4 4
      AnKi/Renderer/DownscaleBlur.cpp
  66. 24 19
      AnKi/Renderer/Drawer.cpp
  67. 4 3
      AnKi/Renderer/Drawer.h
  68. 4 5
      AnKi/Renderer/FinalComposite.cpp
  69. 14 9
      AnKi/Renderer/ForwardShading.cpp
  70. 5 5
      AnKi/Renderer/GBuffer.cpp
  71. 6 6
      AnKi/Renderer/GBuffer.h
  72. 1 1
      AnKi/Renderer/GBufferPost.cpp
  73. 7 8
      AnKi/Renderer/IndirectDiffuse.cpp
  74. 12 14
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  75. 2 3
      AnKi/Renderer/IndirectSpecular.cpp
  76. 3 4
      AnKi/Renderer/LensFlare.cpp
  77. 5 4
      AnKi/Renderer/LightShading.cpp
  78. 1 1
      AnKi/Renderer/MainRenderer.cpp
  79. 4 5
      AnKi/Renderer/MotionVectors.cpp
  80. 7 10
      AnKi/Renderer/ProbeReflections.cpp
  81. 4 12
      AnKi/Renderer/RenderQueue.h
  82. 19 20
      AnKi/Renderer/Renderer.cpp
  83. 1 1
      AnKi/Renderer/Renderer.h
  84. 14 15
      AnKi/Renderer/RtShadows.cpp
  85. 0 1
      AnKi/Renderer/RtShadows.h
  86. 7 6
      AnKi/Renderer/Scale.cpp
  87. 8 9
      AnKi/Renderer/ShadowMapping.cpp
  88. 2 2
      AnKi/Renderer/ShadowmapsResolve.cpp
  89. 5 6
      AnKi/Renderer/TemporalAA.cpp
  90. 1 1
      AnKi/Renderer/Tonemapping.cpp
  91. 4 3
      AnKi/Renderer/TraditionalDeferredShading.cpp
  92. 2 12
      AnKi/Renderer/VolumetricFog.cpp
  93. 4 12
      AnKi/Renderer/VolumetricLightingAccumulation.cpp
  94. 4 4
      AnKi/Renderer/VrsSriGeneration.cpp
  95. 4 2
      AnKi/Resource/CMakeLists.txt
  96. 0 28
      AnKi/Resource/Common.h
  97. 18 1
      AnKi/Resource/ImageResource.cpp
  98. 489 547
      AnKi/Resource/MaterialResource.cpp
  99. 75 263
      AnKi/Resource/MaterialResource.h
  100. 31 50
      AnKi/Resource/ModelResource.cpp

+ 12 - 6
.github/workflows/Android.yml

@@ -14,21 +14,27 @@ jobs:
 
 
     steps:
     steps:
     - name: Install dependencies
     - name: Install dependencies
-      run: | 
-        apt-get update 
+      run: |
+        apt-get update
         apt install ninja-build
         apt install ninja-build
-      
+
     - name: Clone
     - name: Clone
       uses: actions/checkout@v2
       uses: actions/checkout@v2
 
 
+    - name: Configure CMake for Linux
+      run: cmake -B ${{github.workspace}}/build -DANKI_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DANKI_EXTRA_CHECKS=OFF
+
+    - name: Build Linux ShaderCompiler
+      run: cmake --build ${{github.workspace}}/build --config Release --target ShaderCompiler
+
     - name: Generate project
     - name: Generate project
-      run: ./Samples/Sponza/GenerateAndroidProject.sh
-    
+      run: ./Samples/Sponza/GenerateAndroidProject.sh ${{github.workspace}}/build/Bin/ShaderCompiler
+
     - name: local.properties
     - name: local.properties
       run: |
       run: |
         echo "sdk.dir=/usr/local/android-sdk" > AndroidProject_Sponza/local.properties
         echo "sdk.dir=/usr/local/android-sdk" > AndroidProject_Sponza/local.properties
         echo "ndk.dir=/usr/local/android-ndk" >> AndroidProject_Sponza/local.properties
         echo "ndk.dir=/usr/local/android-ndk" >> AndroidProject_Sponza/local.properties
 
 
-    - name: Build
+    - name: Build Android
       working-directory: AndroidProject_Sponza
       working-directory: AndroidProject_Sponza
       run: ./gradlew build
       run: ./gradlew build

+ 1 - 1
.github/workflows/Linux.yml

@@ -88,7 +88,7 @@ jobs:
       uses: actions/checkout@v2
       uses: actions/checkout@v2
 
 
     - name: Configure CMake
     - name: Configure CMake
-      run: cmake -B ${{github.workspace}}/build -DANKI_BUILD_TESTS=OFF -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug -DANKI_EXTRA_CHECKS=ON -DANKI_HEADLESS=ON
+      run: cmake -B ${{github.workspace}}/build -DANKI_BUILD_TESTS=OFF -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Release -DANKI_EXTRA_CHECKS=ON -DANKI_HEADLESS=ON
 
 
     - name: Build
     - name: Build
       run: cmake --build ${{github.workspace}}/build --config Release
       run: cmake --build ${{github.workspace}}/build --config Release

+ 2 - 1
AnKi/CMakeLists.txt

@@ -1,4 +1,5 @@
-set(ANKI_SUB_DIRS Importer Core Script Renderer Scene Ui Input Physics Resource Gr Collision Math Util ShaderCompiler)
+set(ANKI_SUB_DIRS Importer Core Script Renderer Scene Ui Input Physics Resource Gr Collision Math Util ShaderCompiler
+	Shaders)
 foreach(TMP ${ANKI_SUB_DIRS})
 foreach(TMP ${ANKI_SUB_DIRS})
 	add_subdirectory(${TMP})
 	add_subdirectory(${TMP})
 endforeach()
 endforeach()

+ 4 - 3
AnKi/Collision/CMakeLists.txt

@@ -1,3 +1,4 @@
-file(GLOB SOURCES *.cpp)
-file(GLOB HEADERS *.h)
-anki_add_source_files(${SOURCES} ${HEADERS})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiCollision ${sources})
+target_compile_definitions(AnKiCollision PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiCollision AnKiMath)

+ 3 - 1
AnKi/Config.h.cmake

@@ -175,7 +175,8 @@
 #	define ANKI_HOT __attribute__ ((hot))
 #	define ANKI_HOT __attribute__ ((hot))
 #	define ANKI_UNREACHABLE() __builtin_unreachable()
 #	define ANKI_UNREACHABLE() __builtin_unreachable()
 #	define ANKI_PREFETCH_MEMORY(addr) __builtin_prefetch(addr)
 #	define ANKI_PREFETCH_MEMORY(addr) __builtin_prefetch(addr)
-#	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx) __attribute__((format(printf, fmtArgIdx + 1, firstArgIdx + 1))) // On methods need to include "this"
+#	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx) __attribute__((format(printf, fmtArgIdx + 1, firstArgIdx + 1))) // On methods you need to include "this"
+#	define ANKI_PURE __attribute__((pure))
 #else
 #else
 #	define ANKI_LIKELY(x) (x)
 #	define ANKI_LIKELY(x) (x)
 #	define ANKI_UNLIKELY(x) (x)
 #	define ANKI_UNLIKELY(x) (x)
@@ -189,6 +190,7 @@
 #	define ANKI_UNREACHABLE() __assume(false)
 #	define ANKI_UNREACHABLE() __assume(false)
 #	define ANKI_PREFETCH_MEMORY(addr) (void)(addr)
 #	define ANKI_PREFETCH_MEMORY(addr) (void)(addr)
 #	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx)
 #	define ANKI_CHECK_FORMAT(fmtArgIdx, firstArgIdx)
+#	define ANKI_PURE
 #endif
 #endif
 
 
 // Pack structs
 // Pack structs

+ 18 - 6
AnKi/Core/App.cpp

@@ -1,3 +1,4 @@
+
 // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
 // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
 // All rights reserved.
 // All rights reserved.
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
@@ -153,11 +154,11 @@ void App::cleanup()
 	m_cacheDir.destroy(m_heapAlloc);
 	m_cacheDir.destroy(m_heapAlloc);
 }
 }
 
 
-Error App::init(ConfigSet* config, AllocAlignedCallback allocCb, void* allocCbUserData)
+Error App::init(ConfigSet* config, CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 {
 	ANKI_ASSERT(config);
 	ANKI_ASSERT(config);
 	m_config = config;
 	m_config = config;
-	const Error err = initInternal(allocCb, allocCbUserData);
+	const Error err = initInternal(executableFilename, allocCb, allocCbUserData);
 	if(err)
 	if(err)
 	{
 	{
 		ANKI_CORE_LOGE("App initialization failed. Shutting down");
 		ANKI_CORE_LOGE("App initialization failed. Shutting down");
@@ -167,13 +168,13 @@ Error App::init(ConfigSet* config, AllocAlignedCallback allocCb, void* allocCbUs
 	return err;
 	return err;
 }
 }
 
 
-Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
+Error App::initInternal(CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 {
 	LoggerSingleton::get().enableVerbosity(m_config->getCoreVerboseLog());
 	LoggerSingleton::get().enableVerbosity(m_config->getCoreVerboseLog());
 
 
 	setSignalHandlers();
 	setSignalHandlers();
 
 
-	Thread::setNameOfCurrentThread("anki_main");
+	Thread::setNameOfCurrentThread("AnKiMain");
 
 
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData, "Core");
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData, "Core");
@@ -240,7 +241,8 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	nwinit.m_height = m_config->getHeight();
 	nwinit.m_height = m_config->getHeight();
 	nwinit.m_depthBits = 0;
 	nwinit.m_depthBits = 0;
 	nwinit.m_stencilBits = 0;
 	nwinit.m_stencilBits = 0;
-	nwinit.m_fullscreenDesktopRez = m_config->getWindowFullscreen();
+	nwinit.m_fullscreenDesktopRez = m_config->getWindowFullscreen() > 0;
+	nwinit.m_exclusiveFullscreen = m_config->getWindowFullscreen() == 2;
 	ANKI_CHECK(NativeWindow::newInstance(nwinit, m_window));
 	ANKI_CHECK(NativeWindow::newInstance(nwinit, m_window));
 
 
 	//
 	//
@@ -292,6 +294,17 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	//
 	//
 	// Resource FS
 	// Resource FS
 	//
 	//
+#if !ANKI_OS_ANDROID
+	// Add the location of the executable where the shaders are supposed to be
+	StringAuto executableFname(m_heapAlloc);
+	ANKI_CHECK(getApplicationPath(executableFname));
+	StringAuto shadersPath(m_heapAlloc);
+	getParentFilepath(executableFname, shadersPath);
+	shadersPath.append(":");
+	shadersPath.append(m_config->getRsrcDataPaths());
+	m_config->setRsrcDataPaths(shadersPath);
+#endif
+
 	m_resourceFs = m_heapAlloc.newInstance<ResourceFilesystem>(m_heapAlloc);
 	m_resourceFs = m_heapAlloc.newInstance<ResourceFilesystem>(m_heapAlloc);
 	ANKI_CHECK(m_resourceFs->init(*m_config, m_cacheDir.toCString()));
 	ANKI_CHECK(m_resourceFs->init(*m_config, m_cacheDir.toCString()));
 
 
@@ -304,7 +317,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 	rinit.m_resourceFs = m_resourceFs;
 	rinit.m_resourceFs = m_resourceFs;
 	rinit.m_vertexMemory = m_vertexMem;
 	rinit.m_vertexMemory = m_vertexMem;
 	rinit.m_config = m_config;
 	rinit.m_config = m_config;
-	rinit.m_cacheDir = m_cacheDir.toCString();
 	rinit.m_allocCallback = m_allocCb;
 	rinit.m_allocCallback = m_allocCb;
 	rinit.m_allocCallbackData = m_allocCbData;
 	rinit.m_allocCallbackData = m_allocCbData;
 	m_resources = m_heapAlloc.newInstance<ResourceManager>();
 	m_resources = m_heapAlloc.newInstance<ResourceManager>();

+ 3 - 2
AnKi/Core/App.h

@@ -42,7 +42,8 @@ public:
 
 
 	/// Initialize the application.
 	/// Initialize the application.
 	/// @param[in,out] config The config. Needs to be alive as long as the app is alive.
 	/// @param[in,out] config The config. Needs to be alive as long as the app is alive.
-	ANKI_USE_RESULT Error init(ConfigSet* config, AllocAlignedCallback allocCb, void* allocCbUserData);
+	ANKI_USE_RESULT Error init(ConfigSet* config, CString executableFilename, AllocAlignedCallback allocCb,
+							   void* allocCbUserData);
 
 
 	const String& getSettingsDirectory() const
 	const String& getSettingsDirectory() const
 	{
 	{
@@ -199,7 +200,7 @@ private:
 
 
 	void initMemoryCallbacks(AllocAlignedCallback allocCb, void* allocCbUserData);
 	void initMemoryCallbacks(AllocAlignedCallback allocCb, void* allocCbUserData);
 
 
-	ANKI_USE_RESULT Error initInternal(AllocAlignedCallback allocCb, void* allocCbUserData);
+	ANKI_USE_RESULT Error initInternal(CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData);
 
 
 	ANKI_USE_RESULT Error initDirs();
 	ANKI_USE_RESULT Error initDirs();
 	void cleanup();
 	void cleanup();

+ 26 - 8
AnKi/Core/CMakeLists.txt

@@ -1,17 +1,35 @@
-set(SOURCES App.cpp ConfigSet.cpp GpuMemoryPools.cpp DeveloperConsole.cpp CoreTracer.cpp MaliHwCounters.cpp
+set(sources
+	App.cpp
+	ConfigSet.cpp
+	GpuMemoryPools.cpp
+	DeveloperConsole.cpp
+	CoreTracer.cpp
+	MaliHwCounters.cpp
 	StatsUi.cpp)
 	StatsUi.cpp)
-file(GLOB HEADERS *.h)
 
 
 if(ANKI_HEADLESS)
 if(ANKI_HEADLESS)
-	set(SOURCES ${SOURCES} NativeWindowHeadless.cpp)
+	set(sources ${sources} NativeWindowHeadless.cpp)
 elseif(SDL)
 elseif(SDL)
-	set(SOURCES ${SOURCES} NativeWindowSdl.cpp)
+	set(sources ${sources} NativeWindowSdl.cpp)
 elseif(ANDROID)
 elseif(ANDROID)
-	set(SOURCES ${SOURCES} NativeWindowAndroid.cpp)
+	set(sources ${sources} NativeWindowAndroid.cpp)
 else()
 else()
 	message(FATAL_ERROR "Not implemented")
 	message(FATAL_ERROR "Not implemented")
 endif()
 endif()
 
 
-foreach(S ${SOURCES})
-	anki_add_source_files("${CMAKE_CURRENT_SOURCE_DIR}/${S}" ${HEADERS})
-endforeach()
+add_library(AnKiCore ${sources})
+
+if(SDL)
+	if(LINUX)
+		set(extra_libs X11-xcb pthread dl)
+	endif()
+
+	set(extra_libs ${extra_libs} SDL2-static)
+elseif(ANDROID)
+	set(extra_libs log android AnKiAndroidNativeGlue AnKiHwcPipe)
+elseif(WINDOWS)
+	set(extra_libs version Imm32 Winmm DbgHelp)
+endif()
+
+target_compile_definitions(AnKiCore PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiCore AnKiGr AnKiResource AnKiUi AnKiRenderer AnKiUtil AnKiPhysics AnKiScript AnKiInput ${extra_libs})

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

@@ -15,7 +15,7 @@ ANKI_CONFIG_VAR_BOOL(CoreMaliHwCounters, false, "Enable Mali counters")
 
 
 ANKI_CONFIG_VAR_U32(Width, 1920, 16, 16 * 1024, "Width")
 ANKI_CONFIG_VAR_U32(Width, 1920, 16, 16 * 1024, "Width")
 ANKI_CONFIG_VAR_U32(Height, 1080, 16, 16 * 1024, "Height")
 ANKI_CONFIG_VAR_U32(Height, 1080, 16, 16 * 1024, "Height")
-ANKI_CONFIG_VAR_BOOL(WindowFullscreen, false, "Start at fullscreen")
+ANKI_CONFIG_VAR_U32(WindowFullscreen, 1, 0, 2, "0: windowed, 1: borderless fullscreen, 2: exclusive fullscreen")
 
 
 ANKI_CONFIG_VAR_U32(CoreTargetFps, 60u, 30u, MAX_U32, "Target FPS")
 ANKI_CONFIG_VAR_U32(CoreTargetFps, 60u, 30u, MAX_U32, "Target FPS")
 ANKI_CONFIG_VAR_U32(CoreJobThreadCount, max(2u, getCpuCoresCount() / 2u), 2u, 1024u, "Number of job thread")
 ANKI_CONFIG_VAR_U32(CoreJobThreadCount, max(2u, getCpuCoresCount() / 2u), 2u, 1024u, "Number of job thread")

+ 1 - 0
AnKi/Core/NativeWindow.h

@@ -29,6 +29,7 @@ public:
 	static const Bool m_doubleBuffer = true;
 	static const Bool m_doubleBuffer = true;
 	/// Create a fullscreen window with the desktop's resolution
 	/// Create a fullscreen window with the desktop's resolution
 	Bool m_fullscreenDesktopRez = false;
 	Bool m_fullscreenDesktopRez = false;
+	Bool m_exclusiveFullscreen = false;
 
 
 	CString m_title = "AnKi";
 	CString m_title = "AnKi";
 };
 };

+ 9 - 14
AnKi/Core/NativeWindowSdl.cpp

@@ -80,19 +80,6 @@ Error NativeWindowSdl::init(const NativeWindowInitInfo& init)
 	//
 	//
 	ANKI_CORE_LOGI("Creating SDL window. SDL version %u.%u", SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
 	ANKI_CORE_LOGI("Creating SDL window. SDL version %u.%u", SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
 
 
-#if ANKI_GR_BACKEND_GL
-	if(SDL_GL_SetAttribute(SDL_GL_RED_SIZE, init.m_rgbaBits[0])
-	   || SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, init.m_rgbaBits[1])
-	   || SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, init.m_rgbaBits[2])
-	   || SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, init.m_rgbaBits[3])
-	   || SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, init.m_depthBits)
-	   || SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, init.m_doubleBuffer))
-	{
-		ANKI_CORE_LOGE("SDL_GL_SetAttribute() failed");
-		return Error::FUNCTION_FAILED;
-	}
-#endif
-
 	//
 	//
 	// Create window
 	// Create window
 	//
 	//
@@ -104,9 +91,17 @@ Error NativeWindowSdl::init(const NativeWindowInitInfo& init)
 	flags |= SDL_WINDOW_VULKAN;
 	flags |= SDL_WINDOW_VULKAN;
 #endif
 #endif
 
 
+	SDL_SetHint(SDL_HINT_ALLOW_TOPMOST, "0");
 	if(init.m_fullscreenDesktopRez)
 	if(init.m_fullscreenDesktopRez)
 	{
 	{
-		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+#if ANKI_OS_WINDOWS
+		flags |= SDL_WINDOW_FULLSCREEN;
+#endif
+
+		if(init.m_exclusiveFullscreen)
+		{
+			flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+		}
 
 
 		// Alter the window size
 		// Alter the window size
 		SDL_DisplayMode mode;
 		SDL_DisplayMode mode;

+ 19 - 14
AnKi/Gr/CMakeLists.txt

@@ -1,17 +1,14 @@
-set(COMMON
+set(common_sources
 	"Common.cpp"
 	"Common.cpp"
 	"GrObject.cpp"
 	"GrObject.cpp"
 	"RenderGraph.cpp"
 	"RenderGraph.cpp"
 	"ShaderProgram.cpp"
 	"ShaderProgram.cpp"
+	"Enums.cpp"
 	"Utils/FrameGpuAllocator.cpp"
 	"Utils/FrameGpuAllocator.cpp"
 	"Utils/Functions.cpp")
 	"Utils/Functions.cpp")
 
 
-foreach(S ${COMMON})
-	anki_add_source_files("${CMAKE_CURRENT_SOURCE_DIR}/${S}")
-endforeach()
-
 if(VULKAN)
 if(VULKAN)
-	set(VKCPP
+	set(backend_sources
 		"Vulkan/AccelerationStructure.cpp"
 		"Vulkan/AccelerationStructure.cpp"
 		"Vulkan/AccelerationStructureImpl.cpp"
 		"Vulkan/AccelerationStructureImpl.cpp"
 		"Vulkan/Buffer.cpp"
 		"Vulkan/Buffer.cpp"
@@ -48,17 +45,25 @@ if(VULKAN)
 		"Vulkan/TextureViewImpl.cpp"
 		"Vulkan/TextureViewImpl.cpp"
 		"Vulkan/TimestampQuery.cpp"
 		"Vulkan/TimestampQuery.cpp"
 		"Vulkan/TimestampQueryImpl.cpp"
 		"Vulkan/TimestampQueryImpl.cpp"
-		"Vulkan/VulkanObject.cpp")
+		"Vulkan/VulkanObject.cpp"
+		"Vulkan/FrameGarbageCollector.cpp")
 
 
 	if(ANKI_HEADLESS)
 	if(ANKI_HEADLESS)
-		set(VKCPP ${VKCPP} "Vulkan/GrManagerImplHeadless.cpp")
+		set(backend_sources ${backend_sources} "Vulkan/GrManagerImplHeadless.cpp")
 	elseif(SDL)
 	elseif(SDL)
-		set(VKCPP ${VKCPP} "Vulkan/GrManagerImplSdl.cpp")
+		set(backend_sources ${backend_sources} "Vulkan/GrManagerImplSdl.cpp")
 	elseif(ANDROID)
 	elseif(ANDROID)
-		set(VKCPP ${VKCPP} "Vulkan/GrManagerImplAndroid.cpp")
+		set(backend_sources ${backend_sources} "Vulkan/GrManagerImplAndroid.cpp")
 	endif()
 	endif()
-
-	foreach(S ${VKCPP})
-		anki_add_source_files("${CMAKE_CURRENT_SOURCE_DIR}/${S}")
-	endforeach()
 endif()
 endif()
+
+# Have 2 libraries. The AnKiGrCommon is the bare minimum for the AnKiShaderCompiler to work. Don't have
+# AnKiShaderCompiler depend on what AnKiGr depends on
+
+add_library(AnKiGrCommon ${common_sources})
+target_compile_definitions(AnKiGrCommon PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiGrCommon AnKiUtil) # Only depend on Util
+
+add_library(AnKiGr ${backend_sources})
+target_compile_definitions(AnKiGr PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiGr AnKiCore AnKiSpirvCross AnKiGrCommon)

+ 0 - 3
AnKi/Gr/CommandBuffer.h

@@ -446,9 +446,6 @@ public:
 	void pushSecondLevelCommandBuffer(CommandBufferPtr cmdb);
 	void pushSecondLevelCommandBuffer(CommandBufferPtr cmdb);
 
 
 	Bool isEmpty() const;
 	Bool isEmpty() const;
-
-	/// The command buffer will co-own a pointer. Useful to track the lifetime of bindless resources.
-	void addReference(GrObjectPtr ptr);
 	/// @}
 	/// @}
 
 
 protected:
 protected:

+ 5 - 2
AnKi/Gr/Common.h

@@ -39,7 +39,7 @@ class AccelerationStructureInitInfo;
 // Some constants
 // Some constants
 constexpr U32 MAX_VERTEX_ATTRIBUTES = 8;
 constexpr U32 MAX_VERTEX_ATTRIBUTES = 8;
 constexpr U32 MAX_COLOR_ATTACHMENTS = 4;
 constexpr U32 MAX_COLOR_ATTACHMENTS = 4;
-constexpr U32 MAX_DESCRIPTOR_SETS = 2; ///< Groups that can be bound at the same time.
+constexpr U32 MAX_DESCRIPTOR_SETS = 3; ///< Groups that can be bound at the same time.
 constexpr U32 MAX_BINDINGS_PER_DESCRIPTOR_SET = 32;
 constexpr U32 MAX_BINDINGS_PER_DESCRIPTOR_SET = 32;
 constexpr U32 MAX_FRAMES_IN_FLIGHT = 3; ///< Triple buffering.
 constexpr U32 MAX_FRAMES_IN_FLIGHT = 3; ///< Triple buffering.
 constexpr U32 MAX_GR_OBJECT_NAME_LENGTH = 31;
 constexpr U32 MAX_GR_OBJECT_NAME_LENGTH = 31;
@@ -138,6 +138,9 @@ public:
 	/// Max push constant size.
 	/// Max push constant size.
 	PtrSize m_pushConstantsSize = 128;
 	PtrSize m_pushConstantsSize = 128;
 
 
+	/// The max combined size of shared variables (with paddings) in compute shaders.
+	PtrSize m_computeSharedMemorySize = 16_KB;
+
 	/// Each SBT record should be a multiple of this.
 	/// Each SBT record should be a multiple of this.
 	U32 m_sbtRecordAlignment = MAX_U32;
 	U32 m_sbtRecordAlignment = MAX_U32;
 
 
@@ -179,7 +182,7 @@ public:
 };
 };
 ANKI_END_PACKED_STRUCT
 ANKI_END_PACKED_STRUCT
 static_assert(sizeof(GpuDeviceCapabilities)
 static_assert(sizeof(GpuDeviceCapabilities)
-				  == sizeof(PtrSize) * 4 + sizeof(U32) * 7 + sizeof(U8) * 3 + sizeof(Bool) * 6,
+				  == sizeof(PtrSize) * 5 + sizeof(U32) * 7 + sizeof(U8) * 3 + sizeof(Bool) * 6,
 			  "Should be packed");
 			  "Should be packed");
 
 
 /// The type of the allocator for heap allocations
 /// The type of the allocator for heap allocations

+ 54 - 0
AnKi/Gr/Enums.cpp

@@ -0,0 +1,54 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Gr/Enums.h>
+#include <AnKi/Math.h>
+
+namespace anki {
+
+/// @warning Don't use Array because the compilers can't handle it for some reason.
+static constexpr ShaderVariableDataTypeInfo SVD_INFOS[] = {
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
+	{ANKI_STRINGIZE(type), sizeof(type), false, isIntagralType},
+#define ANKI_SVDT_MACRO_OPAQUE(capital, type) {ANKI_STRINGIZE(type), MAX_U32, true, false},
+#include <AnKi/Gr/ShaderVariableDataType.defs.h>
+#undef ANKI_SVDT_MACRO
+#undef ANKI_SVDT_MACRO_OPAQUE
+};
+
+const ShaderVariableDataTypeInfo& getShaderVariableDataTypeInfo(ShaderVariableDataType type)
+{
+	ANKI_ASSERT(type > ShaderVariableDataType::NONE && type < ShaderVariableDataType::COUNT);
+	return SVD_INFOS[U32(type) - 1];
+}
+
+FormatInfo getFormatInfo(Format fmt)
+{
+	FormatInfo out = {};
+	switch(fmt)
+	{
+#define ANKI_FORMAT_DEF(type, id, componentCount, texelSize, blockWidth, blockHeight, blockSize, shaderType, \
+						depthStencil) \
+	case Format::type: \
+		out = {componentCount, \
+			   texelSize, \
+			   blockWidth, \
+			   blockHeight, \
+			   blockSize, \
+			   shaderType, \
+			   DepthStencilAspectBit::depthStencil, \
+			   ANKI_STRINGIZE(type)}; \
+		break;
+#include <AnKi/Gr/Format.defs.h>
+#undef ANKI_FORMAT_DEF
+
+	default:
+		ANKI_ASSERT(0);
+	}
+
+	return out;
+}
+
+} // namespace anki

+ 30 - 50
AnKi/Gr/Enums.h

@@ -155,62 +155,30 @@ public:
 	U8 m_shaderType; ///< It's 0 if the shader sees it as float, 1 if uint and 2 if signed int.
 	U8 m_shaderType; ///< It's 0 if the shader sees it as float, 1 if uint and 2 if signed int.
 	DepthStencilAspectBit m_depthStencil; ///< Depth/stencil mask.
 	DepthStencilAspectBit m_depthStencil; ///< Depth/stencil mask.
 	const char* m_name;
 	const char* m_name;
-};
 
 
-/// Get info for a specific Format.
-inline FormatInfo getFormatInfo(Format fmt)
-{
-	ANKI_ASSERT(fmt != Format::NONE);
-	FormatInfo out;
-	switch(fmt)
+	Bool isDepthStencil() const
 	{
 	{
-#define ANKI_FORMAT_DEF(type, id, componentCount, texelSize, blockWidth, blockHeight, blockSize, shaderType, \
-						depthStencil) \
-	case Format::type: \
-		out.m_componentCount = componentCount; \
-		out.m_texelSize = texelSize; \
-		out.m_blockWidth = blockWidth; \
-		out.m_blockHeight = blockHeight; \
-		out.m_blockSize = blockSize; \
-		out.m_shaderType = shaderType; \
-		out.m_depthStencil = DepthStencilAspectBit::depthStencil; \
-		out.m_name = #type; \
-		break;
-#include <AnKi/Gr/Format.defs.h>
-#undef ANKI_FORMAT_DEF
-
-	default:
-		ANKI_ASSERT(0);
-		out = {};
+		return m_depthStencil != DepthStencilAspectBit::NONE;
 	}
 	}
 
 
-	return out;
-}
-
-inline Bool formatIsDepthStencil(const Format fmt)
-{
-	return getFormatInfo(fmt).m_depthStencil != DepthStencilAspectBit::NONE;
-}
-
-inline Bool formatIsDepth(const Format fmt)
-{
-	return !!(getFormatInfo(fmt).m_depthStencil & DepthStencilAspectBit::DEPTH);
-}
+	Bool isDepth() const
+	{
+		return !!(m_depthStencil & DepthStencilAspectBit::DEPTH);
+	}
 
 
-inline Bool formatIsStencil(const Format fmt)
-{
-	return !!(getFormatInfo(fmt).m_depthStencil & DepthStencilAspectBit::STENCIL);
-}
+	Bool isStencil() const
+	{
+		return !!(m_depthStencil & DepthStencilAspectBit::STENCIL);
+	}
 
 
-inline Bool formatIsCompressed(const Format fmt)
-{
-	return getFormatInfo(fmt).m_blockSize > 0;
-}
+	Bool isCompressed() const
+	{
+		return m_blockSize > 0;
+	}
+};
 
 
-inline DepthStencilAspectBit computeFormatAspect(const Format fmt)
-{
-	return getFormatInfo(fmt).m_depthStencil;
-}
+/// Get info for a specific Format.
+ANKI_PURE FormatInfo getFormatInfo(Format fmt);
 
 
 /// Texture type.
 /// Texture type.
 enum class TextureType : U8
 enum class TextureType : U8
@@ -348,13 +316,14 @@ enum class ShaderVariableDataType : U8
 {
 {
 	NONE,
 	NONE,
 
 
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) capital,
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) capital,
 #define ANKI_SVDT_MACRO_OPAQUE(capital, type) capital,
 #define ANKI_SVDT_MACRO_OPAQUE(capital, type) capital,
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #undef ANKI_SVDT_MACRO
 #undef ANKI_SVDT_MACRO
 #undef ANKI_SVDT_MACRO_OPAQUE
 #undef ANKI_SVDT_MACRO_OPAQUE
 
 
 	// Derived
 	// Derived
+	COUNT,
 
 
 	NUMERICS_FIRST = I32,
 	NUMERICS_FIRST = I32,
 	NUMERICS_LAST = MAT4,
 	NUMERICS_LAST = MAT4,
@@ -379,6 +348,17 @@ enum class ShaderVariableDataType : U8
 };
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderVariableDataType)
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(ShaderVariableDataType)
 
 
+class ShaderVariableDataTypeInfo
+{
+public:
+	const Char* m_name;
+	U32 m_size; ///< Size of the type.
+	Bool m_opaque;
+	Bool m_isIntegral; ///< If true is integral type. Else it's float.
+};
+
+ANKI_PURE const ShaderVariableDataTypeInfo& getShaderVariableDataTypeInfo(ShaderVariableDataType type);
+
 /// Occlusion query result bit.
 /// Occlusion query result bit.
 enum class OcclusionQueryResultBit : U8
 enum class OcclusionQueryResultBit : U8
 {
 {

+ 39 - 38
AnKi/Gr/ShaderVariableDataType.defs.h

@@ -5,51 +5,52 @@
 
 
 // ShaderVariableDataType defines
 // ShaderVariableDataType defines
 
 
-// ANKI_SVDT_MACRO(capital, varType, baseType, rowCount, columnCount)
+// ANKI_SVDT_MACRO(capital, varType, baseType, rowCount, columnCount, isIntegralType)
 #if defined(ANKI_SVDT_MACRO)
 #if defined(ANKI_SVDT_MACRO)
-ANKI_SVDT_MACRO(I8, I8, I8, 1, 1)
-ANKI_SVDT_MACRO(U8, U8, U8, 1, 1)
-ANKI_SVDT_MACRO(I16, I16, I16, 1, 1)
-ANKI_SVDT_MACRO(U16, U16, U16, 1, 1)
-ANKI_SVDT_MACRO(I32, I32, I32, 1, 1)
-ANKI_SVDT_MACRO(U32, U32, U32, 1, 1)
-ANKI_SVDT_MACRO(I64, I64, I64, 1, 1)
-ANKI_SVDT_MACRO(U64, U64, U64, 1, 1)
-ANKI_SVDT_MACRO(F16, F16, F16, 1, 1)
-ANKI_SVDT_MACRO(F32, F32, F32, 1, 1)
+ANKI_SVDT_MACRO(I8, I8, I8, 1, 1, true)
+ANKI_SVDT_MACRO(U8, U8, U8, 1, 1, true)
+ANKI_SVDT_MACRO(I16, I16, I16, 1, 1, true)
+ANKI_SVDT_MACRO(U16, U16, U16, 1, 1, true)
+ANKI_SVDT_MACRO(I32, I32, I32, 1, 1, true)
+ANKI_SVDT_MACRO(U32, U32, U32, 1, 1, true)
+ANKI_SVDT_MACRO(I64, I64, I64, 1, 1, true)
+ANKI_SVDT_MACRO(U64, U64, U64, 1, 1, true)
+ANKI_SVDT_MACRO(F16, F16, F16, 1, 1, false)
+ANKI_SVDT_MACRO(F32, F32, F32, 1, 1, false)
 
 
-ANKI_SVDT_MACRO(I8VEC2, I8Vec2, I8, 2, 1)
-ANKI_SVDT_MACRO(U8VEC2, U8Vec2, U8, 2, 1)
-ANKI_SVDT_MACRO(I16VEC2, I16Vec2, I16, 2, 1)
-ANKI_SVDT_MACRO(U16VEC2, U16Vec2, U16, 2, 1)
-ANKI_SVDT_MACRO(IVEC2, IVec2, I32, 2, 1)
-ANKI_SVDT_MACRO(UVEC2, UVec2, U32, 2, 1)
-ANKI_SVDT_MACRO(HVEC2, HVec2, F16, 2, 1)
-ANKI_SVDT_MACRO(VEC2, Vec2, F32, 2, 1)
+ANKI_SVDT_MACRO(I8VEC2, I8Vec2, I8, 2, 1, true)
+ANKI_SVDT_MACRO(U8VEC2, U8Vec2, U8, 2, 1, true)
+ANKI_SVDT_MACRO(I16VEC2, I16Vec2, I16, 2, 1, true)
+ANKI_SVDT_MACRO(U16VEC2, U16Vec2, U16, 2, 1, true)
+ANKI_SVDT_MACRO(IVEC2, IVec2, I32, 2, 1, true)
+ANKI_SVDT_MACRO(UVEC2, UVec2, U32, 2, 1, true)
+ANKI_SVDT_MACRO(HVEC2, HVec2, F16, 2, 1, false)
+ANKI_SVDT_MACRO(VEC2, Vec2, F32, 2, 1, false)
 
 
-ANKI_SVDT_MACRO(I8VEC3, I8Vec3, I8, 3, 1)
-ANKI_SVDT_MACRO(U8VEC3, U8Vec3, U8, 3, 1)
-ANKI_SVDT_MACRO(I16VEC3, I16Vec3, I16, 3, 1)
-ANKI_SVDT_MACRO(U16VEC3, U16Vec3, U16, 3, 1)
-ANKI_SVDT_MACRO(IVEC3, IVec3, I32, 3, 1)
-ANKI_SVDT_MACRO(UVEC3, UVec3, U32, 3, 1)
-ANKI_SVDT_MACRO(HVEC3, HVec3, F16, 3, 1)
-ANKI_SVDT_MACRO(VEC3, Vec3, F32, 3, 1)
+ANKI_SVDT_MACRO(I8VEC3, I8Vec3, I8, 3, 1, true)
+ANKI_SVDT_MACRO(U8VEC3, U8Vec3, U8, 3, 1, true)
+ANKI_SVDT_MACRO(I16VEC3, I16Vec3, I16, 3, 1, true)
+ANKI_SVDT_MACRO(U16VEC3, U16Vec3, U16, 3, 1, true)
+ANKI_SVDT_MACRO(IVEC3, IVec3, I32, 3, 1, true)
+ANKI_SVDT_MACRO(UVEC3, UVec3, U32, 3, 1, true)
+ANKI_SVDT_MACRO(HVEC3, HVec3, F16, 3, 1, false)
+ANKI_SVDT_MACRO(VEC3, Vec3, F32, 3, 1, false)
 
 
-ANKI_SVDT_MACRO(I8VEC4, I8Vec4, I8, 4, 1)
-ANKI_SVDT_MACRO(U8VEC4, U8Vec4, U8, 4, 1)
-ANKI_SVDT_MACRO(I16VEC4, I16Vec4, I16, 4, 1)
-ANKI_SVDT_MACRO(U16VEC4, U16Vec4, U16, 4, 1)
-ANKI_SVDT_MACRO(IVEC4, IVec4, I32, 4, 1)
-ANKI_SVDT_MACRO(UVEC4, UVec4, U32, 4, 1)
-ANKI_SVDT_MACRO(HVEC4, HVec4, F16, 4, 1)
-ANKI_SVDT_MACRO(VEC4, Vec4, F32, 4, 1)
+ANKI_SVDT_MACRO(I8VEC4, I8Vec4, I8, 4, 1, true)
+ANKI_SVDT_MACRO(U8VEC4, U8Vec4, U8, 4, 1, true)
+ANKI_SVDT_MACRO(I16VEC4, I16Vec4, I16, 4, 1, true)
+ANKI_SVDT_MACRO(U16VEC4, U16Vec4, U16, 4, 1, true)
+ANKI_SVDT_MACRO(IVEC4, IVec4, I32, 4, 1, true)
+ANKI_SVDT_MACRO(UVEC4, UVec4, U32, 4, 1, true)
+ANKI_SVDT_MACRO(HVEC4, HVec4, F16, 4, 1, false)
+ANKI_SVDT_MACRO(VEC4, Vec4, F32, 4, 1, false)
 
 
-ANKI_SVDT_MACRO(MAT3, Mat3, F32, 3, 3)
-ANKI_SVDT_MACRO(MAT3X4, Mat3x4, F32, 3, 4)
-ANKI_SVDT_MACRO(MAT4, Mat4, F32, 4, 4)
+ANKI_SVDT_MACRO(MAT3, Mat3, F32, 3, 3, false)
+ANKI_SVDT_MACRO(MAT3X4, Mat3x4, F32, 3, 4, false)
+ANKI_SVDT_MACRO(MAT4, Mat4, F32, 4, 4, false)
 #endif
 #endif
 
 
+// ANKI_SVDT_MACRO_OPAQUE(capital, varType)
 #if defined(ANKI_SVDT_MACRO_OPAQUE)
 #if defined(ANKI_SVDT_MACRO_OPAQUE)
 ANKI_SVDT_MACRO_OPAQUE(TEXTURE_1D, texture1D)
 ANKI_SVDT_MACRO_OPAQUE(TEXTURE_1D, texture1D)
 ANKI_SVDT_MACRO_OPAQUE(TEXTURE_1D_ARRAY, texture1DArray)
 ANKI_SVDT_MACRO_OPAQUE(TEXTURE_1D_ARRAY, texture1DArray)

+ 1 - 3
AnKi/Gr/Texture.h

@@ -24,7 +24,6 @@ public:
 	Format m_format = Format::NONE;
 	Format m_format = Format::NONE;
 
 
 	TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
 	TextureUsageBit m_usage = TextureUsageBit::NONE; ///< How the texture will be used.
-	TextureUsageBit m_initialUsage = TextureUsageBit::NONE; ///< Its initial usage.
 	TextureType m_type = TextureType::_2D;
 	TextureType m_type = TextureType::_2D;
 
 
 	U8 m_mipmapCount = 1;
 	U8 m_mipmapCount = 1;
@@ -47,8 +46,7 @@ public:
 		const U size = U(last - first);
 		const U size = U(last - first);
 		ANKI_ASSERT(size
 		ANKI_ASSERT(size
 					== sizeof(m_width) + sizeof(m_height) + sizeof(m_depth) + sizeof(m_layerCount) + sizeof(m_format)
 					== sizeof(m_width) + sizeof(m_height) + sizeof(m_depth) + sizeof(m_layerCount) + sizeof(m_format)
-						   + sizeof(m_usage) + sizeof(m_initialUsage) + sizeof(m_type) + sizeof(m_mipmapCount)
-						   + sizeof(m_samples));
+						   + sizeof(m_usage) + sizeof(m_type) + sizeof(m_mipmapCount) + sizeof(m_samples));
 		return anki::computeHash(first, size);
 		return anki::computeHash(first, size);
 	}
 	}
 
 

+ 1 - 1
AnKi/Gr/TextureView.h

@@ -31,7 +31,7 @@ public:
 		m_faceCount =
 		m_faceCount =
 			(tex->getTextureType() == TextureType::CUBE_ARRAY || tex->getTextureType() == TextureType::CUBE) ? 6 : 1;
 			(tex->getTextureType() == TextureType::CUBE_ARRAY || tex->getTextureType() == TextureType::CUBE) ? 6 : 1;
 
 
-		m_depthStencilAspect = computeFormatAspect(tex->getFormat());
+		m_depthStencilAspect = getFormatInfo(tex->getFormat()).m_depthStencil;
 	}
 	}
 
 
 	TextureViewInitInfo(CString name = {})
 	TextureViewInitInfo(CString name = {})

+ 2 - 25
AnKi/Gr/Utils/Functions.cpp

@@ -86,7 +86,7 @@ public:
 	static constexpr Bool VALUE = false;
 	static constexpr Bool VALUE = false;
 };
 };
 
 
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
 	template<> \
 	template<> \
 	class IsShaderVarDataTypeAMatrix<type> \
 	class IsShaderVarDataTypeAMatrix<type> \
 	{ \
 	{ \
@@ -126,7 +126,7 @@ void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlo
 {
 {
 	switch(type)
 	switch(type)
 	{
 	{
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
 	case ShaderVariableDataType::capital: \
 	case ShaderVariableDataType::capital: \
 		WriteShaderBlockMemory<type>()(varBlkInfo, elements, elementsCount, buffBegin, buffEnd); \
 		WriteShaderBlockMemory<type>()(varBlkInfo, elements, elementsCount, buffBegin, buffEnd); \
 		break;
 		break;
@@ -138,27 +138,4 @@ void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlo
 	}
 	}
 }
 }
 
 
-const CString shaderVariableDataTypeToString(ShaderVariableDataType t)
-{
-	switch(t)
-	{
-	case ShaderVariableDataType::NONE:
-		return "NONE";
-
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
-	case ShaderVariableDataType::capital: \
-		return ANKI_STRINGIZE(type);
-#define ANKI_SVDT_MACRO_OPAQUE(capital, type) ANKI_SVDT_MACRO(capital, type, 0, 0, 0)
-#include <AnKi/Gr/ShaderVariableDataType.defs.h>
-#undef ANKI_SVDT_MACRO
-#undef ANKI_SVDT_MACRO_OPAQUE
-
-	default:
-		ANKI_ASSERT(0);
-	}
-
-	ANKI_ASSERT(0);
-	return "";
-}
-
 } // end namespace anki
 } // end namespace anki

+ 1 - 4
AnKi/Gr/Utils/Functions.h

@@ -31,7 +31,7 @@ inline Bool blendingDisabled(BlendFactor srcFactorRgb, BlendFactor dstFactorRgb,
 template<typename T>
 template<typename T>
 ShaderVariableDataType getShaderVariableTypeFromTypename();
 ShaderVariableDataType getShaderVariableTypeFromTypename();
 
 
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
 	template<> \
 	template<> \
 	inline ShaderVariableDataType getShaderVariableTypeFromTypename<type>() \
 	inline ShaderVariableDataType getShaderVariableTypeFromTypename<type>() \
 	{ \
 	{ \
@@ -45,7 +45,4 @@ ShaderVariableDataType getShaderVariableTypeFromTypename();
 void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo,
 void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo,
 							const void* elements, U32 elementsCount, void* buffBegin, const void* buffEnd);
 							const void* elements, U32 elementsCount, void* buffBegin, const void* buffEnd);
 
 
-/// Convert a ShaderVariableDataType to string.
-const CString shaderVariableDataTypeToString(ShaderVariableDataType t);
-
 } // end namespace anki
 } // end namespace anki

+ 4 - 9
AnKi/Gr/Vulkan/BufferImpl.cpp

@@ -12,15 +12,10 @@ BufferImpl::~BufferImpl()
 {
 {
 	ANKI_ASSERT(!m_mapped);
 	ANKI_ASSERT(!m_mapped);
 
 
-	if(m_handle)
-	{
-		vkDestroyBuffer(getDevice(), m_handle, nullptr);
-	}
-
-	if(m_memHandle)
-	{
-		getGrManagerImpl().getGpuMemoryManager().freeMemory(m_memHandle);
-	}
+	BufferGarbage* garbage = getAllocator().newInstance<BufferGarbage>();
+	garbage->m_bufferHandle = m_handle;
+	garbage->m_memoryHandle = m_memHandle;
+	getGrManagerImpl().getFrameGarbageCollector().newBufferGarbage(garbage);
 
 
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	if(m_needsFlush && m_flushCount.load() == 0)
 	if(m_needsFlush && m_flushCount.load() == 0)

+ 0 - 6
AnKi/Gr/Vulkan/CommandBuffer.cpp

@@ -451,10 +451,4 @@ void CommandBuffer::setLineWidth(F32 width)
 	self.setLineWidth(width);
 	self.setLineWidth(width);
 }
 }
 
 
-void CommandBuffer::addReference(GrObjectPtr ptr)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	self.addReference(ptr);
-}
-
 } // end namespace anki
 } // end namespace anki

+ 45 - 126
AnKi/Gr/Vulkan/CommandBufferFactory.cpp

@@ -23,7 +23,7 @@ static VulkanQueueType getQueueTypeFromCommandBufferFlags(CommandBufferFlag flag
 	}
 	}
 }
 }
 
 
-void MicroCommandBuffer::destroy()
+MicroCommandBuffer::~MicroCommandBuffer()
 {
 {
 	reset();
 	reset();
 
 
@@ -31,6 +31,10 @@ void MicroCommandBuffer::destroy()
 	{
 	{
 		vkFreeCommandBuffers(m_threadAlloc->m_factory->m_dev, m_threadAlloc->m_pools[m_queue], 1, &m_handle);
 		vkFreeCommandBuffers(m_threadAlloc->m_factory->m_dev, m_threadAlloc->m_pools[m_queue], 1, &m_handle);
 		m_handle = {};
 		m_handle = {};
+
+		const U32 count = m_threadAlloc->m_factory->m_createdCmdBufferCount.fetchSub(1);
+		ANKI_ASSERT(count > 0);
+		(void)count;
 	}
 	}
 }
 }
 
 
@@ -39,7 +43,7 @@ void MicroCommandBuffer::reset()
 	ANKI_TRACE_SCOPED_EVENT(VK_COMMAND_BUFFER_RESET);
 	ANKI_TRACE_SCOPED_EVENT(VK_COMMAND_BUFFER_RESET);
 
 
 	ANKI_ASSERT(m_refcount.load() == 0);
 	ANKI_ASSERT(m_refcount.load() == 0);
-	ANKI_ASSERT(!m_fence.isCreated() || m_fence->done());
+	ANKI_ASSERT(!m_fence.isCreated());
 
 
 	for(GrObjectType type : EnumIterable<GrObjectType>())
 	for(GrObjectType type : EnumIterable<GrObjectType>())
 	{
 	{
@@ -47,8 +51,6 @@ void MicroCommandBuffer::reset()
 	}
 	}
 
 
 	m_fastAlloc.getMemoryPool().reset();
 	m_fastAlloc.getMemoryPool().reset();
-
-	m_fence = {};
 }
 }
 
 
 Error CommandBufferThreadAllocator::init()
 Error CommandBufferThreadAllocator::init()
@@ -68,42 +70,35 @@ Error CommandBufferThreadAllocator::init()
 		ANKI_VK_CHECK(vkCreateCommandPool(m_factory->m_dev, &ci, nullptr, &m_pools[qtype]));
 		ANKI_VK_CHECK(vkCreateCommandPool(m_factory->m_dev, &ci, nullptr, &m_pools[qtype]));
 	}
 	}
 
 
-	return Error::NONE;
-}
-
-void CommandBufferThreadAllocator::destroyList(IntrusiveList<MicroCommandBuffer>& list)
-{
-	while(!list.isEmpty())
+	for(U32 secondLevel = 0; secondLevel < 2; ++secondLevel)
 	{
 	{
-		MicroCommandBuffer* ptr = list.popFront();
-		ptr->destroy();
-		getAllocator().deleteInstance(ptr);
-#if ANKI_EXTRA_CHECKS
-		m_createdCmdbs.fetchSub(1);
-#endif
+		for(U32 smallBatch = 0; smallBatch < 2; ++smallBatch)
+		{
+			for(VulkanQueueType queue : EnumIterable<VulkanQueueType>())
+			{
+				MicroObjectRecycler<MicroCommandBuffer>& recycler = m_recyclers[secondLevel][smallBatch][queue];
+
+				recycler.init(m_factory->m_alloc);
+			}
+		}
 	}
 	}
+
+	return Error::NONE;
 }
 }
 
 
-void CommandBufferThreadAllocator::destroyLists()
+void CommandBufferThreadAllocator::destroy()
 {
 {
-	for(U i = 0; i < 2; ++i)
+	for(U32 secondLevel = 0; secondLevel < 2; ++secondLevel)
 	{
 	{
-		for(U j = 0; j < 2; ++j)
+		for(U32 smallBatch = 0; smallBatch < 2; ++smallBatch)
 		{
 		{
-			for(VulkanQueueType qtype : EnumIterable<VulkanQueueType>())
+			for(VulkanQueueType queue : EnumIterable<VulkanQueueType>())
 			{
 			{
-				CmdbType& type = m_types[i][j][qtype];
-
-				destroyList(type.m_deletedCmdbs);
-				destroyList(type.m_readyCmdbs);
-				destroyList(type.m_inUseCmdbs);
+				m_recyclers[secondLevel][smallBatch][queue].destroy();
 			}
 			}
 		}
 		}
 	}
 	}
-}
 
 
-void CommandBufferThreadAllocator::destroy()
-{
 	for(VkCommandPool& pool : m_pools)
 	for(VkCommandPool& pool : m_pools)
 	{
 	{
 		if(pool)
 		if(pool)
@@ -112,94 +107,19 @@ void CommandBufferThreadAllocator::destroy()
 			pool = VK_NULL_HANDLE;
 			pool = VK_NULL_HANDLE;
 		}
 		}
 	}
 	}
-
-	ANKI_ASSERT(m_createdCmdbs.load() == 0 && "Someone still holds references to command buffers");
 }
 }
 
 
-Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& outPtr,
-													 Bool& createdNew)
+Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& outPtr)
 {
 {
 	ANKI_ASSERT(!!(cmdbFlags & CommandBufferFlag::COMPUTE_WORK) ^ !!(cmdbFlags & CommandBufferFlag::GENERAL_WORK));
 	ANKI_ASSERT(!!(cmdbFlags & CommandBufferFlag::COMPUTE_WORK) ^ !!(cmdbFlags & CommandBufferFlag::GENERAL_WORK));
-	createdNew = false;
 
 
 	const Bool secondLevel = !!(cmdbFlags & CommandBufferFlag::SECOND_LEVEL);
 	const Bool secondLevel = !!(cmdbFlags & CommandBufferFlag::SECOND_LEVEL);
 	const Bool smallBatch = !!(cmdbFlags & CommandBufferFlag::SMALL_BATCH);
 	const Bool smallBatch = !!(cmdbFlags & CommandBufferFlag::SMALL_BATCH);
 	const VulkanQueueType queue = getQueueTypeFromCommandBufferFlags(cmdbFlags, m_factory->m_queueFamilies);
 	const VulkanQueueType queue = getQueueTypeFromCommandBufferFlags(cmdbFlags, m_factory->m_queueFamilies);
 
 
-	CmdbType& type = m_types[secondLevel][smallBatch][queue];
+	MicroObjectRecycler<MicroCommandBuffer>& recycler = m_recyclers[secondLevel][smallBatch][queue];
 
 
-	// Move the deleted to (possibly) in-use or ready
-	{
-		LockGuard<Mutex> lock(type.m_deletedMtx);
-
-		while(!type.m_deletedCmdbs.isEmpty())
-		{
-			MicroCommandBuffer* ptr = type.m_deletedCmdbs.popFront();
-
-			if(secondLevel)
-			{
-				type.m_readyCmdbs.pushFront(ptr);
-				ptr->reset();
-			}
-			else
-			{
-				type.m_inUseCmdbs.pushFront(ptr);
-			}
-		}
-	}
-
-	// Reset the in-use command buffers and try to get one available
-	MicroCommandBuffer* out = nullptr;
-	if(!secondLevel)
-	{
-		// Primary
-
-		// Try to reuse a ready buffer
-		if(!type.m_readyCmdbs.isEmpty())
-		{
-			out = type.m_readyCmdbs.popFront();
-		}
-
-		// Do a sweep and move in-use buffers to ready
-		IntrusiveList<MicroCommandBuffer> inUseCmdbs; // Push to temporary because we are iterating
-		while(!type.m_inUseCmdbs.isEmpty())
-		{
-			MicroCommandBuffer* inUseCmdb = type.m_inUseCmdbs.popFront();
-
-			if(!inUseCmdb->m_fence.isCreated() || inUseCmdb->m_fence->done())
-			{
-				// It's ready
-
-				if(out)
-				{
-					type.m_readyCmdbs.pushFront(inUseCmdb);
-					inUseCmdb->reset();
-				}
-				else
-				{
-					out = inUseCmdb;
-				}
-			}
-			else
-			{
-				inUseCmdbs.pushBack(inUseCmdb);
-			}
-		}
-
-		ANKI_ASSERT(type.m_inUseCmdbs.isEmpty());
-		type.m_inUseCmdbs = std::move(inUseCmdbs);
-	}
-	else
-	{
-		// Secondary
-
-		ANKI_ASSERT(type.m_inUseCmdbs.isEmpty());
-
-		if(!type.m_readyCmdbs.isEmpty())
-		{
-			out = type.m_readyCmdbs.popFront();
-		}
-	}
+	MicroCommandBuffer* out = recycler.findToReuse();
 
 
 	if(ANKI_UNLIKELY(out == nullptr))
 	if(ANKI_UNLIKELY(out == nullptr))
 	{
 	{
@@ -217,10 +137,6 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 
 
 		MicroCommandBuffer* newCmdb = getAllocator().newInstance<MicroCommandBuffer>(this);
 		MicroCommandBuffer* newCmdb = getAllocator().newInstance<MicroCommandBuffer>(this);
 
 
-#if ANKI_EXTRA_CHECKS
-		m_createdCmdbs.fetchAdd(1);
-#endif
-
 		newCmdb->m_fastAlloc =
 		newCmdb->m_fastAlloc =
 			StackAllocator<U8>(m_factory->m_alloc.getMemoryPool().getAllocationCallback(),
 			StackAllocator<U8>(m_factory->m_alloc.getMemoryPool().getAllocationCallback(),
 							   m_factory->m_alloc.getMemoryPool().getAllocationCallbackUserData(), 256_KB, 2.0f);
 							   m_factory->m_alloc.getMemoryPool().getAllocationCallbackUserData(), 256_KB, 2.0f);
@@ -231,11 +147,15 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 
 
 		out = newCmdb;
 		out = newCmdb;
 
 
-		createdNew = true;
+		m_factory->m_createdCmdBufferCount.fetchAdd(1);
 	}
 	}
 	else
 	else
 	{
 	{
-		out->reset();
+		for(GrObjectType type : EnumIterable<GrObjectType>())
+		{
+			(void)type;
+			ANKI_ASSERT(out->m_objectRefs[type].getSize() == 0);
+		}
 	}
 	}
 
 
 	ANKI_ASSERT(out && out->m_refcount.load() == 0);
 	ANKI_ASSERT(out && out->m_refcount.load() == 0);
@@ -251,10 +171,7 @@ void CommandBufferThreadAllocator::deleteCommandBuffer(MicroCommandBuffer* ptr)
 	const Bool secondLevel = !!(ptr->m_flags & CommandBufferFlag::SECOND_LEVEL);
 	const Bool secondLevel = !!(ptr->m_flags & CommandBufferFlag::SECOND_LEVEL);
 	const Bool smallBatch = !!(ptr->m_flags & CommandBufferFlag::SMALL_BATCH);
 	const Bool smallBatch = !!(ptr->m_flags & CommandBufferFlag::SMALL_BATCH);
 
 
-	CmdbType& type = m_types[secondLevel][smallBatch][ptr->m_queue];
-
-	LockGuard<Mutex> lock(type.m_deletedMtx);
-	type.m_deletedCmdbs.pushBack(ptr);
+	m_recyclers[secondLevel][smallBatch][ptr->m_queue].recycle(ptr);
 }
 }
 
 
 Error CommandBufferFactory::init(GrAllocator<U8> alloc, VkDevice dev, const VulkanQueueFamilies& queueFamilies)
 Error CommandBufferFactory::init(GrAllocator<U8> alloc, VkDevice dev, const VulkanQueueFamilies& queueFamilies)
@@ -269,12 +186,19 @@ Error CommandBufferFactory::init(GrAllocator<U8> alloc, VkDevice dev, const Vulk
 
 
 void CommandBufferFactory::destroy()
 void CommandBufferFactory::destroy()
 {
 {
-	// Run 2 times because destroyLists() populates other allocators' lists
-	for(U i = 0; i < 2; ++i)
+	// First trim the caches for all recyclers. This will release the primaries and populate the recyclers of
+	// secondaries
+	for(CommandBufferThreadAllocator* talloc : m_threadAllocs)
 	{
 	{
-		for(CommandBufferThreadAllocator* alloc : m_threadAllocs)
+		for(U32 secondLevel = 0; secondLevel < 2; ++secondLevel)
 		{
 		{
-			alloc->destroyLists();
+			for(U32 smallBatch = 0; smallBatch < 2; ++smallBatch)
+			{
+				for(VulkanQueueType queue : EnumIterable<VulkanQueueType>())
+				{
+					talloc->m_recyclers[secondLevel][smallBatch][queue].trimCache();
+				}
+			}
 		}
 		}
 	}
 	}
 
 
@@ -342,12 +266,7 @@ Error CommandBufferFactory::newCommandBuffer(ThreadId tid, CommandBufferFlag cmd
 
 
 	ANKI_ASSERT(alloc);
 	ANKI_ASSERT(alloc);
 	ANKI_ASSERT(alloc->m_tid == tid);
 	ANKI_ASSERT(alloc->m_tid == tid);
-	Bool createdNew;
-	ANKI_CHECK(alloc->newCommandBuffer(cmdbFlags, ptr, createdNew));
-	if(createdNew)
-	{
-		m_createdCmdBufferCount.fetchAdd(1);
-	}
+	ANKI_CHECK(alloc->newCommandBuffer(cmdbFlags, ptr));
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }

+ 23 - 23
AnKi/Gr/Vulkan/CommandBufferFactory.h

@@ -7,6 +7,7 @@
 
 
 #include <AnKi/Gr/Vulkan/FenceFactory.h>
 #include <AnKi/Gr/Vulkan/FenceFactory.h>
 #include <AnKi/Gr/CommandBuffer.h>
 #include <AnKi/Gr/CommandBuffer.h>
+#include <AnKi/Gr/Vulkan/MicroObjectRecycler.h>
 #include <AnKi/Util/List.h>
 #include <AnKi/Util/List.h>
 
 
 namespace anki {
 namespace anki {
@@ -30,13 +31,33 @@ public:
 		ANKI_ASSERT(allocator);
 		ANKI_ASSERT(allocator);
 	}
 	}
 
 
+	~MicroCommandBuffer();
+
 	Atomic<I32>& getRefcount()
 	Atomic<I32>& getRefcount()
 	{
 	{
 		return m_refcount;
 		return m_refcount;
 	}
 	}
 
 
+	void setFence(MicroFencePtr& fence)
+	{
+		ANKI_ASSERT(!(m_flags & CommandBufferFlag::SECOND_LEVEL));
+		ANKI_ASSERT(!m_fence.isCreated());
+		m_fence = fence;
+	}
+
+	MicroFencePtr& getFence()
+	{
+		return m_fence;
+	}
+
 	GrAllocator<U8>& getAllocator();
 	GrAllocator<U8>& getAllocator();
 
 
+	/// Interface method.
+	void onFenceDone()
+	{
+		reset();
+	}
+
 	StackAllocator<U8>& getFastAllocator()
 	StackAllocator<U8>& getFastAllocator()
 	{
 	{
 		return m_fastAlloc;
 		return m_fastAlloc;
@@ -54,13 +75,6 @@ public:
 		pushToArray(m_objectRefs[T::CLASS_TYPE], x.get());
 		pushToArray(m_objectRefs[T::CLASS_TYPE], x.get());
 	}
 	}
 
 
-	void setFence(MicroFencePtr& fence)
-	{
-		ANKI_ASSERT(!(m_flags & CommandBufferFlag::SECOND_LEVEL));
-		ANKI_ASSERT(!m_fence.isCreated());
-		m_fence = fence;
-	}
-
 	CommandBufferFlag getFlags() const
 	CommandBufferFlag getFlags() const
 	{
 	{
 		return m_flags;
 		return m_flags;
@@ -88,7 +102,6 @@ private:
 	CommandBufferFlag m_flags = CommandBufferFlag::NONE;
 	CommandBufferFlag m_flags = CommandBufferFlag::NONE;
 	VulkanQueueType m_queue = VulkanQueueType::COUNT;
 	VulkanQueueType m_queue = VulkanQueueType::COUNT;
 
 
-	void destroy();
 	void reset();
 	void reset();
 
 
 	void pushToArray(DynamicArray<GrObjectPtr>& arr, GrObject* grobj)
 	void pushToArray(DynamicArray<GrObjectPtr>& arr, GrObject* grobj)
@@ -153,7 +166,7 @@ public:
 	GrAllocator<U8>& getAllocator();
 	GrAllocator<U8>& getAllocator();
 
 
 	/// Request a new command buffer.
 	/// Request a new command buffer.
-	ANKI_USE_RESULT Error newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr, Bool& createdNew);
+	ANKI_USE_RESULT Error newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
 
 
 	/// It will recycle it.
 	/// It will recycle it.
 	void deleteCommandBuffer(MicroCommandBuffer* ptr);
 	void deleteCommandBuffer(MicroCommandBuffer* ptr);
@@ -163,24 +176,11 @@ private:
 	ThreadId m_tid;
 	ThreadId m_tid;
 	Array<VkCommandPool, U(VulkanQueueType::COUNT)> m_pools = {};
 	Array<VkCommandPool, U(VulkanQueueType::COUNT)> m_pools = {};
 
 
-	class CmdbType
-	{
-	public:
-		IntrusiveList<MicroCommandBuffer> m_readyCmdbs; ///< Buffers that are ready to be used.
-		IntrusiveList<MicroCommandBuffer> m_inUseCmdbs; ///< Buffer that got dereferenced and maybe in-use.
-
-		IntrusiveList<MicroCommandBuffer> m_deletedCmdbs;
-		Mutex m_deletedMtx; ///< Lock because the dallocations may happen anywhere.
-	};
-
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	Atomic<U32> m_createdCmdbs = {0};
 	Atomic<U32> m_createdCmdbs = {0};
 #endif
 #endif
 
 
-	Array3d<CmdbType, 2, 2, U(VulkanQueueType::COUNT)> m_types;
-
-	void destroyList(IntrusiveList<MicroCommandBuffer>& list);
-	void destroyLists();
+	Array3d<MicroObjectRecycler<MicroCommandBuffer>, 2, 2, U(VulkanQueueType::COUNT)> m_recyclers;
 };
 };
 
 
 /// Command bufffer object recycler.
 /// Command bufffer object recycler.

+ 0 - 5
AnKi/Gr/Vulkan/CommandBufferImpl.h

@@ -379,11 +379,6 @@ public:
 
 
 	void setLineWidth(F32 width);
 	void setLineWidth(F32 width);
 
 
-	void addReference(GrObjectPtr& ptr)
-	{
-		m_microCmdb->pushObjectRef(ptr);
-	}
-
 private:
 private:
 	StackAllocator<U8> m_alloc;
 	StackAllocator<U8> m_alloc;
 
 

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

@@ -403,7 +403,7 @@ VkImageUsageFlags convertTextureUsage(const TextureUsageBit ak, const Format for
 
 
 	if(!!(ak & (TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE)))
 	if(!!(ak & (TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE)))
 	{
 	{
-		if(formatIsDepthStencil(format))
+		if(getFormatInfo(format).isDepthStencil())
 		{
 		{
 			out |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 			out |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 		}
 		}

+ 2 - 2
AnKi/Gr/Vulkan/Common.h

@@ -163,12 +163,12 @@ ANKI_USE_RESULT inline VkFormat convertFormat(const Format ak)
 ANKI_USE_RESULT inline DepthStencilAspectBit getImageAspectFromFormat(const Format ak)
 ANKI_USE_RESULT inline DepthStencilAspectBit getImageAspectFromFormat(const Format ak)
 {
 {
 	DepthStencilAspectBit out = DepthStencilAspectBit::NONE;
 	DepthStencilAspectBit out = DepthStencilAspectBit::NONE;
-	if(formatIsStencil(ak))
+	if(getFormatInfo(ak).isStencil())
 	{
 	{
 		out = DepthStencilAspectBit::STENCIL;
 		out = DepthStencilAspectBit::STENCIL;
 	}
 	}
 
 
-	if(formatIsDepth(ak))
+	if(getFormatInfo(ak).isDepth())
 	{
 	{
 		out |= DepthStencilAspectBit::DEPTH;
 		out |= DepthStencilAspectBit::DEPTH;
 	}
 	}

+ 6 - 0
AnKi/Gr/Vulkan/DeferredBarrierFactory.h

@@ -50,6 +50,12 @@ public:
 		return m_fence;
 		return m_fence;
 	}
 	}
 
 
+	/// Interface method.
+	void onFenceDone()
+	{
+		// Do nothing
+	}
+
 private:
 private:
 	VkEvent m_handle = VK_NULL_HANDLE;
 	VkEvent m_handle = VK_NULL_HANDLE;
 	Atomic<U32> m_refcount = {0};
 	Atomic<U32> m_refcount = {0};

+ 11 - 4
AnKi/Gr/Vulkan/DescriptorSet.cpp

@@ -193,7 +193,7 @@ U32 DescriptorSetFactory::BindlessDescriptorSet::bindTexture(const VkImageView v
 	LockGuard<Mutex> lock(m_mtx);
 	LockGuard<Mutex> lock(m_mtx);
 	ANKI_ASSERT(m_freeTexIndexCount > 0 && "Out of indices");
 	ANKI_ASSERT(m_freeTexIndexCount > 0 && "Out of indices");
 
 
-	// Get the index
+	// Pop the index
 	--m_freeTexIndexCount;
 	--m_freeTexIndexCount;
 	const U16 idx = m_freeTexIndices[m_freeTexIndexCount];
 	const U16 idx = m_freeTexIndices[m_freeTexIndexCount];
 	ANKI_ASSERT(idx < m_freeTexIndices.getSize());
 	ANKI_ASSERT(idx < m_freeTexIndices.getSize());
@@ -252,9 +252,9 @@ U32 DescriptorSetFactory::BindlessDescriptorSet::bindImage(const VkImageView vie
 void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, DynamicArray<U16>& freeIndices,
 void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, DynamicArray<U16>& freeIndices,
 															   U16& freeIndexCount)
 															   U16& freeIndexCount)
 {
 {
-	ANKI_ASSERT(idx < freeIndices.getSize());
-
 	LockGuard<Mutex> lock(m_mtx);
 	LockGuard<Mutex> lock(m_mtx);
+
+	ANKI_ASSERT(idx < freeIndices.getSize());
 	ANKI_ASSERT(freeIndexCount < freeIndices.getSize());
 	ANKI_ASSERT(freeIndexCount < freeIndices.getSize());
 
 
 	freeIndices[freeIndexCount] = U16(idx);
 	freeIndices[freeIndexCount] = U16(idx);
@@ -805,7 +805,14 @@ void DescriptorSetState::flush(U64& hash, Array<PtrSize, MAX_BINDINGS_PER_DESCRI
 	dynamicOffsetCount = 0;
 	dynamicOffsetCount = 0;
 	bindlessDSet = false;
 	bindlessDSet = false;
 
 
-	if(!m_bindlessDSetBound)
+	// There is a chance where the bindless set is bound but the actual shaders have an empty DS layout (maybe because
+	// the dead code elimination eliminated the bindless set). In that case we can't bind the bindless DS. We have to
+	// treat it as regular set
+	ANKI_ASSERT(!(m_layout.m_entry == nullptr && !m_bindlessDSetBound)
+				&& "DS layout points to bindless but no bindless is bound");
+	const Bool reallyBindless = m_bindlessDSetBound && m_layout.m_entry == nullptr;
+
+	if(!reallyBindless)
 	{
 	{
 		// Get cache entry
 		// Get cache entry
 		ANKI_ASSERT(m_layout.m_entry);
 		ANKI_ASSERT(m_layout.m_entry);

+ 156 - 0
AnKi/Gr/Vulkan/FrameGarbageCollector.cpp

@@ -0,0 +1,156 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Gr/Vulkan/FrameGarbageCollector.h>
+#include <AnKi/Gr/Vulkan/GrManagerImpl.h>
+#include <AnKi/Gr/Fence.h>
+
+namespace anki {
+
+FrameGarbageCollector::~FrameGarbageCollector()
+{
+	destroy();
+}
+
+void FrameGarbageCollector::collectGarbage()
+{
+	if(ANKI_LIKELY(m_frames.isEmpty()))
+	{
+		return;
+	}
+
+	const VkDevice dev = m_gr->getDevice();
+	GrAllocator<U8> alloc = m_gr->getAllocator();
+
+	IntrusiveList<FrameGarbage> newFrames;
+	while(!m_frames.isEmpty())
+	{
+		FrameGarbage& frame = *m_frames.popFront();
+
+		if(frame.m_fence.isCreated() && !frame.m_fence->done())
+		{
+			ANKI_ASSERT(!frame.m_textureGarbage.isEmpty() || !frame.m_bufferGarbage.isEmpty());
+			newFrames.pushBack(&frame);
+			continue;
+		}
+
+		// Frame is done, dispose garbage and destroy it
+
+		// Dispose texture garbage
+		while(!frame.m_textureGarbage.isEmpty())
+		{
+			TextureGarbage* textureGarbage = frame.m_textureGarbage.popBack();
+
+			for(VkImageView viewHandle : textureGarbage->m_viewHandles)
+			{
+				vkDestroyImageView(dev, viewHandle, nullptr);
+			}
+			textureGarbage->m_viewHandles.destroy(alloc);
+
+			for(U32 bindlessIndex : textureGarbage->m_bindlessIndices)
+			{
+				m_gr->getDescriptorSetFactory().unbindBindlessTexture(bindlessIndex);
+			}
+			textureGarbage->m_bindlessIndices.destroy(alloc);
+
+			if(textureGarbage->m_imageHandle)
+			{
+				vkDestroyImage(dev, textureGarbage->m_imageHandle, nullptr);
+			}
+
+			if(textureGarbage->m_memoryHandle)
+			{
+				m_gr->getGpuMemoryManager().freeMemory(textureGarbage->m_memoryHandle);
+			}
+
+			alloc.deleteInstance(textureGarbage);
+		}
+
+		// Dispose buffer garbage
+		while(!frame.m_bufferGarbage.isEmpty())
+		{
+			BufferGarbage* bufferGarbage = frame.m_bufferGarbage.popBack();
+
+			if(bufferGarbage->m_bufferHandle)
+			{
+				vkDestroyBuffer(dev, bufferGarbage->m_bufferHandle, nullptr);
+			}
+
+			if(bufferGarbage->m_memoryHandle)
+			{
+				m_gr->getGpuMemoryManager().freeMemory(bufferGarbage->m_memoryHandle);
+			}
+
+			alloc.deleteInstance(bufferGarbage);
+		}
+
+		alloc.deleteInstance(&frame);
+	}
+
+	m_frames = std::move(newFrames);
+}
+
+FrameGarbageCollector::FrameGarbage& FrameGarbageCollector::getFrame()
+{
+	if(!m_frames.isEmpty() && !m_frames.getBack().m_fence.isCreated())
+	{
+		// Do nothing
+	}
+	else
+	{
+		FrameGarbage* newGarbage = m_gr->getAllocator().newInstance<FrameGarbage>();
+		m_frames.pushBack(newGarbage);
+	}
+
+	return m_frames.getBack();
+}
+
+void FrameGarbageCollector::setNewFrame(MicroFencePtr frameFence)
+{
+	ANKI_ASSERT(frameFence.isCreated());
+
+	LockGuard<Mutex> lock(m_mtx);
+	ANKI_ASSERT(m_initialized);
+
+	if(!m_frames.isEmpty() && !m_frames.getBack().m_fence.isCreated())
+	{
+		// Last frame is without a fence, asign the fence to not not have it garbage collected
+		m_frames.getBack().m_fence = frameFence;
+	}
+
+	collectGarbage();
+}
+
+void FrameGarbageCollector::newTextureGarbage(TextureGarbage* textureGarbage)
+{
+	ANKI_ASSERT(textureGarbage);
+	LockGuard<Mutex> lock(m_mtx);
+	ANKI_ASSERT(m_initialized);
+	FrameGarbage& frame = getFrame();
+	frame.m_textureGarbage.pushBack(textureGarbage);
+}
+
+void FrameGarbageCollector::newBufferGarbage(BufferGarbage* bufferGarbage)
+{
+	ANKI_ASSERT(bufferGarbage);
+	LockGuard<Mutex> lock(m_mtx);
+	ANKI_ASSERT(m_initialized);
+	FrameGarbage& frame = getFrame();
+	frame.m_bufferGarbage.pushBack(bufferGarbage);
+}
+
+void FrameGarbageCollector::destroy()
+{
+	LockGuard<Mutex> lock(m_mtx);
+
+	collectGarbage();
+	ANKI_ASSERT(m_frames.isEmpty());
+
+#if ANKI_EXTRA_CHECKS
+	m_initialized = false;
+#endif
+}
+
+} // end namespace anki

+ 90 - 0
AnKi/Gr/Vulkan/FrameGarbageCollector.h

@@ -0,0 +1,90 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/Gr/Vulkan/Common.h>
+#include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
+#include <AnKi/Gr/Vulkan/FenceFactory.h>
+#include <AnKi/Util/DynamicArray.h>
+#include <AnKi/Util/List.h>
+
+namespace anki {
+
+/// @addtogroup vulkan
+/// @{
+
+/// @memberof FrameGarbageCollector
+class TextureGarbage : public IntrusiveListEnabled<TextureGarbage>
+{
+public:
+	DynamicArray<VkImageView> m_viewHandles;
+	DynamicArray<U32> m_bindlessIndices;
+	VkImage m_imageHandle = VK_NULL_HANDLE;
+	GpuMemoryHandle m_memoryHandle;
+};
+
+/// @memberof FrameGarbageCollector
+class BufferGarbage : public IntrusiveListEnabled<BufferGarbage>
+{
+public:
+	VkBuffer m_bufferHandle = VK_NULL_HANDLE;
+	GpuMemoryHandle m_memoryHandle;
+};
+
+/// This class gathers various garbages and disposes them when in some later frame where it is safe to do so. This is
+/// used on bindless textures and buffers where we have to wait until the frame where they were deleted is done.
+class FrameGarbageCollector
+{
+public:
+	FrameGarbageCollector() = default;
+
+	~FrameGarbageCollector();
+
+	void init(GrManagerImpl* gr)
+	{
+		m_gr = gr;
+#if ANKI_EXTRA_CHECKS
+		m_initialized = true;
+#endif
+	}
+
+	void destroy();
+
+	/// Sets a new frame and collects garbage as well.
+	/// @note It's thread-safe.
+	void setNewFrame(MicroFencePtr frameFence);
+
+	/// @note It's thread-safe.
+	void newTextureGarbage(TextureGarbage* textureGarbage);
+
+	/// @note It's thread-safe.
+	void newBufferGarbage(BufferGarbage* bufferGarbage);
+
+private:
+	class FrameGarbage : public IntrusiveListEnabled<FrameGarbage>
+	{
+	public:
+		IntrusiveList<TextureGarbage> m_textureGarbage;
+		IntrusiveList<BufferGarbage> m_bufferGarbage;
+		MicroFencePtr m_fence;
+	};
+
+	GrManagerImpl* m_gr = nullptr;
+
+	Mutex m_mtx;
+	IntrusiveList<FrameGarbage> m_frames;
+
+#if ANKI_EXTRA_CHECKS
+	Bool m_initialized = false;
+#endif
+
+	void collectGarbage();
+
+	FrameGarbage& getFrame();
+};
+/// @}
+
+} // end namespace anki

+ 55 - 32
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -12,7 +12,6 @@
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
-#include <glslang/Public/ShaderLang.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -40,9 +39,9 @@ GrManagerImpl::~GrManagerImpl()
 		}
 		}
 	}
 	}
 
 
+	// 3rd THING: The destroy everything that has a reference to GrObjects.
 	m_cmdbFactory.destroy();
 	m_cmdbFactory.destroy();
 
 
-	// 3rd THING: The destroy everything that has a reference to GrObjects.
 	for(PerFrame& frame : m_perFrame)
 	for(PerFrame& frame : m_perFrame)
 	{
 	{
 		frame.m_presentFence.reset(nullptr);
 		frame.m_presentFence.reset(nullptr);
@@ -53,11 +52,13 @@ GrManagerImpl::~GrManagerImpl()
 	m_crntSwapchain.reset(nullptr);
 	m_crntSwapchain.reset(nullptr);
 
 
 	// 4th THING: Continue with the rest
 	// 4th THING: Continue with the rest
-	m_gpuMemManager.destroy();
 
 
 	m_barrierFactory.destroy(); // Destroy before fences
 	m_barrierFactory.destroy(); // Destroy before fences
 	m_semaphoreFactory.destroy(); // Destroy before fences
 	m_semaphoreFactory.destroy(); // Destroy before fences
 	m_swapchainFactory.destroy(); // Destroy before fences
 	m_swapchainFactory.destroy(); // Destroy before fences
+	m_frameGarbageCollector.destroy();
+
+	m_gpuMemManager.destroy();
 
 
 	m_pplineLayoutFactory.destroy();
 	m_pplineLayoutFactory.destroy();
 	m_descrFactory.destroy();
 	m_descrFactory.destroy();
@@ -95,6 +96,10 @@ GrManagerImpl::~GrManagerImpl()
 	}
 	}
 
 
 	m_vkHandleToName.destroy(getAllocator());
 	m_vkHandleToName.destroy(getAllocator());
+
+#if ANKI_PLATFORM_MOBILE
+	m_alloc.deleteInstance(m_globalCreatePipelineMtx);
+#endif
 }
 }
 
 
 Error GrManagerImpl::init(const GrManagerInitInfo& init)
 Error GrManagerImpl::init(const GrManagerInitInfo& init)
@@ -147,7 +152,6 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		resetFrame(f);
 		resetFrame(f);
 	}
 	}
 
 
-	glslang::InitializeProcess();
 	m_fenceFactory.init(getAllocator(), m_device);
 	m_fenceFactory.init(getAllocator(), m_device);
 	m_semaphoreFactory.init(getAllocator(), m_device);
 	m_semaphoreFactory.init(getAllocator(), m_device);
 	m_samplerFactory.init(this);
 	m_samplerFactory.init(this);
@@ -193,6 +197,8 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	ANKI_CHECK(m_descrFactory.init(getAllocator(), m_device, MAX_BINDLESS_TEXTURES, MAX_BINDLESS_IMAGES));
 	ANKI_CHECK(m_descrFactory.init(getAllocator(), m_device, MAX_BINDLESS_TEXTURES, MAX_BINDLESS_IMAGES));
 	m_pplineLayoutFactory.init(getAllocator(), m_device);
 	m_pplineLayoutFactory.init(getAllocator(), m_device);
 
 
+	m_frameGarbageCollector.init(this);
+
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
@@ -523,6 +529,7 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 	m_capabilities.m_textureBufferBindOffsetAlignment =
 	m_capabilities.m_textureBufferBindOffsetAlignment =
 		max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minTexelBufferOffsetAlignment));
 		max<U32>(ANKI_SAFE_ALIGNMENT, U32(m_devProps.properties.limits.minTexelBufferOffsetAlignment));
 	m_capabilities.m_textureBufferMaxRange = MAX_U32;
 	m_capabilities.m_textureBufferMaxRange = MAX_U32;
+	m_capabilities.m_computeSharedMemorySize = m_devProps.properties.limits.maxComputeSharedMemorySize;
 
 
 	m_capabilities.m_majorApiVersion = vulkanMajor;
 	m_capabilities.m_majorApiVersion = vulkanMajor;
 	m_capabilities.m_minorApiVersion = vulkanMinor;
 	m_capabilities.m_minorApiVersion = vulkanMinor;
@@ -530,6 +537,15 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 	m_capabilities.m_shaderGroupHandleSize = m_rtPipelineProps.shaderGroupHandleSize;
 	m_capabilities.m_shaderGroupHandleSize = m_rtPipelineProps.shaderGroupHandleSize;
 	m_capabilities.m_sbtRecordAlignment = m_rtPipelineProps.shaderGroupBaseAlignment;
 	m_capabilities.m_sbtRecordAlignment = m_rtPipelineProps.shaderGroupBaseAlignment;
 
 
+#if ANKI_PLATFORM_MOBILE
+	if(m_capabilities.m_gpuVendor == GpuVendor::QUALCOMM)
+	{
+		// Calling vkCreateGraphicsPipeline from multiple threads crashes qualcomm's compiler
+		ANKI_VK_LOGI("Enabling workaround for vkCreateGraphicsPipeline crashing when called from multiple threads");
+		m_globalCreatePipelineMtx = m_alloc.newInstance<Mutex>();
+	}
+#endif
+
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
@@ -1340,48 +1356,55 @@ void GrManagerImpl::flushCommandBuffer(MicroCommandBufferPtr cmdb, Bool cmdbRend
 		++submit.signalSemaphoreCount;
 		++submit.signalSemaphoreCount;
 	}
 	}
 
 
-	// Protect the class, the queue and other stuff
-	LockGuard<Mutex> lock(m_globalMtx);
-
-	// Do some special stuff for the last command buffer
-	PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
-	if(cmdbRenderedToSwapchain)
+	// Submit
 	{
 	{
-		// Wait semaphore
-		waitSemaphores[submit.waitSemaphoreCount] = frame.m_acquireSemaphore->getHandle();
+		// Protect the class, the queue and other stuff
+		LockGuard<Mutex> lock(m_globalMtx);
 
 
-		// That depends on how we use the swapchain img. Be a bit conservative
-		waitStages[submit.waitSemaphoreCount] =
-			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
-		++submit.waitSemaphoreCount;
+		// Do some special stuff for the last command buffer
+		PerFrame& frame = m_perFrame[m_frame % MAX_FRAMES_IN_FLIGHT];
+		if(cmdbRenderedToSwapchain)
+		{
+			// Wait semaphore
+			waitSemaphores[submit.waitSemaphoreCount] = frame.m_acquireSemaphore->getHandle();
 
 
-		// Refresh the fence because the semaphore can't be recycled until the current submission is done
-		frame.m_acquireSemaphore->setFence(fence);
+			// That depends on how we use the swapchain img. Be a bit conservative
+			waitStages[submit.waitSemaphoreCount] =
+				VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+			++submit.waitSemaphoreCount;
 
 
-		// Create the semaphore to signal
-		ANKI_ASSERT(!frame.m_renderSemaphore && "Only one begin/end render pass is allowed with the default fb");
-		frame.m_renderSemaphore = m_semaphoreFactory.newInstance(fence, false);
+			// Refresh the fence because the semaphore can't be recycled until the current submission is done
+			frame.m_acquireSemaphore->setFence(fence);
 
 
-		signalSemaphores[submit.signalSemaphoreCount++] = frame.m_renderSemaphore->getHandle();
+			// Create the semaphore to signal
+			ANKI_ASSERT(!frame.m_renderSemaphore && "Only one begin/end render pass is allowed with the default fb");
+			frame.m_renderSemaphore = m_semaphoreFactory.newInstance(fence, false);
 
 
-		// Update the frame fence
-		frame.m_presentFence = fence;
+			signalSemaphores[submit.signalSemaphoreCount++] = frame.m_renderSemaphore->getHandle();
 
 
-		// Update the swapchain's fence
-		m_crntSwapchain->setFence(fence);
+			// Update the frame fence
+			frame.m_presentFence = fence;
 
 
-		frame.m_queueWroteToSwapchainImage = cmdb->getVulkanQueueType();
-	}
+			// Update the swapchain's fence
+			m_crntSwapchain->setFence(fence);
 
 
-	// Submit
-	{
+			frame.m_queueWroteToSwapchainImage = cmdb->getVulkanQueueType();
+		}
+
+		// Submit
 		ANKI_TRACE_SCOPED_EVENT(VK_QUEUE_SUBMIT);
 		ANKI_TRACE_SCOPED_EVENT(VK_QUEUE_SUBMIT);
 		ANKI_VK_CHECKF(vkQueueSubmit(m_queues[cmdb->getVulkanQueueType()], 1, &submit, fence->getHandle()));
 		ANKI_VK_CHECKF(vkQueueSubmit(m_queues[cmdb->getVulkanQueueType()], 1, &submit, fence->getHandle()));
+
+		if(wait)
+		{
+			vkQueueWaitIdle(m_queues[cmdb->getVulkanQueueType()]);
+		}
 	}
 	}
 
 
-	if(wait)
+	// Garbage work
+	if(cmdbRenderedToSwapchain)
 	{
 	{
-		vkQueueWaitIdle(m_queues[cmdb->getVulkanQueueType()]);
+		m_frameGarbageCollector.setNewFrame(fence);
 	}
 	}
 }
 }
 
 

+ 19 - 0
AnKi/Gr/Vulkan/GrManagerImpl.h

@@ -19,6 +19,7 @@
 #include <AnKi/Gr/Vulkan/PipelineLayout.h>
 #include <AnKi/Gr/Vulkan/PipelineLayout.h>
 #include <AnKi/Gr/Vulkan/PipelineCache.h>
 #include <AnKi/Gr/Vulkan/PipelineCache.h>
 #include <AnKi/Gr/Vulkan/DescriptorSet.h>
 #include <AnKi/Gr/Vulkan/DescriptorSet.h>
+#include <AnKi/Gr/Vulkan/FrameGarbageCollector.h>
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Util/File.h>
 #include <AnKi/Util/File.h>
 
 
@@ -213,6 +214,18 @@ public:
 
 
 	void printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash = 0) const;
 	void printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash = 0) const;
 
 
+	FrameGarbageCollector& getFrameGarbageCollector()
+	{
+		return m_frameGarbageCollector;
+	}
+
+#if ANKI_PLATFORM_MOBILE
+	Mutex* getGlobalCreatePipelineMutex() const
+	{
+		return m_globalCreatePipelineMtx;
+	}
+#endif
+
 private:
 private:
 	U64 m_frame = 0;
 	U64 m_frame = 0;
 
 
@@ -315,6 +328,12 @@ private:
 	mutable HashMap<U64, StringAuto> m_vkHandleToName;
 	mutable HashMap<U64, StringAuto> m_vkHandleToName;
 	mutable SpinLock m_vkHandleToNameLock;
 	mutable SpinLock m_vkHandleToNameLock;
 
 
+	FrameGarbageCollector m_frameGarbageCollector;
+
+#if ANKI_PLATFORM_MOBILE
+	Mutex* m_globalCreatePipelineMtx = nullptr;
+#endif
+
 	ANKI_USE_RESULT Error initInternal(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initInternal(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initInstance(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initInstance(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initSurface(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initSurface(const GrManagerInitInfo& init);

+ 34 - 4
AnKi/Gr/Vulkan/MicroObjectRecycler.h

@@ -13,7 +13,7 @@ namespace anki {
 /// @addtogroup vulkan
 /// @addtogroup vulkan
 /// @{
 /// @{
 
 
-/// Helper class for MicroXXX objects.
+/// Helper class for MicroXXX objects. It expects a specific interface for the T.
 template<typename T>
 template<typename T>
 class MicroObjectRecycler
 class MicroObjectRecycler
 {
 {
@@ -47,17 +47,47 @@ public:
 	void recycle(T* s);
 	void recycle(T* s);
 
 
 	/// Destroy those objects that their fence is done. It's thread-safe.
 	/// Destroy those objects that their fence is done. It's thread-safe.
-	void trimCache();
+	void trimCache()
+	{
+		LockGuard<Mutex> lock(m_mtx);
+		checkDoneFences();
+		trimCacheInternal(0);
+	}
+
+	U32 getCacheSize() const
+	{
+		return m_objects.getSize();
+	}
 
 
 private:
 private:
+	class Object
+	{
+	public:
+		T* m_microObject;
+		Bool m_fenceDone;
+	};
+
 	GrAllocator<U8> m_alloc;
 	GrAllocator<U8> m_alloc;
-	DynamicArray<T*> m_objects;
+	DynamicArray<Object> m_objects;
 	Mutex m_mtx;
 	Mutex m_mtx;
+
+	// Begin trim cache adjustment vars
+	U32 m_readyObjectsAfterTrim = 1;
+	static constexpr U32 m_maxRequestsPerAdjustment = 128;
+	U32 m_cacheMisses = 0;
+	U32 m_requests = 0;
+	U32 m_minCacheSizePerRequest = MAX_U32;
+	// End trim cache adjustment vars
+
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	U32 m_createdAndNotRecycled = 0;
 	U32 m_createdAndNotRecycled = 0;
 #endif
 #endif
 
 
-	void releaseFences();
+	void trimCacheInternal(U32 aliveObjectCountAfterTrim);
+
+	void adjustAliveObjectCount();
+
+	void checkDoneFences();
 };
 };
 /// @}
 /// @}
 
 

+ 106 - 47
AnKi/Gr/Vulkan/MicroObjectRecycler.inl.h

@@ -12,14 +12,16 @@ inline void MicroObjectRecycler<T>::destroy()
 {
 {
 	LockGuard<Mutex> lock(m_mtx);
 	LockGuard<Mutex> lock(m_mtx);
 
 
+	checkDoneFences();
+
 	for(U32 i = 0; i < m_objects.getSize(); ++i)
 	for(U32 i = 0; i < m_objects.getSize(); ++i)
 	{
 	{
-		T* obj = m_objects[i];
-		ANKI_ASSERT(obj);
-		ANKI_ASSERT(!obj->getFence() || obj->getFence()->done());
+		T* mobj = m_objects[i].m_microObject;
+		ANKI_ASSERT(mobj);
+		ANKI_ASSERT(!mobj->getFence());
 
 
-		auto alloc = obj->getAllocator();
-		alloc.deleteInstance(obj);
+		auto alloc = mobj->getAllocator();
+		alloc.deleteInstance(mobj);
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 		--m_createdAndNotRecycled;
 		--m_createdAndNotRecycled;
 #endif
 #endif
@@ -29,43 +31,34 @@ inline void MicroObjectRecycler<T>::destroy()
 	ANKI_ASSERT(m_createdAndNotRecycled == 0 && "Destroying the recycler while objects have not recycled yet");
 	ANKI_ASSERT(m_createdAndNotRecycled == 0 && "Destroying the recycler while objects have not recycled yet");
 }
 }
 
 
-template<typename T>
-inline void MicroObjectRecycler<T>::releaseFences()
-{
-	for(U32 i = 0; i < m_objects.getSize(); ++i)
-	{
-		T& obj = *m_objects[i];
-		if(obj.getFence() && obj.getFence()->done())
-		{
-			obj.getFence().reset(nullptr);
-		}
-	}
-}
-
 template<typename T>
 template<typename T>
 inline T* MicroObjectRecycler<T>::findToReuse()
 inline T* MicroObjectRecycler<T>::findToReuse()
 {
 {
 	T* out = nullptr;
 	T* out = nullptr;
 	LockGuard<Mutex> lock(m_mtx);
 	LockGuard<Mutex> lock(m_mtx);
 
 
-	if(m_objects.getSize() > 0)
-	{
-		releaseFences();
+	checkDoneFences();
+	adjustAliveObjectCount();
+
+	// Trim the cache but leave at least one object to be recycled
+	trimCacheInternal(max(m_readyObjectsAfterTrim, 1u));
 
 
-		for(U32 i = 0; i < m_objects.getSize(); ++i)
+	for(U32 i = 0; i < m_objects.getSize(); ++i)
+	{
+		if(m_objects[i].m_fenceDone)
 		{
 		{
-			if(!m_objects[i]->getFence())
-			{
-				out = m_objects[i];
-				m_objects[i] = m_objects[m_objects.getSize() - 1];
-				m_objects.popBack(m_alloc);
-				break;
-			}
+			out = m_objects[i].m_microObject;
+			m_objects[i] = m_objects[m_objects.getSize() - 1];
+			m_objects.popBack(m_alloc);
+
+			break;
 		}
 		}
 	}
 	}
 
 
 	ANKI_ASSERT(out == nullptr || out->getRefcount().getNonAtomically() == 0);
 	ANKI_ASSERT(out == nullptr || out->getRefcount().getNonAtomically() == 0);
 
 
+	m_cacheMisses += (out == nullptr);
+
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	if(out == nullptr)
 	if(out == nullptr)
 	{
 	{
@@ -77,42 +70,73 @@ inline T* MicroObjectRecycler<T>::findToReuse()
 }
 }
 
 
 template<typename T>
 template<typename T>
-inline void MicroObjectRecycler<T>::recycle(T* s)
+void MicroObjectRecycler<T>::recycle(T* mobj)
 {
 {
-	ANKI_ASSERT(s);
-	ANKI_ASSERT(s->getRefcount().getNonAtomically() == 0);
+	ANKI_ASSERT(mobj);
+	ANKI_ASSERT(mobj->getRefcount().getNonAtomically() == 0);
 
 
 	LockGuard<Mutex> lock(m_mtx);
 	LockGuard<Mutex> lock(m_mtx);
 
 
-	releaseFences();
+	Object obj;
+	obj.m_fenceDone = !mobj->getFence();
+	obj.m_microObject = mobj;
+
+	if(obj.m_fenceDone)
+	{
+		mobj->onFenceDone();
+	}
 
 
-	m_objects.emplaceBack(m_alloc, s);
+	m_objects.emplaceBack(m_alloc, obj);
+	checkDoneFences();
+	trimCacheInternal(m_readyObjectsAfterTrim);
 }
 }
 
 
 template<typename T>
 template<typename T>
-inline void MicroObjectRecycler<T>::trimCache()
+void MicroObjectRecycler<T>::checkDoneFences()
 {
 {
-	LockGuard<Mutex> lock(m_mtx);
+	for(Object& obj : m_objects)
+	{
+		T& mobj = *obj.m_microObject;
+
+		if(obj.m_fenceDone)
+		{
+			ANKI_ASSERT(!mobj.getFence());
+		}
 
 
-	releaseFences();
+		if(!obj.m_fenceDone && mobj.getFence() && mobj.getFence()->done())
+		{
+			mobj.getFence().reset(nullptr);
+			mobj.onFenceDone();
+			obj.m_fenceDone = true;
+		}
+	}
+}
 
 
-	DynamicArray<T*> aliveObjects;
+template<typename T>
+void MicroObjectRecycler<T>::trimCacheInternal(U32 aliveObjectCountAfterTrim)
+{
+	DynamicArray<Object> aliveObjects;
 
 
-	for(U32 i = 0; i < m_objects.getSize(); ++i)
+	for(Object& obj : m_objects)
 	{
 	{
-		T* obj = m_objects[i];
-		ANKI_ASSERT(obj);
-		ANKI_ASSERT(obj->getRefcount().getNonAtomically() == 0);
+		T& mobj = *obj.m_microObject;
+		const Bool inUseByTheGpu = !obj.m_fenceDone;
 
 
-		if(obj->getFence())
+		if(inUseByTheGpu)
 		{
 		{
-			// Can't delete it
+			// Can't delete it for sure
 			aliveObjects.emplaceBack(m_alloc, obj);
 			aliveObjects.emplaceBack(m_alloc, obj);
 		}
 		}
+		else if(aliveObjectCountAfterTrim > 0)
+		{
+			// Need to keep a few alive for recycling
+			aliveObjects.emplaceBack(m_alloc, obj);
+			--aliveObjectCountAfterTrim;
+		}
 		else
 		else
 		{
 		{
-			auto alloc = obj->getAllocator();
-			alloc.deleteInstance(obj);
+			auto alloc = mobj.getAllocator();
+			alloc.deleteInstance(&mobj);
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 			--m_createdAndNotRecycled;
 			--m_createdAndNotRecycled;
 #endif
 #endif
@@ -125,11 +149,46 @@ inline void MicroObjectRecycler<T>::trimCache()
 		m_objects.destroy(m_alloc);
 		m_objects.destroy(m_alloc);
 		m_objects = std::move(aliveObjects);
 		m_objects = std::move(aliveObjects);
 	}
 	}
-	else if(aliveObjects.getSize() == 0 && m_objects.getSize() >= 0)
+	else if(aliveObjects.getSize() == 0 && m_objects.getSize() > 0)
 	{
 	{
 		// All dead, destroy the array
 		// All dead, destroy the array
 		m_objects.destroy(m_alloc);
 		m_objects.destroy(m_alloc);
 	}
 	}
 }
 }
 
 
+template<typename T>
+void MicroObjectRecycler<T>::adjustAliveObjectCount()
+{
+	U32 readyObjects = 0;
+	for(Object& obj : m_objects)
+	{
+		readyObjects += obj.m_fenceDone;
+	}
+
+	if(ANKI_LIKELY(m_requests < m_maxRequestsPerAdjustment))
+	{
+		// Not enough requests for a recycle
+		m_minCacheSizePerRequest = min(m_minCacheSizePerRequest, readyObjects);
+		++m_requests;
+	}
+	else
+	{
+		if(m_cacheMisses)
+		{
+			// Need more alive objects
+			m_readyObjectsAfterTrim += 4;
+		}
+		else if(m_minCacheSizePerRequest > 2 && m_readyObjectsAfterTrim > 0)
+		{
+			// Have more than enough alive objects per request, decrease alive objects
+			--m_readyObjectsAfterTrim;
+		}
+
+		// Start new cycle
+		m_cacheMisses = 0;
+		m_requests = 0;
+		m_minCacheSizePerRequest = readyObjects;
+	}
+}
+
 } // end namespace anki
 } // end namespace anki

+ 15 - 0
AnKi/Gr/Vulkan/Pipeline.cpp

@@ -469,7 +469,22 @@ void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline&
 
 
 	{
 	{
 		ANKI_TRACE_SCOPED_EVENT(VK_PIPELINE_CREATE);
 		ANKI_TRACE_SCOPED_EVENT(VK_PIPELINE_CREATE);
+
+#if ANKI_PLATFORM_MOBILE
+		if(m_globalCreatePipelineMtx)
+		{
+			m_globalCreatePipelineMtx->lock();
+		}
+#endif
+
 		ANKI_VK_CHECKF(vkCreateGraphicsPipelines(m_dev, m_pplineCache, 1, &ci, nullptr, &pp.m_handle));
 		ANKI_VK_CHECKF(vkCreateGraphicsPipelines(m_dev, m_pplineCache, 1, &ci, nullptr, &pp.m_handle));
+
+#if ANKI_PLATFORM_MOBILE
+		if(m_globalCreatePipelineMtx)
+		{
+			m_globalCreatePipelineMtx->unlock();
+		}
+#endif
 	}
 	}
 
 
 	ANKI_TRACE_INC_COUNTER(VK_PIPELINES_CACHE_MISS, 1);
 	ANKI_TRACE_INC_COUNTER(VK_PIPELINES_CACHE_MISS, 1);

+ 12 - 1
AnKi/Gr/Vulkan/Pipeline.h

@@ -549,11 +549,19 @@ public:
 	{
 	{
 	}
 	}
 
 
-	void init(GrAllocator<U8> alloc, VkDevice dev, VkPipelineCache pplineCache)
+	void init(GrAllocator<U8> alloc, VkDevice dev, VkPipelineCache pplineCache
+#if ANKI_PLATFORM_MOBILE
+			  ,
+			  Mutex* globalCreatePipelineMtx
+#endif
+	)
 	{
 	{
 		m_alloc = alloc;
 		m_alloc = alloc;
 		m_dev = dev;
 		m_dev = dev;
 		m_pplineCache = pplineCache;
 		m_pplineCache = pplineCache;
+#if ANKI_PLATFORM_MOBILE
+		m_globalCreatePipelineMtx = globalCreatePipelineMtx;
+#endif
 	}
 	}
 
 
 	void destroy();
 	void destroy();
@@ -571,6 +579,9 @@ private:
 
 
 	HashMap<U64, PipelineInternal, Hasher> m_pplines;
 	HashMap<U64, PipelineInternal, Hasher> m_pplines;
 	RWMutex m_pplinesMtx;
 	RWMutex m_pplinesMtx;
+#if ANKI_PLATFORM_MOBILE
+	Mutex* m_globalCreatePipelineMtx = nullptr;
+#endif
 };
 };
 /// @}
 /// @}
 
 

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

@@ -15,7 +15,7 @@ Error PipelineCache::init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir,
 {
 {
 	ANKI_ASSERT(cacheDir && dev && pdev);
 	ANKI_ASSERT(cacheDir && dev && pdev);
 	m_dumpSize = cfg.getGrDiskShaderCacheMaxSize();
 	m_dumpSize = cfg.getGrDiskShaderCacheMaxSize();
-	m_dumpFilename.sprintf(alloc, "%s/vk_pipeline_cache", &cacheDir[0]);
+	m_dumpFilename.sprintf(alloc, "%s/VkPipelineCache", &cacheDir[0]);
 
 
 	// Try read the pipeline cache file.
 	// Try read the pipeline cache file.
 	DynamicArrayAuto<U8, PtrSize> diskDump(alloc);
 	DynamicArrayAuto<U8, PtrSize> diskDump(alloc);

+ 6 - 0
AnKi/Gr/Vulkan/SemaphoreFactory.h

@@ -47,6 +47,12 @@ public:
 		return m_fence;
 		return m_fence;
 	}
 	}
 
 
+	/// Interface method.
+	void onFenceDone()
+	{
+		// Do nothing
+	}
+
 	void setFence(MicroFencePtr& fence)
 	void setFence(MicroFencePtr& fence)
 	{
 	{
 		m_fence = fence;
 		m_fence = fence;

+ 2 - 1
AnKi/Gr/Vulkan/ShaderImpl.h

@@ -25,7 +25,8 @@ public:
 	BitSet<MAX_COLOR_ATTACHMENTS, U8> m_colorAttachmentWritemask = {false};
 	BitSet<MAX_COLOR_ATTACHMENTS, U8> m_colorAttachmentWritemask = {false};
 	BitSet<MAX_VERTEX_ATTRIBUTES, U8> m_attributeMask = {false};
 	BitSet<MAX_VERTEX_ATTRIBUTES, U8> m_attributeMask = {false};
 	BitSet<MAX_DESCRIPTOR_SETS, U8> m_descriptorSetMask = {false};
 	BitSet<MAX_DESCRIPTOR_SETS, U8> m_descriptorSetMask = {false};
-	Array<BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U8>, MAX_DESCRIPTOR_SETS> m_activeBindingMask = {{{false}, {false}}};
+	Array<BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U8>, MAX_DESCRIPTOR_SETS> m_activeBindingMask = {
+		{{false}, {false}, {false}}};
 	U32 m_pushConstantsSize = 0;
 	U32 m_pushConstantsSize = 0;
 
 
 	ShaderImpl(GrManager* manager, CString name)
 	ShaderImpl(GrManager* manager, CString name)

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

@@ -222,7 +222,12 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	{
 	{
 		m_graphics.m_pplineFactory = getAllocator().newInstance<PipelineFactory>();
 		m_graphics.m_pplineFactory = getAllocator().newInstance<PipelineFactory>();
 		m_graphics.m_pplineFactory->init(getGrManagerImpl().getAllocator(), getGrManagerImpl().getDevice(),
 		m_graphics.m_pplineFactory->init(getGrManagerImpl().getAllocator(), getGrManagerImpl().getDevice(),
-										 getGrManagerImpl().getPipelineCache());
+										 getGrManagerImpl().getPipelineCache()
+#if ANKI_PLATFORM_MOBILE
+											 ,
+										 getGrManagerImpl().getGlobalCreatePipelineMutex()
+#endif
+		);
 	}
 	}
 
 
 	// Create the pipeline if compute
 	// Create the pipeline if compute

+ 2 - 1
AnKi/Gr/Vulkan/ShaderProgramImpl.h

@@ -23,7 +23,8 @@ public:
 	BitSet<MAX_COLOR_ATTACHMENTS, U8> m_colorAttachmentWritemask = {false};
 	BitSet<MAX_COLOR_ATTACHMENTS, U8> m_colorAttachmentWritemask = {false};
 	BitSet<MAX_VERTEX_ATTRIBUTES, U8> m_attributeMask = {false};
 	BitSet<MAX_VERTEX_ATTRIBUTES, U8> m_attributeMask = {false};
 	BitSet<MAX_DESCRIPTOR_SETS, U8> m_descriptorSetMask = {false};
 	BitSet<MAX_DESCRIPTOR_SETS, U8> m_descriptorSetMask = {false};
-	Array<BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U8>, MAX_DESCRIPTOR_SETS> m_activeBindingMask = {{{false}, {false}}};
+	Array<BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U8>, MAX_DESCRIPTOR_SETS> m_activeBindingMask = {
+		{{false}, {false}, {false}}};
 	U32 m_pushConstantsSize = 0;
 	U32 m_pushConstantsSize = 0;
 };
 };
 
 

+ 6 - 0
AnKi/Gr/Vulkan/SwapchainFactory.h

@@ -49,6 +49,12 @@ public:
 		return m_fence;
 		return m_fence;
 	}
 	}
 
 
+	/// Interface method.
+	void onFenceDone()
+	{
+		// Do nothing
+	}
+
 	VkRenderPass getRenderPass(VkAttachmentLoadOp loadOp) const
 	VkRenderPass getRenderPass(VkAttachmentLoadOp loadOp) const
 	{
 	{
 		const U idx = (loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE) ? RPASS_LOAD_DONT_CARE : RPASS_LOAD_CLEAR;
 		const U idx = (loadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE) ? RPASS_LOAD_DONT_CARE : RPASS_LOAD_CLEAR;

+ 34 - 52
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -83,27 +83,54 @@ TextureImpl::~TextureImpl()
 	}
 	}
 #endif
 #endif
 
 
+	TextureGarbage* garbage = getAllocator().newInstance<TextureGarbage>();
+
 	for(MicroImageView& it : m_viewsMap)
 	for(MicroImageView& it : m_viewsMap)
 	{
 	{
-		destroyMicroImageView(it);
+		garbage->m_viewHandles.emplaceBack(getAllocator(), it.m_handle);
+		it.m_handle = VK_NULL_HANDLE;
+
+		if(it.m_bindlessIndices[0] != MAX_U32)
+		{
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), it.m_bindlessIndices[0]);
+			it.m_bindlessIndices[0] = MAX_U32;
+		}
+
+		if(it.m_bindlessIndices[1] != MAX_U32)
+		{
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), it.m_bindlessIndices[1]);
+			it.m_bindlessIndices[1] = MAX_U32;
+		}
 	}
 	}
 
 
 	m_viewsMap.destroy(getAllocator());
 	m_viewsMap.destroy(getAllocator());
 
 
 	if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
 	if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
 	{
 	{
-		destroyMicroImageView(m_singleSurfaceImageView);
+		garbage->m_viewHandles.emplaceBack(getAllocator(), m_singleSurfaceImageView.m_handle);
+		m_singleSurfaceImageView.m_handle = VK_NULL_HANDLE;
+
+		if(m_singleSurfaceImageView.m_bindlessIndices[0] != MAX_U32)
+		{
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), m_singleSurfaceImageView.m_bindlessIndices[0]);
+			m_singleSurfaceImageView.m_bindlessIndices[0] = MAX_U32;
+		}
+
+		if(m_singleSurfaceImageView.m_bindlessIndices[1] != MAX_U32)
+		{
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), m_singleSurfaceImageView.m_bindlessIndices[1]);
+			m_singleSurfaceImageView.m_bindlessIndices[1] = MAX_U32;
+		}
 	}
 	}
 
 
 	if(m_imageHandle && !(m_usage & TextureUsageBit::PRESENT))
 	if(m_imageHandle && !(m_usage & TextureUsageBit::PRESENT))
 	{
 	{
-		vkDestroyImage(getDevice(), m_imageHandle, nullptr);
+		garbage->m_imageHandle = m_imageHandle;
 	}
 	}
 
 
-	if(m_memHandle)
-	{
-		getGrManagerImpl().getGpuMemoryManager().freeMemory(m_memHandle);
-	}
+	garbage->m_memoryHandle = m_memHandle;
+
+	getGrManagerImpl().getFrameGarbageCollector().newTextureGarbage(garbage);
 }
 }
 
 
 Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& init_)
 Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& init_)
@@ -176,30 +203,6 @@ Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& in
 		m_viewCreateInfoTemplate.pNext = &m_astcDecodeMode;
 		m_viewCreateInfoTemplate.pNext = &m_astcDecodeMode;
 	}
 	}
 
 
-	// Transition the image layout from undefined to something relevant
-	if(!!init.m_initialUsage)
-	{
-		ANKI_ASSERT(usageValid(init.m_initialUsage));
-		ANKI_ASSERT(!(init.m_initialUsage & TextureUsageBit::GENERATE_MIPMAPS) && "That doesn't make any sense");
-
-		CommandBufferInitInfo cmdbinit;
-		cmdbinit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
-		CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
-
-		VkImageSubresourceRange range;
-		range.aspectMask = convertImageAspect(m_aspect);
-		range.baseArrayLayer = 0;
-		range.baseMipLevel = 0;
-		range.layerCount = m_layerCount;
-		range.levelCount = m_mipCount;
-
-		CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
-		cmdbImpl.setTextureBarrierRange(TexturePtr(this), TextureUsageBit::NONE, init.m_initialUsage, range);
-
-		cmdbImpl.endRecording();
-		getGrManagerImpl().flushCommandBuffer(cmdbImpl.getMicroCommandBuffer(), false, {}, nullptr);
-	}
-
 	// Create a view if the texture is a single surface
 	// Create a view if the texture is a single surface
 	if(m_texType == TextureType::_2D && m_mipCount == 1 && m_aspect == DepthStencilAspectBit::NONE)
 	if(m_texType == TextureType::_2D && m_mipCount == 1 && m_aspect == DepthStencilAspectBit::NONE)
 	{
 	{
@@ -646,25 +649,4 @@ TextureType TextureImpl::computeNewTexTypeOfSubresource(const TextureSubresource
 	return m_texType;
 	return m_texType;
 }
 }
 
 
-void TextureImpl::destroyMicroImageView(MicroImageView& view)
-{
-	if(view.m_handle != VK_NULL_HANDLE)
-	{
-		vkDestroyImageView(getDevice(), view.m_handle, nullptr);
-		view.m_handle = VK_NULL_HANDLE;
-	}
-
-	if(view.m_bindlessIndices[0] != MAX_U32)
-	{
-		getGrManagerImpl().getDescriptorSetFactory().unbindBindlessTexture(view.m_bindlessIndices[0]);
-		view.m_bindlessIndices[0] = MAX_U32;
-	}
-
-	if(view.m_bindlessIndices[1] != MAX_U32)
-	{
-		getGrManagerImpl().getDescriptorSetFactory().unbindBindlessImage(view.m_bindlessIndices[1]);
-		view.m_bindlessIndices[1] = MAX_U32;
-	}
-}
-
 } // end namespace anki
 } // end namespace anki

+ 0 - 2
AnKi/Gr/Vulkan/TextureImpl.h

@@ -220,8 +220,6 @@ private:
 
 
 	void computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
 	void computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
 							VkAccessFlags& accesses) const;
 							VkAccessFlags& accesses) const;
-
-	void destroyMicroImageView(MicroImageView& view);
 };
 };
 /// @}
 /// @}
 
 

+ 4 - 2
AnKi/Importer/CMakeLists.txt

@@ -1,2 +1,4 @@
-file(GLOB SOURCES *.cpp)
-anki_add_source_files(${SOURCES})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiImporter ${sources})
+target_compile_definitions(AnKiImporter PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiImporter AnKiResource)

+ 12 - 12
AnKi/Importer/GltfImporter.cpp

@@ -191,7 +191,7 @@ Error GltfImporter::init(const GltfImporterInitInfo& initInfo)
 		m_lodFactor = 0.0f;
 		m_lodFactor = 0.0f;
 	}
 	}
 
 
-	ANKI_IMPORTER_LOGI("Having %u LODs with LOD factor %f", m_lodCount, m_lodFactor);
+	ANKI_IMPORTER_LOGV("Having %u LODs with LOD factor %f", m_lodCount, m_lodFactor);
 
 
 	cgltf_options options = {};
 	cgltf_options options = {};
 	cgltf_result res = cgltf_parse_file(&options, m_inputFname.cstr(), &m_gltf);
 	cgltf_result res = cgltf_parse_file(&options, m_inputFname.cstr(), &m_gltf);
@@ -686,7 +686,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				Array<const cgltf_material*, 128> m_materials;
 				Array<const cgltf_material*, 128> m_materials;
 				U32 m_materialCount = 0;
 				U32 m_materialCount = 0;
 				const cgltf_skin* m_skin;
 				const cgltf_skin* m_skin;
-				RayTypeBit m_rayTypes;
+				Bool m_rayTracing;
 			};
 			};
 			Ctx* ctx = m_alloc.newInstance<Ctx>();
 			Ctx* ctx = m_alloc.newInstance<Ctx>();
 			ctx->m_importer = this;
 			ctx->m_importer = this;
@@ -696,7 +696,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				ctx->m_materials[ctx->m_materialCount++] = node.mesh->primitives[i].material;
 				ctx->m_materials[ctx->m_materialCount++] = node.mesh->primitives[i].material;
 			}
 			}
 			ctx->m_skin = node.skin;
 			ctx->m_skin = node.skin;
-			ctx->m_rayTypes = (skipRt) ? RayTypeBit::NONE : RayTypeBit::ALL;
+			ctx->m_rayTracing = !skipRt;
 
 
 			HashMapAuto<CString, StringAuto>::Iterator it2;
 			HashMapAuto<CString, StringAuto>::Iterator it2;
 			const Bool selfCollision = (it2 = extras.find("collision_mesh")) != extras.getEnd() && *it2 == "self";
 			const Bool selfCollision = (it2 = extras.find("collision_mesh")) != extras.getEnd() && *it2 == "self";
@@ -732,7 +732,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 
 
 				for(U32 i = 0; i < self.m_materialCount && !err; ++i)
 				for(U32 i = 0; i < self.m_materialCount && !err; ++i)
 				{
 				{
-					err = self.m_importer->writeMaterial(*self.m_materials[i], self.m_rayTypes);
+					err = self.m_importer->writeMaterial(*self.m_materials[i], self.m_rayTracing);
 				}
 				}
 
 
 				if(!err)
 				if(!err)
@@ -785,7 +785,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 	}
 	}
 	else
 	else
 	{
 	{
-		ANKI_IMPORTER_LOGW("Ignoring node %s. Assuming transform node", getNodeName(node).cstr());
+		ANKI_IMPORTER_LOGV("Ignoring node %s. Assuming transform node", getNodeName(node).cstr());
 		ANKI_CHECK(getExtras(node.extras, outExtras));
 		ANKI_CHECK(getExtras(node.extras, outExtras));
 	}
 	}
 
 
@@ -830,7 +830,7 @@ Error GltfImporter::writeTransform(const Transform& trf)
 Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 {
 {
 	const StringAuto modelFname = computeModelResourceFilename(mesh);
 	const StringAuto modelFname = computeModelResourceFilename(mesh);
-	ANKI_IMPORTER_LOGI("Importing model %s", modelFname.cstr());
+	ANKI_IMPORTER_LOGV("Importing model %s", modelFname.cstr());
 
 
 	HashMapAuto<CString, StringAuto> extras(m_alloc);
 	HashMapAuto<CString, StringAuto> extras(m_alloc);
 	ANKI_CHECK(getExtras(mesh.extras, extras));
 	ANKI_CHECK(getExtras(mesh.extras, extras));
@@ -975,7 +975,7 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
 	StringAuto fname(m_alloc);
 	StringAuto fname(m_alloc);
 	fname.sprintf("%s%s", m_outDir.cstr(), computeAnimationResourceFilename(anim).cstr());
 	fname.sprintf("%s%s", m_outDir.cstr(), computeAnimationResourceFilename(anim).cstr());
 	fname = fixFilename(fname);
 	fname = fixFilename(fname);
-	ANKI_IMPORTER_LOGI("Importing animation %s", fname.cstr());
+	ANKI_IMPORTER_LOGV("Importing animation %s", fname.cstr());
 
 
 	// Gather the channels
 	// Gather the channels
 	HashMapAuto<CString, Array<const cgltf_animation_channel*, 3>> channelMap(m_alloc);
 	HashMapAuto<CString, Array<const cgltf_animation_channel*, 3>> channelMap(m_alloc);
@@ -1204,7 +1204,7 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 {
 {
 	StringAuto fname(m_alloc);
 	StringAuto fname(m_alloc);
 	fname.sprintf("%s%s", m_outDir.cstr(), computeSkeletonResourceFilename(skin).cstr());
 	fname.sprintf("%s%s", m_outDir.cstr(), computeSkeletonResourceFilename(skin).cstr());
-	ANKI_IMPORTER_LOGI("Importing skeleton %s", fname.cstr());
+	ANKI_IMPORTER_LOGV("Importing skeleton %s", fname.cstr());
 
 
 	// Get matrices
 	// Get matrices
 	DynamicArrayAuto<Mat4> boneMats(m_alloc);
 	DynamicArrayAuto<Mat4> boneMats(m_alloc);
@@ -1269,7 +1269,7 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 {
 {
 	const cgltf_light& light = *node.light;
 	const cgltf_light& light = *node.light;
 	StringAuto nodeName = getNodeName(node);
 	StringAuto nodeName = getNodeName(node);
-	ANKI_IMPORTER_LOGI("Importing light %s", nodeName.cstr());
+	ANKI_IMPORTER_LOGV("Importing light %s", nodeName.cstr());
 
 
 	HashMapAuto<CString, StringAuto> extras(parentExtras);
 	HashMapAuto<CString, StringAuto> extras(parentExtras);
 	ANKI_CHECK(getExtras(light.extras, extras));
 	ANKI_CHECK(getExtras(light.extras, extras));
@@ -1407,12 +1407,12 @@ Error GltfImporter::writeCamera(const cgltf_node& node, const HashMapAuto<CStrin
 {
 {
 	if(node.camera->type != cgltf_camera_type_perspective)
 	if(node.camera->type != cgltf_camera_type_perspective)
 	{
 	{
-		ANKI_IMPORTER_LOGW("Unsupported camera type: %s", getNodeName(node).cstr());
+		ANKI_IMPORTER_LOGV("Unsupported camera type: %s", getNodeName(node).cstr());
 		return Error::NONE;
 		return Error::NONE;
 	}
 	}
 
 
 	const cgltf_camera_perspective& cam = node.camera->data.perspective;
 	const cgltf_camera_perspective& cam = node.camera->data.perspective;
-	ANKI_IMPORTER_LOGI("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.writeText("\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"));
@@ -1428,7 +1428,7 @@ Error GltfImporter::writeCamera(const cgltf_node& node, const HashMapAuto<CStrin
 
 
 Error GltfImporter::writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
 Error GltfImporter::writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
 {
 {
-	ANKI_IMPORTER_LOGI("Importing model node %s", getNodeName(node).cstr());
+	ANKI_IMPORTER_LOGV("Importing model node %s", getNodeName(node).cstr());
 
 
 	HashMapAuto<CString, StringAuto> extras(parentExtras);
 	HashMapAuto<CString, StringAuto> extras(parentExtras);
 	ANKI_CHECK(getExtras(node.extras, extras));
 	ANKI_CHECK(getExtras(node.extras, extras));

+ 1 - 1
AnKi/Importer/GltfImporter.h

@@ -137,7 +137,7 @@ private:
 
 
 	// Resources
 	// Resources
 	ANKI_USE_RESULT Error writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFactor);
 	ANKI_USE_RESULT Error writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFactor);
-	ANKI_USE_RESULT Error writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayTypes);
+	ANKI_USE_RESULT Error writeMaterial(const cgltf_material& mtl, Bool writeRayTracing);
 	ANKI_USE_RESULT Error writeModel(const cgltf_mesh& mesh);
 	ANKI_USE_RESULT Error writeModel(const cgltf_mesh& mesh);
 	ANKI_USE_RESULT Error writeAnimation(const cgltf_animation& anim);
 	ANKI_USE_RESULT Error writeAnimation(const cgltf_animation& anim);
 	ANKI_USE_RESULT Error writeSkeleton(const cgltf_skin& skin);
 	ANKI_USE_RESULT Error writeSkeleton(const cgltf_skin& skin);

+ 40 - 39
AnKi/Importer/GltfImporterMaterial.cpp

@@ -10,21 +10,25 @@
 namespace anki {
 namespace anki {
 
 
 const char* MATERIAL_TEMPLATE = R"(<!-- This file is auto generated by ImporterMaterial.cpp -->
 const char* MATERIAL_TEMPLATE = R"(<!-- This file is auto generated by ImporterMaterial.cpp -->
-<material shaderProgram="AnKi/Shaders/GBufferGeneric.ankiprog">
-	<mutation>
-		<mutator name="DIFFUSE_TEX" value="%diffTexMutator%"/>
-		<mutator name="SPECULAR_TEX" value="%specTexMutator%"/>
-		<mutator name="ROUGHNESS_TEX" value="%roughnessTexMutator%"/>
-		<mutator name="METAL_TEX" value="%metalTexMutator%"/>
-		<mutator name="NORMAL_TEX" value="%normalTexMutator%"/>
-		<mutator name="PARALLAX" value="%parallaxMutator%"/>
-		<mutator name="EMISSIVE_TEX" value="%emissiveTexMutator%"/>
-		<mutator name="ALPHA_TEST" value="%alphaTestMutator%"/>
-	</mutation>
+<material shadows="1">
+	<shaderPrograms>
+		<shaderProgram name="GBufferGeneric">
+			<mutation>
+				<mutator name="DIFFUSE_TEX" value="%diffTexMutator%"/>
+				<mutator name="SPECULAR_TEX" value="%specTexMutator%"/>
+				<mutator name="ROUGHNESS_TEX" value="%roughnessTexMutator%"/>
+				<mutator name="METAL_TEX" value="%metalTexMutator%"/>
+				<mutator name="NORMAL_TEX" value="%normalTexMutator%"/>
+				<mutator name="PARALLAX" value="%parallaxMutator%"/>
+				<mutator name="EMISSIVE_TEX" value="%emissiveTexMutator%"/>
+				<mutator name="ALPHA_TEST" value="%alphaTestMutator%"/>
+			</mutation>
+		</shaderProgram>
+		%rayTracing%
+	</shaderPrograms>
 
 
 	<inputs>
 	<inputs>
 		%parallaxInput%
 		%parallaxInput%
-
 		%diff%
 		%diff%
 		%spec%
 		%spec%
 		%roughness%
 		%roughness%
@@ -38,13 +42,12 @@ const char* MATERIAL_TEMPLATE = R"(<!-- This file is auto generated by ImporterM
 )";
 )";
 
 
 const char* RT_MATERIAL_TEMPLATE = R"(
 const char* RT_MATERIAL_TEMPLATE = R"(
-<rtMaterial>
-	<rayType type="shadows" shaderProgram="AnKi/Shaders/RtShadowsHit.ankiprog">
-		<mutation>
-			<mutator name="ALPHA_TEXTURE" value="0"/>
-		</mutation>
-	</rayType>
-</rtMaterial>)";
+		<shaderProgram name="RtShadowsHit">
+			<mutation>
+				<mutator name="ALPHA_TEXTURE" value="0"/>
+			</mutation>
+		</shaderProgram>
+)";
 
 
 static CString getTextureUri(const cgltf_texture_view& view)
 static CString getTextureUri(const cgltf_texture_view& view)
 {
 {
@@ -94,11 +97,11 @@ static Error findConstantColorsInImage(CString fname, Vec4& constantColor, Gener
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
-Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayTypes)
+Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracing)
 {
 {
 	StringAuto fname(m_alloc);
 	StringAuto fname(m_alloc);
 	fname.sprintf("%s%s", m_outDir.cstr(), computeMaterialResourceFilename(mtl).cstr());
 	fname.sprintf("%s%s", m_outDir.cstr(), computeMaterialResourceFilename(mtl).cstr());
-	ANKI_IMPORTER_LOGI("Importing material %s", fname.cstr());
+	ANKI_IMPORTER_LOGV("Importing material %s", fname.cstr());
 
 
 	if(!mtl.has_pbr_metallic_roughness)
 	if(!mtl.has_pbr_metallic_roughness)
 	{
 	{
@@ -114,9 +117,9 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 	xml.append("\n");
 	xml.append("\n");
 	xml.append(MATERIAL_TEMPLATE);
 	xml.append(MATERIAL_TEMPLATE);
 
 
-	if(!!(usedRayTypes & RayTypeBit::SHADOWS))
+	if(writeRayTracing)
 	{
 	{
-		xml.append(RT_MATERIAL_TEMPLATE);
+		xml.replaceAll("%rayTracing%", RT_MATERIAL_TEMPLATE);
 	}
 	}
 
 
 	// Diffuse
 	// Diffuse
@@ -127,8 +130,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 		StringAuto uri(m_alloc);
 		StringAuto uri(m_alloc);
 		uri.sprintf("%s%s", m_texrpath.cstr(), fname.cstr());
 		uri.sprintf("%s%s", m_texrpath.cstr(), fname.cstr());
 
 
-		xml.replaceAll("%diff%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_diffTex\" value=\"%s\"/>", uri.cstr()));
+		xml.replaceAll("%diff%", StringAuto(m_alloc).sprintf("<input name=\"m_diffTex\" value=\"%s\"/>", uri.cstr()));
 		xml.replaceAll("%diffTexMutator%", "1");
 		xml.replaceAll("%diffTexMutator%", "1");
 
 
 		Vec4 constantColor;
 		Vec4 constantColor;
@@ -141,7 +143,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 	{
 	{
 		const F32* diffCol = &mtl.pbr_metallic_roughness.base_color_factor[0];
 		const F32* diffCol = &mtl.pbr_metallic_roughness.base_color_factor[0];
 
 
-		xml.replaceAll("%diff%", StringAuto(m_alloc).sprintf("<input shaderVar=\"m_diffColor\" value=\"%f %f %f\"/>",
+		xml.replaceAll("%diff%", StringAuto(m_alloc).sprintf("<input name=\"m_diffColor\" value=\"%f %f %f\"/>",
 															 diffCol[0], diffCol[1], diffCol[2]));
 															 diffCol[0], diffCol[1], diffCol[2]));
 
 
 		xml.replaceAll("%diffTexMutator%", "0");
 		xml.replaceAll("%diffTexMutator%", "0");
@@ -174,7 +176,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 			specular = Vec3(0.04f);
 			specular = Vec3(0.04f);
 		}
 		}
 
 
-		xml.replaceAll("%spec%", StringAuto(m_alloc).sprintf("<input shaderVar=\"m_specColor\" value=\"%f %f %f\"/>",
+		xml.replaceAll("%spec%", StringAuto(m_alloc).sprintf("<input name=\"m_specColor\" value=\"%f %f %f\"/>",
 															 specular.x(), specular.y(), specular.z()));
 															 specular.x(), specular.y(), specular.z()));
 
 
 		xml.replaceAll("%specTexMutator%", "0");
 		xml.replaceAll("%specTexMutator%", "0");
@@ -200,7 +202,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 					getTextureUri(mtl.pbr_metallic_roughness.metallic_roughness_texture).cstr());
 					getTextureUri(mtl.pbr_metallic_roughness.metallic_roughness_texture).cstr());
 
 
 		xml.replaceAll("%roughness%",
 		xml.replaceAll("%roughness%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_roughnessTex\" value=\"%s\"/>", uri.cstr()));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_roughnessTex\" value=\"%s\"/>", uri.cstr()));
 
 
 		xml.replaceAll("%roughnessTexMutator%", "1");
 		xml.replaceAll("%roughnessTexMutator%", "1");
 	}
 	}
@@ -211,7 +213,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 								  : mtl.pbr_metallic_roughness.roughness_factor;
 								  : mtl.pbr_metallic_roughness.roughness_factor;
 
 
 		xml.replaceAll("%roughness%",
 		xml.replaceAll("%roughness%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"m_roughness\" value=\"%f\"/>", roughness));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_roughness\" value=\"%f\"/>", roughness));
 
 
 		xml.replaceAll("%roughnessTexMutator%", "0");
 		xml.replaceAll("%roughnessTexMutator%", "0");
 	}
 	}
@@ -224,7 +226,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 					getTextureUri(mtl.pbr_metallic_roughness.metallic_roughness_texture).cstr());
 					getTextureUri(mtl.pbr_metallic_roughness.metallic_roughness_texture).cstr());
 
 
 		xml.replaceAll("%metallic%",
 		xml.replaceAll("%metallic%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_metallicTex\" value=\"%s\"/>", uri.cstr()));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_metallicTex\" value=\"%s\"/>", uri.cstr()));
 
 
 		xml.replaceAll("%metalTexMutator%", "1");
 		xml.replaceAll("%metalTexMutator%", "1");
 	}
 	}
@@ -235,7 +237,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 								  : mtl.pbr_metallic_roughness.metallic_factor;
 								  : mtl.pbr_metallic_roughness.metallic_factor;
 
 
 		xml.replaceAll("%metallic%",
 		xml.replaceAll("%metallic%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"m_metallic\" value=\"%f\"/>", metalines));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_metallic\" value=\"%f\"/>", metalines));
 
 
 		xml.replaceAll("%metalTexMutator%", "0");
 		xml.replaceAll("%metalTexMutator%", "0");
 	}
 	}
@@ -251,7 +253,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 			uri.sprintf("%s%s", m_texrpath.cstr(), getTextureUri(mtl.normal_texture).cstr());
 			uri.sprintf("%s%s", m_texrpath.cstr(), getTextureUri(mtl.normal_texture).cstr());
 
 
 			xml.replaceAll("%normal%",
 			xml.replaceAll("%normal%",
-						   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_normalTex\" value=\"%s\"/>", uri.cstr()));
+						   StringAuto(m_alloc).sprintf("<input name=\"m_normalTex\" value=\"%s\"/>", uri.cstr()));
 
 
 			xml.replaceAll("%normalTexMutator%", "1");
 			xml.replaceAll("%normalTexMutator%", "1");
 		}
 		}
@@ -274,7 +276,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 		uri.sprintf("%s%s", m_texrpath.cstr(), getTextureUri(mtl.emissive_texture).cstr());
 		uri.sprintf("%s%s", m_texrpath.cstr(), getTextureUri(mtl.emissive_texture).cstr());
 
 
 		xml.replaceAll("%emission%",
 		xml.replaceAll("%emission%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_emissiveTex\" value=\"%s\"/>", uri.cstr()));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_emissiveTex\" value=\"%s\"/>", uri.cstr()));
 
 
 		xml.replaceAll("%emissiveTexMutator%", "1");
 		xml.replaceAll("%emissiveTexMutator%", "1");
 	}
 	}
@@ -282,7 +284,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 	{
 	{
 		const F32* emissionCol = &mtl.emissive_factor[0];
 		const F32* emissionCol = &mtl.emissive_factor[0];
 
 
-		xml.replaceAll("%emission%", StringAuto(m_alloc).sprintf("<input shaderVar=\"m_emission\" value=\"%f %f %f\"/>",
+		xml.replaceAll("%emission%", StringAuto(m_alloc).sprintf("<input name=\"m_emission\" value=\"%f %f %f\"/>",
 																 emissionCol[0], emissionCol[1], emissionCol[2]));
 																 emissionCol[0], emissionCol[1], emissionCol[2]));
 
 
 		xml.replaceAll("%emissiveTexMutator%", "0");
 		xml.replaceAll("%emissiveTexMutator%", "0");
@@ -302,7 +304,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 		}
 		}
 
 
 		xml.replaceAll("%subsurface%",
 		xml.replaceAll("%subsurface%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"m_subsurface\" value=\"%f\"/>", subsurface));
+					   StringAuto(m_alloc).sprintf("<input name=\"m_subsurface\" value=\"%f\"/>", subsurface));
 	}
 	}
 
 
 	// Height texture
 	// Height texture
@@ -312,10 +314,9 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayT
 		StringAuto uri(m_alloc);
 		StringAuto uri(m_alloc);
 		uri.sprintf("%s%s", m_texrpath.cstr(), it->cstr());
 		uri.sprintf("%s%s", m_texrpath.cstr(), it->cstr());
 
 
-		xml.replaceAll("%height%",
-					   StringAuto(m_alloc).sprintf("<input shaderVar=\"u_heightTex\" value=\"%s\" \"/>\n"
-												   "\t\t<input shaderVar=\"m_heightmapScale\" value=\"0.05\"/>",
-												   uri.cstr()));
+		xml.replaceAll("%height%", StringAuto(m_alloc).sprintf("<input name=\"m_heightTex\" value=\"%s\" \"/>\n"
+															   "\t\t<input name=\"m_heightmapScale\" value=\"0.05\"/>",
+															   uri.cstr()));
 
 
 		xml.replaceAll("%parallaxMutator%", "1");
 		xml.replaceAll("%parallaxMutator%", "1");
 	}
 	}

+ 19 - 6
AnKi/Importer/GltfImporterMesh.cpp

@@ -49,6 +49,9 @@ static U cgltfComponentSize(cgltf_component_type type)
 	case cgltf_component_type_r_16u:
 	case cgltf_component_type_r_16u:
 		out = sizeof(U16);
 		out = sizeof(U16);
 		break;
 		break;
+	case cgltf_component_type_r_8u:
+		out = sizeof(U8);
+		break;
 	default:
 	default:
 		ANKI_ASSERT(!"TODO");
 		ANKI_ASSERT(!"TODO");
 		out = 0;
 		out = 0;
@@ -275,7 +278,7 @@ Error GltfImporter::writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFacto
 {
 {
 	StringAuto fname(m_alloc);
 	StringAuto fname(m_alloc);
 	fname.sprintf("%s%s", m_outDir.cstr(), computeMeshResourceFilename(mesh, lod).cstr());
 	fname.sprintf("%s%s", m_outDir.cstr(), computeMeshResourceFilename(mesh, lod).cstr());
-	ANKI_IMPORTER_LOGI("Importing mesh (%s, decimate factor %f): %s",
+	ANKI_IMPORTER_LOGV("Importing mesh (%s, decimate factor %f): %s",
 					   (m_optimizeMeshes) ? "optimize" : "WON'T optimize", decimateFactor, fname.cstr());
 					   (m_optimizeMeshes) ? "optimize" : "WON'T optimize", decimateFactor, fname.cstr());
 
 
 	ListAuto<SubMesh> submeshes(m_alloc);
 	ListAuto<SubMesh> submeshes(m_alloc);
@@ -354,10 +357,20 @@ Error GltfImporter::writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFacto
 			else if(attrib->type == cgltf_attribute_type_joints)
 			else if(attrib->type == cgltf_attribute_type_joints)
 			{
 			{
 				U32 count = 0;
 				U32 count = 0;
-				ANKI_CHECK(checkAttribute<U16Vec4>(*attrib));
-				visitAccessor<U16Vec4>(*attrib->data, [&](const U16Vec4& x) {
-					submesh.m_verts[count++].m_boneIds = x;
-				});
+				if(cgltfComponentSize(attrib->data->component_type) == 2)
+				{
+					ANKI_CHECK(checkAttribute<U16Vec4>(*attrib));
+					visitAccessor<U16Vec4>(*attrib->data, [&](const U16Vec4& x) {
+						submesh.m_verts[count++].m_boneIds = x;
+					});
+				}
+				else
+				{
+					ANKI_CHECK(checkAttribute<U8Vec4>(*attrib));
+					visitAccessor<U8Vec4>(*attrib->data, [&](const U8Vec4& x) {
+						submesh.m_verts[count++].m_boneIds = U16Vec4(x);
+					});
+				}
 				hasBoneWeights = true;
 				hasBoneWeights = true;
 			}
 			}
 			else if(attrib->type == cgltf_attribute_type_weights)
 			else if(attrib->type == cgltf_attribute_type_weights)
@@ -370,7 +383,7 @@ Error GltfImporter::writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFacto
 			}
 			}
 			else
 			else
 			{
 			{
-				ANKI_IMPORTER_LOGW("Ignoring attribute: %s", attrib->name);
+				ANKI_IMPORTER_LOGV("Ignoring attribute: %s", attrib->name);
 			}
 			}
 		}
 		}
 
 

+ 1 - 1
AnKi/Importer/ImageImporter.cpp

@@ -1008,7 +1008,7 @@ static ANKI_USE_RESULT Error importImageInternal(const ImageImporterConfig& conf
 	}
 	}
 
 
 	ctx.m_channelCount = desiredChannelCount;
 	ctx.m_channelCount = desiredChannelCount;
-	ctx.m_pixelSize = ctx.m_channelCount * ((isHdr) ? sizeof(F32) : sizeof(U8));
+	ctx.m_pixelSize = ctx.m_channelCount * U32((isHdr) ? sizeof(F32) : sizeof(U8));
 
 
 	// Load first mip from the files
 	// Load first mip from the files
 	ANKI_CHECK(loadFirstMipmap(config, ctx));
 	ANKI_CHECK(loadFirstMipmap(config, ctx));

+ 2 - 0
AnKi/Importer/TinyExr.cpp

@@ -13,6 +13,8 @@
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #	pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wunused-function"
+#	pragma GCC diagnostic ignored "-Wconversion"
+#	pragma GCC diagnostic ignored "-Wunused-variable"
 #endif
 #endif
 
 
 #include <ThirdParty/TinyExr/tinyexr.h>
 #include <ThirdParty/TinyExr/tinyexr.h>

+ 6 - 8
AnKi/Input/CMakeLists.txt

@@ -1,13 +1,11 @@
-set(SOURCES "")
-
 if(ANKI_HEADLESS)
 if(ANKI_HEADLESS)
-	set(SOURCES ${SOURCES} InputDummy.cpp)
+	set(sources InputDummy.cpp)
 elseif(SDL)
 elseif(SDL)
-	set(SOURCES ${SOURCES} InputSdl.cpp)
+	set(sources InputSdl.cpp)
 elseif(ANDROID)
 elseif(ANDROID)
-	set(SOURCES ${SOURCES} InputAndroid.cpp)
+	set(sources InputAndroid.cpp)
 endif()
 endif()
 
 
-foreach(F ${SOURCES})
-	anki_add_source_files("${CMAKE_CURRENT_SOURCE_DIR}/${F}")
-endforeach()
+add_library(AnKiInput ${sources})
+target_compile_definitions(AnKiInput PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiInput AnKiCore AnKiImGui)

+ 4 - 2
AnKi/Math/CMakeLists.txt

@@ -1,2 +1,4 @@
-file(GLOB SOURCES *.cpp)
-anki_add_source_files(${SOURCES})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiMath ${sources})
+target_compile_definitions(AnKiMath PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiMath AnKiUtil)

+ 4 - 2
AnKi/Physics/CMakeLists.txt

@@ -1,2 +1,4 @@
-file(GLOB SOURCES *.cpp)
-anki_add_source_files(${SOURCES})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiPhysics ${sources})
+target_compile_definitions(AnKiPhysics PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiPhysics AnKiUtil BulletSoftBody BulletDynamics BulletCollision LinearMath)

+ 1 - 1
AnKi/Renderer/AccelerationStructureBuilder.cpp

@@ -35,7 +35,7 @@ void AccelerationStructureBuilder::populateRenderGraph(RenderingContext& ctx)
 		AccelerationStructureInstance& out = instances[instanceIdx];
 		AccelerationStructureInstance& out = instances[instanceIdx];
 		::new(&out) AccelerationStructureInstance();
 		::new(&out) AccelerationStructureInstance();
 		out.m_bottomLevel.reset(element.m_bottomLevelAccelerationStructure);
 		out.m_bottomLevel.reset(element.m_bottomLevelAccelerationStructure);
-		memcpy(&out.m_transform, &element.m_modelDescriptor.m_worldTransform[0], sizeof(out.m_transform));
+		memcpy(&out.m_transform, &element.m_transform, sizeof(out.m_transform));
 		out.m_hitgroupSbtRecordIndex = instanceIdx;
 		out.m_hitgroupSbtRecordIndex = instanceIdx;
 		out.m_mask = 0xFF;
 		out.m_mask = 0xFF;
 	}
 	}

+ 5 - 4
AnKi/Renderer/Bloom.cpp

@@ -43,8 +43,9 @@ Error Bloom::initExposure()
 	m_exposure.m_rtDescr.bake();
 	m_exposure.m_rtDescr.bake();
 
 
 	// init shaders
 	// init shaders
-	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute()) ? "Shaders/BloomCompute.ankiprog"
-																				   : "Shaders/BloomRaster.ankiprog",
+	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
+													 ? "ShaderBinaries/BloomCompute.ankiprogbin"
+													 : "ShaderBinaries/BloomRaster.ankiprogbin",
 												 m_exposure.m_prog));
 												 m_exposure.m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_exposure.m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_exposure.m_prog);
@@ -72,8 +73,8 @@ Error Bloom::initUpscale()
 
 
 	// init shaders
 	// init shaders
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
-													 ? "Shaders/BloomUpscaleCompute.ankiprog"
-													 : "Shaders/BloomUpscaleRaster.ankiprog",
+													 ? "ShaderBinaries/BloomUpscaleCompute.ankiprogbin"
+													 : "ShaderBinaries/BloomUpscaleRaster.ankiprogbin",
 												 m_upscale.m_prog));
 												 m_upscale.m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscale.m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscale.m_prog);

+ 4 - 2
AnKi/Renderer/CMakeLists.txt

@@ -1,2 +1,4 @@
-file(GLOB_RECURSE SOURCES *.cpp)
-anki_add_source_files(${SOURCES})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiRenderer ${sources})
+target_compile_definitions(AnKiRenderer PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiRenderer AnKiGr AnKiResource AnKiUi)

+ 22 - 16
AnKi/Renderer/ClusterBinning.cpp

@@ -30,7 +30,7 @@ Error ClusterBinning::init()
 {
 {
 	ANKI_R_LOGV("Initializing clusterer binning");
 	ANKI_R_LOGV("Initializing clusterer binning");
 
 
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/ClusterBinning.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/ClusterBinning.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("TILE_SIZE", m_r->getTileSize());
 	variantInitInfo.addConstant("TILE_SIZE", m_r->getTileSize());
@@ -261,9 +261,10 @@ void ClusterBinning::writeClustererBuffersTask()
 			{
 			{
 				out.m_shadowLayer = in.m_shadowLayer;
 				out.m_shadowLayer = in.m_shadowLayer;
 				out.m_shadowAtlasTileScale = in.m_shadowAtlasTileSize;
 				out.m_shadowAtlasTileScale = in.m_shadowAtlasTileSize;
-				static_assert(sizeof(out.m_shadowAtlasTileOffsets) == sizeof(in.m_shadowAtlasTileOffsets), "See file");
-				memcpy(&out.m_shadowAtlasTileOffsets[0], &in.m_shadowAtlasTileOffsets[0],
-					   sizeof(in.m_shadowAtlasTileOffsets));
+				for(U32 f = 0; f < 6; ++f)
+				{
+					out.m_shadowAtlasTileOffsets[f] = Vec4(in.m_shadowAtlasTileOffsets[f], 0.0f, 0.0f);
+				}
 			}
 			}
 		}
 		}
 	}
 	}
@@ -279,7 +280,10 @@ void ClusterBinning::writeClustererBuffersTask()
 			SpotLight& out = lights[i];
 			SpotLight& out = lights[i];
 
 
 			out.m_position = in.m_worldTransform.getTranslationPart().xyz();
 			out.m_position = in.m_worldTransform.getTranslationPart().xyz();
-			memcpy(&out.m_edgePoints[0][0], &in.m_edgePoints[0][0], sizeof(out.m_edgePoints));
+			for(U32 j = 0; j < 4; ++j)
+			{
+				out.m_edgePoints[j] = in.m_edgePoints[j].xyz0();
+			}
 			out.m_diffuseColor = in.m_diffuseColor;
 			out.m_diffuseColor = in.m_diffuseColor;
 			out.m_radius = in.m_distance;
 			out.m_radius = in.m_distance;
 			out.m_squareRadiusOverOne = 1.0f / (in.m_distance * in.m_distance);
 			out.m_squareRadiusOverOne = 1.0f / (in.m_distance * in.m_distance);
@@ -431,17 +435,19 @@ void ClusterBinning::writeClustererBuffersTask()
 		unis.m_tileSize = m_r->getTileSize();
 		unis.m_tileSize = m_r->getTileSize();
 		unis.m_lightVolumeLastZSplit = m_r->getVolumetricLightingAccumulation().getFinalZSplit();
 		unis.m_lightVolumeLastZSplit = m_r->getVolumetricLightingAccumulation().getFinalZSplit();
 
 
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_POINT_LIGHT] = rqueue.m_pointLights.getSize();
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT] =
-			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT - 1] + rqueue.m_spotLights.getSize();
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL] =
-			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL - 1] + rqueue.m_decals.getSize();
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME] =
-			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME - 1] + rqueue.m_fogDensityVolumes.getSize();
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE] =
-			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE - 1] + rqueue.m_reflectionProbes.getSize();
-		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE] =
-			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE - 1] + rqueue.m_giProbes.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_POINT_LIGHT].x() = rqueue.m_pointLights.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT].x() =
+			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT - 1].x() + rqueue.m_spotLights.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL].x() =
+			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL - 1].x() + rqueue.m_decals.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME].x() =
+			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME - 1].x()
+			+ rqueue.m_fogDensityVolumes.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE].x() =
+			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE - 1].x() + rqueue.m_reflectionProbes.getSize();
+		unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE].x() =
+			unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE - 1].x()
+			+ rqueue.m_giProbes.getSize();
 
 
 		unis.m_reflectionProbesMipCount = F32(m_r->getProbeReflections().getReflectionTextureMipmapCount());
 		unis.m_reflectionProbesMipCount = F32(m_r->getProbeReflections().getReflectionTextureMipmapCount());
 
 

+ 1 - 1
AnKi/Renderer/Common.h

@@ -8,7 +8,7 @@
 #include <AnKi/Gr.h>
 #include <AnKi/Gr.h>
 #include <AnKi/Core/GpuMemoryPools.h>
 #include <AnKi/Core/GpuMemoryPools.h>
 #include <AnKi/Util/Ptr.h>
 #include <AnKi/Util/Ptr.h>
-#include <AnKi/Shaders/Include/Evsm.h>
+#include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 
 
 namespace anki {
 namespace anki {

+ 10 - 5
AnKi/Renderer/ConfigVars.defs.h

@@ -32,6 +32,13 @@ ANKI_CONFIG_VAR_U32(RSsrDepthLod, 2, 0, 1000, "Texture LOD of the depth texture
 ANKI_CONFIG_VAR_U32(RSsrMaxSteps, 64, 1, 256, "Max SSR raymarching steps")
 ANKI_CONFIG_VAR_U32(RSsrMaxSteps, 64, 1, 256, "Max SSR raymarching steps")
 ANKI_CONFIG_VAR_BOOL(RSsrStochastic, false, "Stochastic reflections")
 ANKI_CONFIG_VAR_BOOL(RSsrStochastic, false, "Stochastic reflections")
 
 
+// GI probes
+ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeTileResolution, (ANKI_PLATFORM_MOBILE) ? 16 : 32, 8, 32, "GI tile resolution")
+ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeShadowMapResolution, 128, 4, 2048, "GI shadowmap resolution")
+ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeMaxCachedProbes, 16, 4, 2048, "Max cached probes")
+ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeMaxVisibleProbes, 8, 1, 256, "Max visible GI probes")
+
+// GI
 ANKI_CONFIG_VAR_U32(RIndirectDiffuseSsgiSampleCount, 8, 1, 1024, "SSGI sample count")
 ANKI_CONFIG_VAR_U32(RIndirectDiffuseSsgiSampleCount, 8, 1, 1024, "SSGI sample count")
 ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsgiRadius, 2.0f, 0.1f, 100.0f, "SSGI radius in meters")
 ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsgiRadius, 2.0f, 0.1f, 100.0f, "SSGI radius in meters")
 ANKI_CONFIG_VAR_U32(RIndirectDiffuseDenoiseSampleCount, 4, 1, 128, "Indirect diffuse denoise sample count")
 ANKI_CONFIG_VAR_U32(RIndirectDiffuseDenoiseSampleCount, 4, 1, 128, "Indirect diffuse denoise sample count")
@@ -40,6 +47,7 @@ ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsaoBias, -0.1f, -10.0f, 10.0f, "SSAO bias")
 ANKI_CONFIG_VAR_F32(RIndirectDiffuseVrsDistanceThreshold, 0.01f, 0.00001f, 10.0f,
 ANKI_CONFIG_VAR_F32(RIndirectDiffuseVrsDistanceThreshold, 0.01f, 0.00001f, 10.0f,
 					"The meters that control the VRS SRI generation")
 					"The meters that control the VRS SRI generation")
 
 
+// Shadows
 ANKI_CONFIG_VAR_U32(RShadowMappingTileResolution, (ANKI_PLATFORM_MOBILE) ? 128 : 512, 16, 2048,
 ANKI_CONFIG_VAR_U32(RShadowMappingTileResolution, (ANKI_PLATFORM_MOBILE) ? 128 : 512, 16, 2048,
 					"Shadowmapping tile resolution")
 					"Shadowmapping tile resolution")
 ANKI_CONFIG_VAR_U32(RShadowMappingTileCountPerRowOrColumn, 16, 1, 256,
 ANKI_CONFIG_VAR_U32(RShadowMappingTileCountPerRowOrColumn, 16, 1, 256,
@@ -48,19 +56,16 @@ ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountX, 4 * (MAX_SHADOW_CASCADES2 +
 					"Number of tiles of the scratch buffer in X")
 					"Number of tiles of the scratch buffer in X")
 ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountY, 4, 1, 256, "Number of tiles of the scratch buffer in Y")
 ANKI_CONFIG_VAR_U32(RShadowMappingScratchTileCountY, 4, 1, 256, "Number of tiles of the scratch buffer in Y")
 
 
+// Probe reflections
 ANKI_CONFIG_VAR_U32(RProbeReflectionResolution, 128, 4, 2048, "Reflection probe face resolution")
 ANKI_CONFIG_VAR_U32(RProbeReflectionResolution, 128, 4, 2048, "Reflection probe face resolution")
 ANKI_CONFIG_VAR_U32(RProbeReflectionIrradianceResolution, 16, 4, 2048, "Reflection probe irradiance resolution")
 ANKI_CONFIG_VAR_U32(RProbeReflectionIrradianceResolution, 16, 4, 2048, "Reflection probe irradiance resolution")
 ANKI_CONFIG_VAR_U32(RProbeRefectionMaxCachedProbes, 32, 4, 256, "Max cached number of reflection probes")
 ANKI_CONFIG_VAR_U32(RProbeRefectionMaxCachedProbes, 32, 4, 256, "Max cached number of reflection probes")
 ANKI_CONFIG_VAR_U32(RProbeReflectionShadowMapResolution, 64, 4, 2048, "Reflection probe shadow resolution")
 ANKI_CONFIG_VAR_U32(RProbeReflectionShadowMapResolution, 64, 4, 2048, "Reflection probe shadow resolution")
 
 
+// Lens flare
 ANKI_CONFIG_VAR_U8(RLensFlareMaxSpritesPerFlare, 8, 4, 255, "Max sprites per lens flare")
 ANKI_CONFIG_VAR_U8(RLensFlareMaxSpritesPerFlare, 8, 4, 255, "Max sprites per lens flare")
 ANKI_CONFIG_VAR_U8(RLensFlareMaxFlares, 16, 8, 255, "Max flare count")
 ANKI_CONFIG_VAR_U8(RLensFlareMaxFlares, 16, 8, 255, "Max flare count")
 
 
-ANKI_CONFIG_VAR_U32(RGiTileResolution, (ANKI_PLATFORM_MOBILE) ? 16 : 32, 4, 2048, "GI tile resolution")
-ANKI_CONFIG_VAR_U32(RGiShadowMapResolution, 128, 4, 2048, "GI shadowmap resolution")
-ANKI_CONFIG_VAR_U32(RGiMaxCachedProbes, 16, 4, 2048, "Max cached probes")
-ANKI_CONFIG_VAR_U32(RGiMaxVisibleProbes, 8, 1, 256, "Max visible GI probes")
-
 ANKI_CONFIG_VAR_U32(RMotionBlurSamples, 32, 1, 2048, "Max motion blur samples")
 ANKI_CONFIG_VAR_U32(RMotionBlurSamples, 32, 1, 2048, "Max motion blur samples")
 
 
 ANKI_CONFIG_VAR_BOOL(RDbgEnabled, false, "Enable or not debugging")
 ANKI_CONFIG_VAR_BOOL(RDbgEnabled, false, "Enable or not debugging")

+ 1 - 1
AnKi/Renderer/Dbg.cpp

@@ -72,7 +72,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	dctx.m_frameAllocator = ctx.m_tempAllocator;
 	dctx.m_frameAllocator = ctx.m_tempAllocator;
 	dctx.m_commandBuffer = cmdb;
 	dctx.m_commandBuffer = cmdb;
 	dctx.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
 	dctx.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
-	dctx.m_key = RenderingKey(Pass::FS, 0, 1, false, false);
+	dctx.m_key = RenderingKey(RenderingTechnique::FORWARD, 0, 1, false, false);
 	dctx.m_debugDraw = true;
 	dctx.m_debugDraw = true;
 	dctx.m_debugDrawFlags = m_debugDrawFlags;
 	dctx.m_debugDrawFlags = m_debugDrawFlags;
 
 

+ 4 - 13
AnKi/Renderer/DepthDownscale.cpp

@@ -62,14 +62,13 @@ Error DepthDownscale::initInternal()
 
 
 		TextureInitInfo texInit = m_r->create2DRenderTargetInitInfo(width, height, Format::R32_SFLOAT, usage, "HiZ");
 		TextureInitInfo texInit = m_r->create2DRenderTargetInitInfo(width, height, Format::R32_SFLOAT, usage, "HiZ");
 		texInit.m_mipmapCount = U8(m_mipCount);
 		texInit.m_mipmapCount = U8(m_mipCount);
-		texInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		m_hizTex = m_r->createAndClearRenderTarget(texInit);
+		m_hizTex = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	// Progs
 	// Progs
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/DepthDownscaleCompute.ankiprog", m_prog));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/DepthDownscaleCompute.ankiprogbin", m_prog));
 
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		variantInitInfo.addMutation("WAVE_OPERATIONS", 0);
 		variantInitInfo.addMutation("WAVE_OPERATIONS", 0);
@@ -80,7 +79,7 @@ Error DepthDownscale::initInternal()
 	}
 	}
 	else
 	else
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/DepthDownscaleRaster.ankiprog", m_prog));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/DepthDownscaleRaster.ankiprogbin", m_prog));
 
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		variantInitInfo.addMutation("REDUCTION_SAMPLER", supportsReductionSampler);
 		variantInitInfo.addMutation("REDUCTION_SAMPLER", supportsReductionSampler);
@@ -260,15 +259,7 @@ void DepthDownscale::runCompute(RenderPassWorkContext& rgraphCtx)
 	SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo);
 	SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo);
 	SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo, m_mipCount);
 	SpdSetup(dispatchThreadGroupCountXY, workGroupOffset, numWorkGroupsAndMips, rectInfo, m_mipCount);
 
 
-	class PC
-	{
-	public:
-		U32 m_workgroupCount;
-		U32 m_mipmapCount;
-		Vec2 m_srcTexSizeOverOne;
-		U32 m_lastMipWidth;
-		U32 m_padding[3u];
-	} pc;
+	DepthDownscaleUniforms pc;
 	pc.m_workgroupCount = numWorkGroupsAndMips[0];
 	pc.m_workgroupCount = numWorkGroupsAndMips[0];
 	pc.m_mipmapCount = numWorkGroupsAndMips[1];
 	pc.m_mipmapCount = numWorkGroupsAndMips[1];
 	pc.m_srcTexSizeOverOne = 1.0f / Vec2(m_r->getInternalResolution());
 	pc.m_srcTexSizeOverOne = 1.0f / Vec2(m_r->getInternalResolution());

+ 4 - 4
AnKi/Renderer/DownscaleBlur.cpp

@@ -50,8 +50,7 @@ Error DownscaleBlur::initInternal()
 		texinit.m_usage |= TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 		texinit.m_usage |= TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 	}
 	}
 	texinit.m_mipmapCount = U8(m_passCount);
 	texinit.m_mipmapCount = U8(m_passCount);
-	texinit.m_initialUsage = TextureUsageBit::SAMPLED_COMPUTE;
-	m_rtTex = m_r->createAndClearRenderTarget(texinit);
+	m_rtTex = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_COMPUTE);
 
 
 	// FB descr
 	// FB descr
 	if(!preferCompute)
 	if(!preferCompute)
@@ -66,8 +65,9 @@ Error DownscaleBlur::initInternal()
 	}
 	}
 
 
 	// Shader programs
 	// Shader programs
-	ANKI_CHECK(getResourceManager().loadResource(
-		(preferCompute) ? "Shaders/DownscaleBlurCompute.ankiprog" : "Shaders/DownscaleBlurRaster.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/DownscaleBlurCompute.ankiprogbin"
+																 : "ShaderBinaries/DownscaleBlurRaster.ankiprogbin",
+												 m_prog));
 	const ShaderProgramResourceVariant* variant = nullptr;
 	const ShaderProgramResourceVariant* variant = nullptr;
 	m_prog->getOrCreateVariant(variant);
 	m_prog->getOrCreateVariant(variant);
 	m_grProg = variant->getProgram();
 	m_grProg = variant->getProgram();

+ 24 - 19
AnKi/Renderer/Drawer.cpp

@@ -39,23 +39,31 @@ RenderableDrawer::~RenderableDrawer()
 {
 {
 }
 }
 
 
-void RenderableDrawer::drawRange(Pass pass, const Mat4& viewMat, const Mat4& viewProjMat, const Mat4& prevViewProjMat,
-								 CommandBufferPtr cmdb, SamplerPtr sampler, const RenderableQueueElement* begin,
-								 const RenderableQueueElement* end, U32 minLod, U32 maxLod)
+void RenderableDrawer::drawRange(RenderingTechnique technique, const Mat4& viewMat, const Mat4& viewProjMat,
+								 const Mat4& prevViewProjMat, CommandBufferPtr cmdb, SamplerPtr sampler,
+								 const RenderableQueueElement* begin, const RenderableQueueElement* end, U32 minLod,
+								 U32 maxLod)
 {
 {
 	ANKI_ASSERT(begin && end && begin < end);
 	ANKI_ASSERT(begin && end && begin < end);
 
 
-	// Allocate and set global uniforms
-	StagingGpuMemoryToken globalUniformsToken;
-	MaterialGlobalUniforms* globalIniforms =
-		static_cast<MaterialGlobalUniforms*>(m_r->getStagingGpuMemory().allocateFrame(
-			sizeof(MaterialGlobalUniforms), StagingGpuMemoryType::UNIFORM, globalUniformsToken));
-	memcpy(&globalIniforms->m_viewProjectionMatrix[0], &viewProjMat, sizeof(viewProjMat));
-	const Mat3x4 viewMat3x4(viewMat);
-	memcpy(&globalIniforms->m_viewMatrix[0], &viewMat3x4, sizeof(viewMat3x4));
-	globalIniforms->m_viewRotationMatrix = viewMat.getRotationPart();
-	const Mat3 camRotationMatrix = viewMat.getInverse().getRotationPart();
-	globalIniforms->m_cameraRotationMatrix = camRotationMatrix;
+	// Allocate, set and bind global uniforms
+	{
+		StagingGpuMemoryToken globalUniformsToken;
+		MaterialGlobalUniforms* globalUniforms =
+			static_cast<MaterialGlobalUniforms*>(m_r->getStagingGpuMemory().allocateFrame(
+				sizeof(MaterialGlobalUniforms), StagingGpuMemoryType::UNIFORM, globalUniformsToken));
+		globalUniforms->m_viewProjectionMatrix = viewProjMat;
+
+		globalUniforms->m_viewMatrix = Mat3x4(viewMat);
+		globalUniforms->m_cameraTransform = Mat3x4(viewMat.getInverse());
+
+		cmdb->bindUniformBuffer(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_GLOBAL_UNIFORMS, globalUniformsToken.m_buffer,
+								globalUniformsToken.m_offset, globalUniformsToken.m_range);
+	}
+
+	// More globals
+	cmdb->bindAllBindless(MATERIAL_SET_BINDLESS);
+	cmdb->bindSampler(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_TRILINEAR_REPEAT_SAMPLER, sampler);
 
 
 	// Set a few things
 	// Set a few things
 	DrawContext ctx;
 	DrawContext ctx;
@@ -66,12 +74,9 @@ void RenderableDrawer::drawRange(Pass pass, const Mat4& viewMat, const Mat4& vie
 	ctx.m_queueCtx.m_cameraTransform = ctx.m_queueCtx.m_viewMatrix.getInverse();
 	ctx.m_queueCtx.m_cameraTransform = ctx.m_queueCtx.m_viewMatrix.getInverse();
 	ctx.m_queueCtx.m_stagingGpuAllocator = &m_r->getStagingGpuMemory();
 	ctx.m_queueCtx.m_stagingGpuAllocator = &m_r->getStagingGpuMemory();
 	ctx.m_queueCtx.m_commandBuffer = cmdb;
 	ctx.m_queueCtx.m_commandBuffer = cmdb;
-	ctx.m_queueCtx.m_sampler = sampler;
-	ctx.m_queueCtx.m_key = RenderingKey(pass, 0, 1, false, false);
+	ctx.m_queueCtx.m_key = RenderingKey(technique, 0, 1, false, false);
 	ctx.m_queueCtx.m_debugDraw = false;
 	ctx.m_queueCtx.m_debugDraw = false;
-	ctx.m_queueCtx.m_globalUniforms.m_buffer = globalUniformsToken.m_buffer;
-	ctx.m_queueCtx.m_globalUniforms.m_offset = globalUniformsToken.m_offset;
-	ctx.m_queueCtx.m_globalUniforms.m_range = globalUniformsToken.m_range;
+	ctx.m_queueCtx.m_sampler = sampler;
 
 
 	ANKI_ASSERT(minLod < MAX_LOD_COUNT && maxLod < MAX_LOD_COUNT);
 	ANKI_ASSERT(minLod < MAX_LOD_COUNT && maxLod < MAX_LOD_COUNT);
 	ctx.m_minLod = U8(minLod);
 	ctx.m_minLod = U8(minLod);

+ 4 - 3
AnKi/Renderer/Drawer.h

@@ -31,9 +31,10 @@ public:
 
 
 	~RenderableDrawer();
 	~RenderableDrawer();
 
 
-	void drawRange(Pass pass, const Mat4& viewMat, const Mat4& viewProjMat, const Mat4& prevViewProjMat,
-				   CommandBufferPtr cmdb, SamplerPtr sampler, const RenderableQueueElement* begin,
-				   const RenderableQueueElement* end, U32 minLod = 0, U32 maxLod = MAX_LOD_COUNT - 1);
+	void drawRange(RenderingTechnique technique, const Mat4& viewMat, const Mat4& viewProjMat,
+				   const Mat4& prevViewProjMat, CommandBufferPtr cmdb, SamplerPtr sampler,
+				   const RenderableQueueElement* begin, const RenderableQueueElement* end, U32 minLod = 0,
+				   U32 maxLod = MAX_LOD_COUNT - 1);
 
 
 private:
 private:
 	Renderer* m_r;
 	Renderer* m_r;

+ 4 - 5
AnKi/Renderer/FinalComposite.cpp

@@ -40,7 +40,7 @@ Error FinalComposite::initInternal()
 	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoise));
 	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoise));
 
 
 	// Progs
 	// Progs
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/FinalComposite.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/FinalComposite.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addMutation("BLUE_NOISE", 1);
 	variantInitInfo.addMutation("BLUE_NOISE", 1);
@@ -57,7 +57,7 @@ Error FinalComposite::initInternal()
 		m_grProgs[dbg] = variant->getProgram();
 		m_grProgs[dbg] = variant->getProgram();
 	}
 	}
 
 
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/VisualizeRenderTarget.ankiprog",
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/VisualizeRenderTarget.ankiprogbin",
 												 m_defaultVisualizeRenderTargetProg));
 												 m_defaultVisualizeRenderTargetProg));
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_defaultVisualizeRenderTargetProg->getOrCreateVariant(variant);
 	m_defaultVisualizeRenderTargetProg->getOrCreateVariant(variant);
@@ -167,9 +167,8 @@ void FinalComposite::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 			rgraphCtx.bindColorTexture(0, 9, m_r->getDbg().getRt());
 			rgraphCtx.bindColorTexture(0, 9, m_r->getDbg().getRt());
 		}
 		}
 
 
-		UVec4 frameCountPad3;
-		frameCountPad3.x() = m_r->getFrameCount() & MAX_U32;
-		cmdb->setPushConstants(&frameCountPad3, sizeof(frameCountPad3));
+		const UVec4 frameCount(m_r->getFrameCount() & MAX_U32);
+		cmdb->setPushConstants(&frameCount, sizeof(frameCount));
 	}
 	}
 	else
 	else
 	{
 	{

+ 14 - 9
AnKi/Renderer/ForwardShading.cpp

@@ -12,6 +12,7 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
+#include <AnKi/Shaders/Include/MaterialTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -34,19 +35,23 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 		cmdb->setBlendFactors(0, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA);
 		cmdb->setBlendFactors(0, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA);
 
 
 		const ClusteredShadingContext& rsrc = ctx.m_clusteredShading;
 		const ClusteredShadingContext& rsrc = ctx.m_clusteredShading;
-		cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
+		const U32 set = MATERIAL_SET_GLOBAL;
+		cmdb->bindSampler(set, MATERIAL_BINDING_LINEAR_CLAMP_SAMPLER, m_r->getSamplers().m_trilinearClamp);
 
 
-		rgraphCtx.bindTexture(0, 1, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
-		rgraphCtx.bindColorTexture(0, 2, m_r->getVolumetricLightingAccumulation().getRt());
+		rgraphCtx.bindTexture(set, MATERIAL_BINDING_DEPTH_RT, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
+		rgraphCtx.bindColorTexture(set, MATERIAL_BINDING_LIGHT_VOLUME,
+								   m_r->getVolumetricLightingAccumulation().getRt());
 
 
-		bindUniforms(cmdb, 0, 3, rsrc.m_clusteredShadingUniformsToken);
-		bindUniforms(cmdb, 0, 4, rsrc.m_pointLightsToken);
-		bindUniforms(cmdb, 0, 5, rsrc.m_spotLightsToken);
-		rgraphCtx.bindColorTexture(0, 6, m_r->getShadowMapping().getShadowmapRt());
-		bindStorage(cmdb, 0, 7, rsrc.m_clustersToken);
+		bindUniforms(cmdb, set, MATERIAL_BINDING_CLUSTER_SHADING_UNIFORMS, rsrc.m_clusteredShadingUniformsToken);
+		bindUniforms(cmdb, set, MATERIAL_BINDING_CLUSTER_SHADING_LIGHTS, rsrc.m_pointLightsToken);
+		bindUniforms(cmdb, set, MATERIAL_BINDING_CLUSTER_SHADING_LIGHTS + 1, rsrc.m_spotLightsToken);
+		rgraphCtx.bindColorTexture(set, MATERIAL_BINDING_CLUSTER_SHADING_LIGHTS + 2,
+								   m_r->getShadowMapping().getShadowmapRt());
+		bindStorage(cmdb, set, MATERIAL_BINDING_CLUSTERS, rsrc.m_clustersToken);
 
 
 		// Start drawing
 		// Start drawing
-		m_r->getSceneDrawer().drawRange(Pass::FS, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::FORWARD, ctx.m_matrices.m_view,
+										ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_prevMatrices.m_viewProjectionJitter, cmdb,
 										ctx.m_prevMatrices.m_viewProjectionJitter, cmdb,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + start,
 										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + start,

+ 5 - 5
AnKi/Renderer/GBuffer.cpp

@@ -41,9 +41,7 @@ Error GBuffer::initInternal()
 			m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), m_r->getDepthNoStencilFormat(),
 			m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), m_r->getDepthNoStencilFormat(),
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, depthRtNames[i]);
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, depthRtNames[i]);
 
 
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-
-		m_depthRts[i] = m_r->createAndClearRenderTarget(texinit);
+		m_depthRts[i] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	static const Array<const char*, GBUFFER_COLOR_ATTACHMENT_COUNT> rtNames = {
 	static const Array<const char*, GBUFFER_COLOR_ATTACHMENT_COUNT> rtNames = {
@@ -128,7 +126,8 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		}
 		}
 
 
 		ANKI_ASSERT(earlyZStart < earlyZEnd && earlyZEnd <= I32(earlyZCount));
 		ANKI_ASSERT(earlyZStart < earlyZEnd && earlyZEnd <= I32(earlyZCount));
-		m_r->getSceneDrawer().drawRange(Pass::EZ, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER_EARLY_Z, ctx.m_matrices.m_view,
+										ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZStart,
 										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZStart,
@@ -150,7 +149,8 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		cmdb->setDepthCompareOperation(CompareOperation::LESS_EQUAL);
 		cmdb->setDepthCompareOperation(CompareOperation::LESS_EQUAL);
 
 
 		ANKI_ASSERT(colorStart < colorEnd && colorEnd <= I32(ctx.m_renderQueue->m_renderables.getSize()));
 		ANKI_ASSERT(colorStart < colorEnd && colorEnd <= I32(ctx.m_renderQueue->m_renderables.getSize()));
-		m_r->getSceneDrawer().drawRange(Pass::GB, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, ctx.m_matrices.m_view,
+										ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_renderables.getBegin() + colorStart,
 										ctx.m_renderQueue->m_renderables.getBegin() + colorStart,

+ 6 - 6
AnKi/Renderer/GBuffer.h

@@ -20,9 +20,9 @@ public:
 	GBuffer(Renderer* r)
 	GBuffer(Renderer* r)
 		: RendererObject(r)
 		: RendererObject(r)
 	{
 	{
-		registerDebugRenderTarget("GBuffer_normals");
-		registerDebugRenderTarget("GBuffer_albedo");
-		registerDebugRenderTarget("GBuffer_velocity");
+		registerDebugRenderTarget("GBufferNormals");
+		registerDebugRenderTarget("GBufferAlbedo");
+		registerDebugRenderTarget("GBufferVelocity");
 	}
 	}
 
 
 	~GBuffer();
 	~GBuffer();
@@ -50,15 +50,15 @@ public:
 	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
 	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
 							  ShaderProgramPtr& optionalShaderProgram) const override
 							  ShaderProgramPtr& optionalShaderProgram) const override
 	{
 	{
-		if(rtName == "GBuffer_albedo")
+		if(rtName == "GBufferAlbedo")
 		{
 		{
 			handle = m_runCtx.m_colorRts[0];
 			handle = m_runCtx.m_colorRts[0];
 		}
 		}
-		else if(rtName == "GBuffer_normals")
+		else if(rtName == "GBufferNormals")
 		{
 		{
 			handle = m_runCtx.m_colorRts[2];
 			handle = m_runCtx.m_colorRts[2];
 		}
 		}
-		else if(rtName == "GBuffer_velocity")
+		else if(rtName == "GBufferVelocity")
 		{
 		{
 			handle = m_runCtx.m_colorRts[3];
 			handle = m_runCtx.m_colorRts[3];
 		}
 		}

+ 1 - 1
AnKi/Renderer/GBufferPost.cpp

@@ -29,7 +29,7 @@ Error GBufferPost::initInternal()
 	ANKI_R_LOGV("Initializing GBufferPost pass");
 	ANKI_R_LOGV("Initializing GBufferPost pass");
 
 
 	// Load shaders
 	// Load shaders
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/GBufferPost.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/GBufferPost.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("TILE_COUNTS", m_r->getTileCounts());
 	variantInitInfo.addConstant("TILE_COUNTS", m_r->getTileCounts());

+ 7 - 8
AnKi/Renderer/IndirectDiffuse.cpp

@@ -11,7 +11,6 @@
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
-#include <AnKi/Shaders/Include/IndirectDiffuseTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -44,10 +43,9 @@ Error IndirectDiffuse::initInternal()
 	usage |= (preferCompute) ? TextureUsageBit::IMAGE_COMPUTE_WRITE : TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 	usage |= (preferCompute) ? TextureUsageBit::IMAGE_COMPUTE_WRITE : TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 	TextureInitInfo texInit =
 	TextureInitInfo texInit =
 		m_r->create2DRenderTargetInitInfo(size.x(), size.y(), m_r->getHdrFormat(), usage, "IndirectDiffuse #1");
 		m_r->create2DRenderTargetInitInfo(size.x(), size.y(), m_r->getHdrFormat(), usage, "IndirectDiffuse #1");
-	texInit.m_initialUsage = TextureUsageBit::ALL_SAMPLED;
-	m_rts[0] = m_r->createAndClearRenderTarget(texInit);
+	m_rts[0] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
 	texInit.setName("IndirectDiffuse #2");
 	texInit.setName("IndirectDiffuse #2");
-	m_rts[1] = m_r->createAndClearRenderTarget(texInit);
+	m_rts[1] = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::ALL_SAMPLED);
 
 
 	// Init VRS SRI generation
 	// Init VRS SRI generation
 	{
 	{
@@ -87,8 +85,9 @@ Error IndirectDiffuse::initInternal()
 
 
 	// Init SSGI+probes pass
 	// Init SSGI+probes pass
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "Shaders/IndirectDiffuseCompute.ankiprog"
-																	 : "Shaders/IndirectDiffuseRaster.ankiprog",
+		ANKI_CHECK(getResourceManager().loadResource((preferCompute)
+														 ? "ShaderBinaries/IndirectDiffuseCompute.ankiprogbin"
+														 : "ShaderBinaries/IndirectDiffuseRaster.ankiprogbin",
 													 m_main.m_prog));
 													 m_main.m_prog));
 
 
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
@@ -101,8 +100,8 @@ Error IndirectDiffuse::initInternal()
 		m_denoise.m_fbDescr.m_colorAttachmentCount = 1;
 		m_denoise.m_fbDescr.m_colorAttachmentCount = 1;
 		m_denoise.m_fbDescr.bake();
 		m_denoise.m_fbDescr.bake();
 
 
-		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "Shaders/IndirectDiffuseDenoiseCompute.ankiprog"
-																	 : "Shaders/IndirectDiffuseDenoiseRaster.ankiprog",
+		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/IndirectDiffuseDenoiseCompute.ankiprog"
+																	 : "ShaderBinaries/IndirectDiffuseDenoiseRaster.ankiprog",
 													 m_denoise.m_prog));
 													 m_denoise.m_prog));
 
 
 		ShaderProgramResourceVariantInitInfo variantInit(m_denoise.m_prog);
 		ShaderProgramResourceVariantInitInfo variantInit(m_denoise.m_prog);

+ 12 - 14
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -108,9 +108,9 @@ Error IndirectDiffuseProbes::init()
 
 
 Error IndirectDiffuseProbes::initInternal()
 Error IndirectDiffuseProbes::initInternal()
 {
 {
-	m_tileSize = getConfig().getRGiTileResolution();
-	m_cacheEntries.create(getAllocator(), getConfig().getRGiMaxCachedProbes());
-	m_maxVisibleProbes = getConfig().getRGiMaxVisibleProbes();
+	m_tileSize = getConfig().getRIndirectDiffuseProbeTileResolution();
+	m_cacheEntries.create(getAllocator(), getConfig().getRIndirectDiffuseProbeMaxCachedProbes());
+	m_maxVisibleProbes = getConfig().getRIndirectDiffuseProbeMaxVisibleProbes();
 	ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
 	ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
 	ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
 	ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
 
 
@@ -166,7 +166,7 @@ Error IndirectDiffuseProbes::initGBuffer()
 
 
 Error IndirectDiffuseProbes::initShadowMapping()
 Error IndirectDiffuseProbes::initShadowMapping()
 {
 {
-	const U32 resolution = getConfig().getRGiShadowMapResolution();
+	const U32 resolution = getConfig().getRIndirectDiffuseProbeShadowMapResolution();
 	ANKI_ASSERT(resolution > 8);
 	ANKI_ASSERT(resolution > 8);
 
 
 	// RT descr
 	// RT descr
@@ -208,7 +208,8 @@ Error IndirectDiffuseProbes::initLightShading()
 
 
 Error IndirectDiffuseProbes::initIrradiance()
 Error IndirectDiffuseProbes::initIrradiance()
 {
 {
-	ANKI_CHECK(m_r->getResourceManager().loadResource("Shaders/IrradianceDice.ankiprog", m_irradiance.m_prog));
+	ANKI_CHECK(
+		m_r->getResourceManager().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
 	variantInitInfo.addMutation("WORKGROUP_SIZE_XY", m_tileSize);
 	variantInitInfo.addMutation("WORKGROUP_SIZE_XY", m_tileSize);
@@ -484,9 +485,8 @@ void IndirectDiffuseProbes::prepareProbes(InternalContext& giCtx)
 			texInit.m_height = probe.m_cellCounts.y();
 			texInit.m_height = probe.m_cellCounts.y();
 			texInit.m_depth = probe.m_cellCounts.z();
 			texInit.m_depth = probe.m_cellCounts.z();
 			texInit.m_usage = TextureUsageBit::ALL_COMPUTE | TextureUsageBit::ALL_SAMPLED;
 			texInit.m_usage = TextureUsageBit::ALL_COMPUTE | TextureUsageBit::ALL_SAMPLED;
-			texInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 
 
-			entry.m_volumeTex = m_r->createAndClearRenderTarget(texInit);
+			entry.m_volumeTex = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::SAMPLED_FRAGMENT);
 		}
 		}
 
 
 		// Compute the render position
 		// Compute the render position
@@ -570,7 +570,7 @@ void IndirectDiffuseProbes::runGBufferInThread(RenderPassWorkContext& rgraphCtx,
 
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			m_r->getSceneDrawer().drawRange(
 			m_r->getSceneDrawer().drawRange(
-				Pass::GB, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
+				RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
 				Mat4::getIdentity(), // Don't care about prev mats since we don't care about velocity
 				Mat4::getIdentity(), // Don't care about prev mats since we don't care about velocity
 				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
 				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
 				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
 				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
@@ -621,7 +621,7 @@ void IndirectDiffuseProbes::runShadowmappingInThread(RenderPassWorkContext& rgra
 
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			m_r->getSceneDrawer().drawRange(
 			m_r->getSceneDrawer().drawRange(
-				Pass::SM, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
+				RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
 				Mat4::getIdentity(), // Don't care about prev matrices here
 				Mat4::getIdentity(), // Don't care about prev matrices here
 				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
 				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
 				cascadeRenderQueue.m_renderables.getBegin() + localStart,
 				cascadeRenderQueue.m_renderables.getBegin() + localStart,
@@ -701,13 +701,11 @@ void IndirectDiffuseProbes::runIrradiance(RenderPassWorkContext& rgraphCtx, Inte
 		rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
 		rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
 	}
 	}
 
 
-	// Bind temporary memory
-	allocateAndBindStorage<void*>(sizeof(Vec4) * 6 * m_tileSize * m_tileSize, cmdb, 0, 3);
+	rgraphCtx.bindImage(0, 3, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
 
 
-	rgraphCtx.bindImage(0, 4, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
-
-	struct
+	class
 	{
 	{
+	public:
 		IVec3 m_volumeTexel;
 		IVec3 m_volumeTexel;
 		I32 m_nextTexelOffsetInU;
 		I32 m_nextTexelOffsetInU;
 	} unis;
 	} unis;

+ 2 - 3
AnKi/Renderer/IndirectSpecular.cpp

@@ -11,7 +11,6 @@
 #include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/RenderQueue.h>
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
-#include <AnKi/Shaders/Include/SsrTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -47,8 +46,8 @@ Error IndirectSpecular::initInternal()
 
 
 	// Create shader
 	// Create shader
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
-													 ? "Shaders/IndirectSpecularCompute.ankiprog"
-													 : "Shaders/IndirectSpecularRaster.ankiprog",
+													 ? "ShaderBinaries/IndirectSpecularCompute.ankiprogbin"
+													 : "ShaderBinaries/IndirectSpecularRaster.ankiprogbin",
 												 m_prog));
 												 m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInit(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInit(m_prog);

+ 3 - 4
AnKi/Renderer/LensFlare.cpp

@@ -9,7 +9,6 @@
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/Functions.h>
-#include <AnKi/Shaders/Include/LensFlareTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -52,7 +51,7 @@ Error LensFlare::initSprite()
 	m_maxSprites = U16(m_maxSpritesPerFlare * m_maxFlares);
 	m_maxSprites = U16(m_maxSpritesPerFlare * m_maxFlares);
 
 
 	// Load prog
 	// Load prog
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/LensFlareSprite.ankiprog", m_realProg));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LensFlareSprite.ankiprogbin", m_realProg));
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_realProg->getOrCreateVariant(variant);
 	m_realProg->getOrCreateVariant(variant);
 	m_realGrProg = variant->getProgram();
 	m_realGrProg = variant->getProgram();
@@ -68,8 +67,8 @@ Error LensFlare::initOcclusion()
 												 BufferUsageBit::INDIRECT_DRAW | BufferUsageBit::STORAGE_COMPUTE_WRITE,
 												 BufferUsageBit::INDIRECT_DRAW | BufferUsageBit::STORAGE_COMPUTE_WRITE,
 												 BufferMapAccessBit::NONE, "LensFlares"));
 												 BufferMapAccessBit::NONE, "LensFlares"));
 
 
-	ANKI_CHECK(
-		getResourceManager().loadResource("Shaders/LensFlareUpdateIndirectInfo.ankiprog", m_updateIndirectBuffProg));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LensFlareUpdateIndirectInfo.ankiprogbin",
+												 m_updateIndirectBuffProg));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_updateIndirectBuffProg);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_updateIndirectBuffProg);
 	variantInitInfo.addConstant(
 	variantInitInfo.addConstant(

+ 5 - 4
AnKi/Renderer/LightShading.cpp

@@ -62,7 +62,7 @@ Error LightShading::init()
 Error LightShading::initLightShading()
 Error LightShading::initLightShading()
 {
 {
 	// Load shaders and programs
 	// Load shaders and programs
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/LightShading.ankiprog", m_lightShading.m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LightShading.ankiprogbin", m_lightShading.m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_lightShading.m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_lightShading.m_prog);
 	variantInitInfo.addConstant("TILE_COUNTS", m_r->getTileCounts());
 	variantInitInfo.addConstant("TILE_COUNTS", m_r->getTileCounts());
@@ -102,7 +102,7 @@ Error LightShading::initLightShading()
 
 
 Error LightShading::initSkybox()
 Error LightShading::initSkybox()
 {
 {
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/LightShadingSkybox.ankiprog", m_skybox.m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LightShadingSkybox.ankiprogbin", m_skybox.m_prog));
 
 
 	for(U32 method = 0; method < 2; ++method)
 	for(U32 method = 0; method < 2; ++method)
 	{
 	{
@@ -120,7 +120,7 @@ Error LightShading::initSkybox()
 Error LightShading::initApplyFog()
 Error LightShading::initApplyFog()
 {
 {
 	// Load shaders and programs
 	// Load shaders and programs
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/LightShadingApplyFog.ankiprog", m_applyFog.m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LightShadingApplyFog.ankiprogbin", m_applyFog.m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_applyFog.m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_applyFog.m_prog);
 	variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
 	variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
@@ -135,7 +135,8 @@ Error LightShading::initApplyFog()
 
 
 Error LightShading::initApplyIndirect()
 Error LightShading::initApplyIndirect()
 {
 {
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/LightShadingApplyIndirect.ankiprog", m_applyIndirect.m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/LightShadingApplyIndirect.ankiprogbin",
+												 m_applyIndirect.m_prog));
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_applyIndirect.m_prog->getOrCreateVariant(variant);
 	m_applyIndirect.m_prog->getOrCreateVariant(variant);
 	m_applyIndirect.m_grProg = variant->getProgram();
 	m_applyIndirect.m_grProg = variant->getProgram();

+ 1 - 1
AnKi/Renderer/MainRenderer.cpp

@@ -46,7 +46,7 @@ Error MainRenderer::init(const MainRendererInitInfo& inf)
 	// Init other
 	// Init other
 	if(!m_rDrawToDefaultFb)
 	if(!m_rDrawToDefaultFb)
 	{
 	{
-		ANKI_CHECK(inf.m_resourceManager->loadResource("Shaders/BlitRaster.ankiprog", m_blitProg));
+		ANKI_CHECK(inf.m_resourceManager->loadResource("ShaderBinaries/BlitRaster.ankiprogbin", m_blitProg));
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
 		m_blitProg->getOrCreateVariant(variant);
 		m_blitProg->getOrCreateVariant(variant);
 		m_blitGrProg = variant->getProgram();
 		m_blitGrProg = variant->getProgram();

+ 4 - 5
AnKi/Renderer/MotionVectors.cpp

@@ -31,8 +31,8 @@ Error MotionVectors::initInternal()
 
 
 	// Prog
 	// Prog
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
-													 ? "Shaders/MotionVectorsCompute.ankiprog"
-													 : "Shaders/MotionVectorsRaster.ankiprog",
+													 ? "ShaderBinaries/MotionVectorsCompute.ankiprogbin"
+													 : "ShaderBinaries/MotionVectorsRaster.ankiprogbin",
 												 m_prog));
 												 m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
 	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
@@ -58,10 +58,9 @@ Error MotionVectors::initInternal()
 	TextureInitInfo historyLengthTexInit =
 	TextureInitInfo historyLengthTexInit =
 		m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
 		m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
 										  Format::R8_UNORM, historyLengthUsage, "MotionVectorsHistoryLen#1");
 										  Format::R8_UNORM, historyLengthUsage, "MotionVectorsHistoryLen#1");
-	historyLengthTexInit.m_initialUsage = TextureUsageBit::ALL_SAMPLED;
-	m_historyLengthTextures[0] = m_r->createAndClearRenderTarget(historyLengthTexInit);
+	m_historyLengthTextures[0] = m_r->createAndClearRenderTarget(historyLengthTexInit, TextureUsageBit::ALL_SAMPLED);
 	historyLengthTexInit.setName("MotionVectorsHistoryLen#2");
 	historyLengthTexInit.setName("MotionVectorsHistoryLen#2");
-	m_historyLengthTextures[1] = m_r->createAndClearRenderTarget(historyLengthTexInit);
+	m_historyLengthTextures[1] = m_r->createAndClearRenderTarget(historyLengthTexInit, TextureUsageBit::ALL_SAMPLED);
 
 
 	m_fbDescr.m_colorAttachmentCount = 2;
 	m_fbDescr.m_colorAttachmentCount = 2;
 	m_fbDescr.bake();
 	m_fbDescr.bake();

+ 7 - 10
AnKi/Renderer/ProbeReflections.cpp

@@ -125,9 +125,8 @@ Error ProbeReflections::initLightShading()
 		texinit.m_mipmapCount = U8(m_lightShading.m_mipCount);
 		texinit.m_mipmapCount = U8(m_lightShading.m_mipCount);
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_layerCount = m_cacheEntries.getSize();
 		texinit.m_layerCount = m_cacheEntries.getSize();
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 
 
-		m_lightShading.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
+		m_lightShading.m_cubeArr = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	// Init deferred
 	// Init deferred
@@ -142,7 +141,8 @@ Error ProbeReflections::initIrradiance()
 
 
 	// Create prog
 	// Create prog
 	{
 	{
-		ANKI_CHECK(m_r->getResourceManager().loadResource("Shaders/IrradianceDice.ankiprog", m_irradiance.m_prog));
+		ANKI_CHECK(
+			m_r->getResourceManager().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
 
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
 
 
@@ -170,7 +170,7 @@ Error ProbeReflections::initIrradiance()
 Error ProbeReflections::initIrradianceToRefl()
 Error ProbeReflections::initIrradianceToRefl()
 {
 {
 	// Create program
 	// Create program
-	ANKI_CHECK(m_r->getResourceManager().loadResource("Shaders/ApplyIrradianceToReflection.ankiprog",
+	ANKI_CHECK(m_r->getResourceManager().loadResource("ShaderBinaries/ApplyIrradianceToReflection.ankiprogbin",
 													  m_irradianceToRefl.m_prog));
 													  m_irradianceToRefl.m_prog));
 
 
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
@@ -351,7 +351,7 @@ void ProbeReflections::runGBuffer(RenderPassWorkContext& rgraphCtx)
 			const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 			const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			m_r->getSceneDrawer().drawRange(
 			m_r->getSceneDrawer().drawRange(
-				Pass::GB, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
+				RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
 				Mat4::getIdentity(), // Don't care about prev mats
 				Mat4::getIdentity(), // Don't care about prev mats
 				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
 				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
 				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
 				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
@@ -440,10 +440,7 @@ void ProbeReflections::runIrradiance(RenderPassWorkContext& rgraphCtx)
 	subresource.m_firstLayer = cacheEntryIdx;
 	subresource.m_firstLayer = cacheEntryIdx;
 	rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
 	rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
 
 
-	allocateAndBindStorage<void*>(sizeof(Vec4) * 6 * m_irradiance.m_workgroupSize * m_irradiance.m_workgroupSize, cmdb,
-								  0, 3);
-
-	cmdb->bindStorageBuffer(0, 4, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
+	cmdb->bindStorageBuffer(0, 3, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
 
 
 	// Draw
 	// Draw
 	cmdb->dispatchCompute(1, 1, 1);
 	cmdb->dispatchCompute(1, 1, 1);
@@ -724,7 +721,7 @@ void ProbeReflections::runShadowMapping(RenderPassWorkContext& rgraphCtx)
 
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
 			m_r->getSceneDrawer().drawRange(
 			m_r->getSceneDrawer().drawRange(
-				Pass::SM, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
+				RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
 				Mat4::getIdentity(), // Don't care about prev matrices here
 				Mat4::getIdentity(), // Don't care about prev matrices here
 				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
 				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
 				cascadeRenderQueue.m_renderables.getBegin() + localStart,
 				cascadeRenderQueue.m_renderables.getBegin() + localStart,

+ 4 - 12
AnKi/Renderer/RenderQueue.h

@@ -45,14 +45,6 @@ public:
 	StackAllocator<U8> m_frameAllocator;
 	StackAllocator<U8> m_frameAllocator;
 	Bool m_debugDraw; ///< If true the drawcall should be drawing some kind of debug mesh.
 	Bool m_debugDraw; ///< If true the drawcall should be drawing some kind of debug mesh.
 	BitSet<U(RenderQueueDebugDrawFlag::COUNT), U32> m_debugDrawFlags = {false};
 	BitSet<U(RenderQueueDebugDrawFlag::COUNT), U32> m_debugDrawFlags = {false};
-
-	class
-	{
-	public:
-		BufferPtr m_buffer;
-		PtrSize m_offset;
-		PtrSize m_range;
-	} m_globalUniforms; ///< Points to a MaterialGlobalUniforms structure.
 };
 };
 
 
 /// Draw callback for drawing.
 /// Draw callback for drawing.
@@ -367,11 +359,11 @@ class RayTracingInstanceQueueElement final
 {
 {
 public:
 public:
 	AccelerationStructure* m_bottomLevelAccelerationStructure;
 	AccelerationStructure* m_bottomLevelAccelerationStructure;
-	ModelGpuDescriptor m_modelDescriptor;
-	Array<U32, U(RayType::COUNT)> m_shaderGroupHandleIndices;
+	U32 m_shaderGroupHandleIndex;
+
+	Mat3x4 m_transform; // TODO rm when you'll add the RenderableGpuView
 
 
-	/// This points to the GR objects that are m_modelDescriptor is referencing. Use this to add a refcount to avoid
-	/// accidential deletions.
+	/// This points to the GR objects used by this element. Use this to add a refcount to avoid accidential deletions.
 	Array<GrObject*, 8> m_grObjects;
 	Array<GrObject*, 8> m_grObjects;
 	U32 m_grObjectCount;
 	U32 m_grObjectCount;
 };
 };

+ 19 - 20
AnKi/Renderer/Renderer.cpp

@@ -113,28 +113,28 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 		return Error::USER_DATA;
 		return Error::USER_DATA;
 	}
 	}
 
 
+	ANKI_CHECK(m_resources->loadResource("ShaderBinaries/ClearTextureCompute.ankiprogbin", m_clearTexComputeProg));
+
+	// Dummy resources
 	{
 	{
 		TextureInitInfo texinit("RendererDummy");
 		TextureInitInfo texinit("RendererDummy");
 		texinit.m_width = texinit.m_height = 4;
 		texinit.m_width = texinit.m_height = 4;
-		texinit.m_usage = TextureUsageBit::ALL_SAMPLED;
+		texinit.m_usage = TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_COMPUTE_WRITE;
 		texinit.m_format = Format::R8G8B8A8_UNORM;
 		texinit.m_format = Format::R8G8B8A8_UNORM;
-		texinit.m_initialUsage = TextureUsageBit::ALL_SAMPLED;
-		TexturePtr tex = getGrManager().newTexture(texinit);
+		TexturePtr tex = createAndClearRenderTarget(texinit, TextureUsageBit::ALL_SAMPLED);
 
 
 		TextureViewInitInfo viewinit(tex);
 		TextureViewInitInfo viewinit(tex);
 		m_dummyTexView2d = getGrManager().newTextureView(viewinit);
 		m_dummyTexView2d = getGrManager().newTextureView(viewinit);
 
 
 		texinit.m_depth = 4;
 		texinit.m_depth = 4;
 		texinit.m_type = TextureType::_3D;
 		texinit.m_type = TextureType::_3D;
-		tex = getGrManager().newTexture(texinit);
+		tex = createAndClearRenderTarget(texinit, TextureUsageBit::ALL_SAMPLED);
 		viewinit = TextureViewInitInfo(tex);
 		viewinit = TextureViewInitInfo(tex);
 		m_dummyTexView3d = getGrManager().newTextureView(viewinit);
 		m_dummyTexView3d = getGrManager().newTextureView(viewinit);
-	}
-
-	m_dummyBuff = getGrManager().newBuffer(BufferInitInfo(
-		1024, BufferUsageBit::ALL_UNIFORM | BufferUsageBit::ALL_STORAGE, BufferMapAccessBit::NONE, "Dummy"));
 
 
-	ANKI_CHECK(m_resources->loadResource("Shaders/ClearTextureCompute.ankiprog", m_clearTexComputeProg));
+		m_dummyBuff = getGrManager().newBuffer(BufferInitInfo(
+			1024, BufferUsageBit::ALL_UNIFORM | BufferUsageBit::ALL_STORAGE, BufferMapAccessBit::NONE, "Dummy"));
+	}
 
 
 	// Init the stages. Careful with the order!!!!!!!!!!
 	// Init the stages. Careful with the order!!!!!!!!!!
 	m_genericCompute.reset(m_alloc.newInstance<GenericCompute>(this));
 	m_genericCompute.reset(m_alloc.newInstance<GenericCompute>(this));
@@ -301,7 +301,6 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	ctx.m_matrices.m_view = ctx.m_renderQueue->m_viewMatrix;
 	ctx.m_matrices.m_view = ctx.m_renderQueue->m_viewMatrix;
 	ctx.m_matrices.m_projection = ctx.m_renderQueue->m_projectionMatrix;
 	ctx.m_matrices.m_projection = ctx.m_renderQueue->m_projectionMatrix;
 	ctx.m_matrices.m_viewProjection = ctx.m_renderQueue->m_viewProjectionMatrix;
 	ctx.m_matrices.m_viewProjection = ctx.m_renderQueue->m_viewProjectionMatrix;
-	ctx.m_matrices.m_viewRotation = ctx.m_renderQueue->m_viewMatrix.getRotationPart();
 
 
 	ctx.m_matrices.m_jitter = m_jitteredMats8x[m_frameCount & (m_jitteredMats8x.getSize() - 1)];
 	ctx.m_matrices.m_jitter = m_jitteredMats8x[m_frameCount & (m_jitteredMats8x.getSize() - 1)];
 	ctx.m_matrices.m_projectionJitter = ctx.m_matrices.m_jitter * ctx.m_matrices.m_projection;
 	ctx.m_matrices.m_projectionJitter = ctx.m_matrices.m_jitter * ctx.m_matrices.m_projection;
@@ -433,7 +432,8 @@ RenderTargetDescription Renderer::create2DRenderTargetDescription(U32 w, U32 h,
 	return init;
 	return init;
 }
 }
 
 
-TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, const ClearValue& clearVal)
+TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, TextureUsageBit initialUsage,
+												const ClearValue& clearVal)
 {
 {
 	ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE)
 	ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE)
 				|| !!(inf.m_usage & TextureUsageBit::IMAGE_COMPUTE_WRITE));
 				|| !!(inf.m_usage & TextureUsageBit::IMAGE_COMPUTE_WRITE));
@@ -480,15 +480,15 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, cons
 					Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> colUsage = {};
 					Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> colUsage = {};
 					TextureUsageBit dsUsage = TextureUsageBit::NONE;
 					TextureUsageBit dsUsage = TextureUsageBit::NONE;
 
 
-					if(formatIsDepthStencil(inf.m_format))
+					if(getFormatInfo(inf.m_format).isDepthStencil())
 					{
 					{
 						DepthStencilAspectBit aspect = DepthStencilAspectBit::NONE;
 						DepthStencilAspectBit aspect = DepthStencilAspectBit::NONE;
-						if(formatIsDepth(inf.m_format))
+						if(getFormatInfo(inf.m_format).isDepth())
 						{
 						{
 							aspect |= DepthStencilAspectBit::DEPTH;
 							aspect |= DepthStencilAspectBit::DEPTH;
 						}
 						}
 
 
-						if(formatIsStencil(inf.m_format))
+						if(getFormatInfo(inf.m_format).isStencil())
 						{
 						{
 							aspect |= DepthStencilAspectBit::STENCIL;
 							aspect |= DepthStencilAspectBit::STENCIL;
 						}
 						}
@@ -521,10 +521,10 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, cons
 					cmdb->beginRenderPass(fb, colUsage, dsUsage);
 					cmdb->beginRenderPass(fb, colUsage, dsUsage);
 					cmdb->endRenderPass();
 					cmdb->endRenderPass();
 
 
-					if(!!inf.m_initialUsage)
+					if(!!initialUsage)
 					{
 					{
-						cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-													   inf.m_initialUsage, surf);
+						cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, initialUsage,
+													   surf);
 					}
 					}
 				}
 				}
 				else
 				else
@@ -569,10 +569,9 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, cons
 
 
 					cmdb->dispatchCompute(wgSize.x(), wgSize.y(), wgSize.z());
 					cmdb->dispatchCompute(wgSize.x(), wgSize.y(), wgSize.z());
 
 
-					if(!!inf.m_initialUsage)
+					if(!!initialUsage)
 					{
 					{
-						cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::IMAGE_COMPUTE_WRITE, inf.m_initialUsage,
-													   surf);
+						cmdb->setTextureSurfaceBarrier(tex, TextureUsageBit::IMAGE_COMPUTE_WRITE, initialUsage, surf);
 					}
 					}
 				}
 				}
 			}
 			}

+ 1 - 1
AnKi/Renderer/Renderer.h

@@ -110,7 +110,7 @@ public:
 	ANKI_USE_RESULT RenderTargetDescription create2DRenderTargetDescription(U32 w, U32 h, Format format,
 	ANKI_USE_RESULT RenderTargetDescription create2DRenderTargetDescription(U32 w, U32 h, Format format,
 																			CString name = {});
 																			CString name = {});
 
 
-	ANKI_USE_RESULT TexturePtr createAndClearRenderTarget(const TextureInitInfo& inf,
+	ANKI_USE_RESULT TexturePtr createAndClearRenderTarget(const TextureInitInfo& inf, TextureUsageBit initialUsage,
 														  const ClearValue& clearVal = ClearValue());
 														  const ClearValue& clearVal = ClearValue());
 
 
 	GrManager& getGrManager()
 	GrManager& getGrManager()

+ 14 - 15
AnKi/Renderer/RtShadows.cpp

@@ -42,7 +42,7 @@ Error RtShadows::initInternal()
 
 
 	// Ray gen program
 	// Ray gen program
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsRayGen.ankiprog", m_rayGenProg));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/RtShadowsRayGen.ankiprogbin", m_rayGenProg));
 
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_rayGenProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_rayGenProg);
 		variantInitInfo.addMutation("RAYS_PER_PIXEL", getConfig().getRRtShadowsRaysPerPixel());
 		variantInitInfo.addMutation("RAYS_PER_PIXEL", getConfig().getRRtShadowsRaysPerPixel());
@@ -55,7 +55,7 @@ Error RtShadows::initInternal()
 
 
 	// Miss prog
 	// Miss prog
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsMiss.ankiprog", m_missProg));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/RtShadowsMiss.ankiprogbin", m_missProg));
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
 		m_missProg->getOrCreateVariant(variant);
 		m_missProg->getOrCreateVariant(variant);
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
@@ -64,7 +64,7 @@ Error RtShadows::initInternal()
 	// Denoise program
 	// Denoise program
 	if(!m_useSvgf)
 	if(!m_useSvgf)
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsDenoise.ankiprog", m_denoiseProg));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/RtShadowsDenoise.ankiprogbin", m_denoiseProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_denoiseProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_denoiseProg);
 		variantInitInfo.addConstant("OUT_IMAGE_SIZE",
 		variantInitInfo.addConstant("OUT_IMAGE_SIZE",
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
@@ -84,7 +84,8 @@ Error RtShadows::initInternal()
 	// SVGF variance program
 	// SVGF variance program
 	if(m_useSvgf)
 	if(m_useSvgf)
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfVariance.ankiprog", m_svgfVarianceProg));
+		ANKI_CHECK(
+			getResourceManager().loadResource("ShaderBinaries/RtShadowsSvgfVariance.ankiprogbin", m_svgfVarianceProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfVarianceProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfVarianceProg);
 		variantInitInfo.addConstant("FB_SIZE",
 		variantInitInfo.addConstant("FB_SIZE",
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
@@ -97,7 +98,8 @@ Error RtShadows::initInternal()
 	// SVGF atrous program
 	// SVGF atrous program
 	if(m_useSvgf)
 	if(m_useSvgf)
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsSvgfAtrous.ankiprog", m_svgfAtrousProg));
+		ANKI_CHECK(
+			getResourceManager().loadResource("ShaderBinaries/RtShadowsSvgfAtrous.ankiprogbin", m_svgfAtrousProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfAtrousProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_svgfAtrousProg);
 		variantInitInfo.addConstant("FB_SIZE",
 		variantInitInfo.addConstant("FB_SIZE",
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
 									UVec2(m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2));
@@ -114,7 +116,7 @@ Error RtShadows::initInternal()
 
 
 	// Upscale program
 	// Upscale program
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsUpscale.ankiprog", m_upscaleProg));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/RtShadowsUpscale.ankiprogbin", m_upscaleProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
 		variantInitInfo.addConstant("OUT_IMAGE_SIZE",
 		variantInitInfo.addConstant("OUT_IMAGE_SIZE",
 									UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
 									UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
@@ -125,7 +127,7 @@ Error RtShadows::initInternal()
 	}
 	}
 
 
 	// Debug program
 	// Debug program
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsVisualizeRenderTarget.ankiprog",
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/RtShadowsVisualizeRenderTarget.ankiprogbin",
 												 m_visualizeRenderTargetsProg));
 												 m_visualizeRenderTargetsProg));
 
 
 	// Quarter rez shadow RT
 	// Quarter rez shadow RT
@@ -135,8 +137,7 @@ Error RtShadows::initInternal()
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
 				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
 				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
 			"RtShadows History");
 			"RtShadows History");
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		m_historyRt = m_r->createAndClearRenderTarget(texinit);
+		m_historyRt = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	// Temp shadow RT
 	// Temp shadow RT
@@ -154,11 +155,10 @@ Error RtShadows::initInternal()
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
 			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
 				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
 				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
 			"RtShadows Moments #1");
 			"RtShadows Moments #1");
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		m_momentsRts[0] = m_r->createAndClearRenderTarget(texinit);
+		m_momentsRts[0] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 		texinit.setName("RtShadows Moments #2");
 		texinit.setName("RtShadows Moments #2");
-		m_momentsRts[1] = m_r->createAndClearRenderTarget(texinit);
+		m_momentsRts[1] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	// Variance RT
 	// Variance RT
@@ -640,9 +640,8 @@ void RtShadows::buildSbt(RenderingContext& ctx)
 		const RayTracingInstanceQueueElement& element = instanceElements[instanceIdx];
 		const RayTracingInstanceQueueElement& element = instanceElements[instanceIdx];
 
 
 		// Init SBT record
 		// Init SBT record
-		memcpy(sbt, &shaderGroupHandles[element.m_shaderGroupHandleIndices[RayType::SHADOWS] * shaderHandleSize],
-			   shaderHandleSize);
-		memcpy(sbt + shaderHandleSize, &element.m_modelDescriptor, sizeof(element.m_modelDescriptor));
+		memcpy(sbt, &shaderGroupHandles[element.m_shaderGroupHandleIndex * shaderHandleSize], shaderHandleSize);
+		// TODO add some reference to the RenderableGpuView
 		sbt += m_sbtRecordSize;
 		sbt += m_sbtRecordSize;
 	}
 	}
 
 

+ 0 - 1
AnKi/Renderer/RtShadows.h

@@ -9,7 +9,6 @@
 #include <AnKi/Renderer/RendererObject.h>
 #include <AnKi/Renderer/RendererObject.h>
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Util/BitSet.h>
 #include <AnKi/Util/BitSet.h>
-#include <AnKi/Shaders/Include/RtShadows.h>
 
 
 namespace anki {
 namespace anki {
 
 

+ 7 - 6
AnKi/Renderer/Scale.cpp

@@ -47,19 +47,19 @@ Error Scale::init()
 		CString shaderFname;
 		CString shaderFname;
 		if(m_fsr && preferCompute)
 		if(m_fsr && preferCompute)
 		{
 		{
-			shaderFname = "Shaders/FsrCompute.ankiprog";
+			shaderFname = "ShaderBinaries/FsrCompute.ankiprogbin";
 		}
 		}
 		else if(m_fsr)
 		else if(m_fsr)
 		{
 		{
-			shaderFname = "Shaders/FsrRaster.ankiprog";
+			shaderFname = "ShaderBinaries/FsrRaster.ankiprogbin";
 		}
 		}
 		else if(preferCompute)
 		else if(preferCompute)
 		{
 		{
-			shaderFname = "Shaders/BlitCompute.ankiprog";
+			shaderFname = "ShaderBinaries/BlitCompute.ankiprogbin";
 		}
 		}
 		else
 		else
 		{
 		{
-			shaderFname = "Shaders/BlitRaster.ankiprog";
+			shaderFname = "ShaderBinaries/BlitRaster.ankiprogbin";
 		}
 		}
 
 
 		ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
 		ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
@@ -80,8 +80,9 @@ Error Scale::init()
 
 
 	if(needsSharpening)
 	if(needsSharpening)
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource(
-			(preferCompute) ? "Shaders/FsrCompute.ankiprog" : "Shaders/FsrRaster.ankiprog", m_sharpenProg));
+		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/FsrCompute.ankiprogbin"
+																	 : "ShaderBinaries/FsrRaster.ankiprogbin",
+													 m_sharpenProg));
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_sharpenProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_sharpenProg);
 		variantInitInfo.addMutation("SHARPEN", 1);
 		variantInitInfo.addMutation("SHARPEN", 1);
 		variantInitInfo.addMutation("FSR_QUALITY", 0);
 		variantInitInfo.addMutation("FSR_QUALITY", 0);

+ 8 - 9
AnKi/Renderer/ShadowMapping.cpp

@@ -9,7 +9,6 @@
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Util/ThreadHive.h>
 #include <AnKi/Util/ThreadHive.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Shaders/Include/ShadowMappingTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -109,10 +108,9 @@ Error ShadowMapping::initAtlas()
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis,
 			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis,
 			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis, texFormat, usage, "SM atlas");
 			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis, texFormat, usage, "SM atlas");
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		ClearValue clearVal;
 		ClearValue clearVal;
 		clearVal.m_colorf[0] = 1.0f;
 		clearVal.m_colorf[0] = 1.0f;
-		m_atlas.m_tex = m_r->createAndClearRenderTarget(texinit, clearVal);
+		m_atlas.m_tex = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT, clearVal);
 	}
 	}
 
 
 	// Tiles
 	// Tiles
@@ -121,8 +119,9 @@ Error ShadowMapping::initAtlas()
 
 
 	// Programs and shaders
 	// Programs and shaders
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource(
-			(preferCompute) ? "Shaders/EvsmCompute.ankiprog" : "Shaders/EvsmRaster.ankiprog", m_atlas.m_resolveProg));
+		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/EvsmCompute.ankiprogbin"
+																	 : "ShaderBinaries/EvsmRaster.ankiprogbin",
+													 m_atlas.m_resolveProg));
 
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_atlas.m_resolveProg);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_atlas.m_resolveProg);
 		variantInitInfo.addConstant("INPUT_TEXTURE_SIZE", UVec2(m_scratch.m_tileCountX * m_scratch.m_tileResolution,
 		variantInitInfo.addConstant("INPUT_TEXTURE_SIZE", UVec2(m_scratch.m_tileCountX * m_scratch.m_tileResolution,
@@ -160,11 +159,11 @@ void ShadowMapping::runAtlas(RenderPassWorkContext& rgraphCtx)
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
 	// Allocate and populate uniforms
 	// Allocate and populate uniforms
-	ShadowMappingUniforms* uniforms = allocateAndBindStorage<ShadowMappingUniforms*>(
-		m_atlas.m_resolveWorkItems.getSize() * sizeof(ShadowMappingUniforms), cmdb, 0, 0);
+	EvsmResolveUniforms* uniforms = allocateAndBindStorage<EvsmResolveUniforms*>(
+		m_atlas.m_resolveWorkItems.getSize() * sizeof(EvsmResolveUniforms), cmdb, 0, 0);
 	for(U32 i = 0; i < m_atlas.m_resolveWorkItems.getSize(); ++i)
 	for(U32 i = 0; i < m_atlas.m_resolveWorkItems.getSize(); ++i)
 	{
 	{
-		ShadowMappingUniforms& uni = uniforms[i];
+		EvsmResolveUniforms& uni = uniforms[i];
 		const Atlas::ResolveWorkItem& workItem = m_atlas.m_resolveWorkItems[i];
 		const Atlas::ResolveWorkItem& workItem = m_atlas.m_resolveWorkItems[i];
 
 
 		uni.m_viewportXY = IVec2(workItem.m_viewportOut.xy());
 		uni.m_viewportXY = IVec2(workItem.m_viewportOut.xy());
@@ -222,7 +221,7 @@ void ShadowMapping::runShadowMapping(RenderPassWorkContext& rgraphCtx)
 		cmdb->setViewport(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 		cmdb->setViewport(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 		cmdb->setScissor(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 		cmdb->setScissor(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 
 
-		m_r->getSceneDrawer().drawRange(Pass::SM, work.m_renderQueue->m_viewMatrix,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, work.m_renderQueue->m_viewMatrix,
 										work.m_renderQueue->m_viewProjectionMatrix,
 										work.m_renderQueue->m_viewProjectionMatrix,
 										Mat4::getIdentity(), // Don't care about prev matrices here
 										Mat4::getIdentity(), // Don't care about prev matrices here
 										cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
 										cmdb, m_r->getSamplers().m_trilinearRepeatAniso,

+ 2 - 2
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -44,8 +44,8 @@ Error ShadowmapsResolve::initInternal()
 
 
 	// Prog
 	// Prog
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
 	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
-													 ? "Shaders/ShadowmapsResolveCompute.ankiprog"
-													 : "Shaders/ShadowmapsResolveRaster.ankiprog",
+													 ? "ShaderBinaries/ShadowmapsResolveCompute.ankiprogbin"
+													 : "ShaderBinaries/ShadowmapsResolveRaster.ankiprogbin",
 												 m_prog));
 												 m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	if(getConfig().getRPreferCompute())
 	if(getConfig().getRPreferCompute())

+ 5 - 6
AnKi/Renderer/TemporalAA.cpp

@@ -37,9 +37,10 @@ Error TemporalAA::initInternal()
 {
 {
 	ANKI_R_LOGV("Initializing TAA");
 	ANKI_R_LOGV("Initializing TAA");
 
 
-	ANKI_CHECK(m_r->getResourceManager().loadResource(
-		(getConfig().getRPreferCompute()) ? "Shaders/TemporalAACompute.ankiprog" : "Shaders/TemporalAARaster.ankiprog",
-		m_prog));
+	ANKI_CHECK(m_r->getResourceManager().loadResource((getConfig().getRPreferCompute())
+														  ? "ShaderBinaries/TemporalAACompute.ankiprogbin"
+														  : "ShaderBinaries/TemporalAARaster.ankiprogbin",
+													  m_prog));
 
 
 	{
 	{
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
@@ -69,9 +70,7 @@ Error TemporalAA::initInternal()
 			m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
 			m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
 											  m_r->getHdrFormat(), usage, "TemporalAA");
 											  m_r->getHdrFormat(), usage, "TemporalAA");
 
 
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-
-		m_rtTextures[i] = m_r->createAndClearRenderTarget(texinit);
+		m_rtTextures[i] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 	}
 	}
 
 
 	m_tonemappedRtDescr = m_r->create2DRenderTargetDescription(
 	m_tonemappedRtDescr = m_r->create2DRenderTargetDescription(

+ 1 - 1
AnKi/Renderer/Tonemapping.cpp

@@ -29,7 +29,7 @@ Error Tonemapping::initInternal()
 	ANKI_R_LOGV("Initializing tonemapping. Resolution %ux%u", width, height);
 	ANKI_R_LOGV("Initializing tonemapping. Resolution %ux%u", width, height);
 
 
 	// Create program
 	// Create program
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/TonemappingAverageLuminance.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/TonemappingAverageLuminance.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("INPUT_TEX_SIZE", UVec2(width, height));
 	variantInitInfo.addConstant("INPUT_TEX_SIZE", UVec2(width, height));

+ 4 - 3
AnKi/Renderer/TraditionalDeferredShading.cpp

@@ -25,7 +25,8 @@ Error TraditionalDeferredLightShading::init()
 {
 {
 	// Init progs
 	// Init progs
 	{
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/TraditionalDeferredShading.ankiprog", m_lightProg));
+		ANKI_CHECK(
+			getResourceManager().loadResource("ShaderBinaries/TraditionalDeferredShading.ankiprogbin", m_lightProg));
 
 
 		for(U32 specular = 0; specular <= 1; ++specular)
 		for(U32 specular = 0; specular <= 1; ++specular)
 		{
 		{
@@ -63,8 +64,8 @@ Error TraditionalDeferredLightShading::init()
 
 
 	// Skybox
 	// Skybox
 	{
 	{
-		ANKI_CHECK(
-			getResourceManager().loadResource("Shaders/TraditionalDeferredShadingSkybox.ankiprog", m_skyboxProg));
+		ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/TraditionalDeferredShadingSkybox.ankiprogbin",
+													 m_skyboxProg));
 
 
 		for(U32 i = 0; i < m_skyboxGrProgs.getSize(); ++i)
 		for(U32 i = 0; i < m_skyboxGrProgs.getSize(); ++i)
 		{
 		{

+ 2 - 12
AnKi/Renderer/VolumetricFog.cpp

@@ -28,7 +28,7 @@ Error VolumetricFog::init()
 	ANKI_R_LOGV("Initializing volumetric fog. Resolution %ux%ux%u", m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]);
 	ANKI_R_LOGV("Initializing volumetric fog. Resolution %ux%ux%u", m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]);
 
 
 	// Shaders
 	// Shaders
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/VolumetricFogAccumulation.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/VolumetricFogAccumulation.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("VOLUME_SIZE", UVec3(m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]));
 	variantInitInfo.addConstant("VOLUME_SIZE", UVec3(m_volumeSize[0], m_volumeSize[1], m_volumeSize[2]));
@@ -72,17 +72,7 @@ void VolumetricFog::populateRenderGraph(RenderingContext& ctx)
 
 
 		rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, TextureSubresourceInfo());
 		rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, TextureSubresourceInfo());
 
 
-		class PushConsts
-		{
-		public:
-			Vec3 m_fogDiffuse;
-			F32 m_fogScatteringCoeff;
-			F32 m_fogAbsorptionCoeff;
-			F32 m_near;
-			F32 m_far;
-			F32 m_padding;
-		} regs;
-
+		VolumetricFogUniforms regs;
 		const SkyboxQueueElement& el = ctx.m_renderQueue->m_skybox;
 		const SkyboxQueueElement& el = ctx.m_renderQueue->m_skybox;
 		regs.m_fogDiffuse = el.m_fog.m_diffuseColor;
 		regs.m_fogDiffuse = el.m_fog.m_diffuseColor;
 		regs.m_fogScatteringCoeff = el.m_fog.m_scatteringCoeff;
 		regs.m_fogScatteringCoeff = el.m_fog.m_scatteringCoeff;

+ 4 - 12
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -44,7 +44,7 @@ Error VolumetricLightingAccumulation::init()
 	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
 	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
 
 
 	// Shaders
 	// Shaders
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/VolumetricLightingAccumulation.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/VolumetricLightingAccumulation.ankiprogbin", m_prog));
 
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addMutation("ENABLE_SHADOWS", 1);
 	variantInitInfo.addMutation("ENABLE_SHADOWS", 1);
@@ -66,9 +66,8 @@ Error VolumetricLightingAccumulation::init()
 										  "VolLight");
 										  "VolLight");
 	texinit.m_depth = m_volumeSize[2];
 	texinit.m_depth = m_volumeSize[2];
 	texinit.m_type = TextureType::_3D;
 	texinit.m_type = TextureType::_3D;
-	texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-	m_rtTextures[0] = m_r->createAndClearRenderTarget(texinit);
-	m_rtTextures[1] = m_r->createAndClearRenderTarget(texinit);
+	m_rtTextures[0] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
+	m_rtTextures[1] = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }
@@ -127,14 +126,7 @@ void VolumetricLightingAccumulation::run(const RenderingContext& ctx, RenderPass
 	bindUniforms(cmdb, 0, 11, rsrc.m_fogDensityVolumesToken);
 	bindUniforms(cmdb, 0, 11, rsrc.m_fogDensityVolumesToken);
 	bindStorage(cmdb, 0, 12, rsrc.m_clustersToken);
 	bindStorage(cmdb, 0, 12, rsrc.m_clustersToken);
 
 
-	class FogUniforms
-	{
-	public:
-		F32 m_densityAtMinHeight;
-		F32 m_densityAtMaxHeight;
-		F32 m_minHeight;
-		F32 m_oneOverMaxMinusMinHeight; // 1 / (maxHeight / minHeight)
-	} unis;
+	VolumetricLightingUniforms unis;
 	const SkyboxQueueElement& queueEl = ctx.m_renderQueue->m_skybox;
 	const SkyboxQueueElement& queueEl = ctx.m_renderQueue->m_skybox;
 	if(queueEl.m_fog.m_heightOfMaxDensity > queueEl.m_fog.m_heightOfMinDensity)
 	if(queueEl.m_fog.m_heightOfMaxDensity > queueEl.m_fog.m_heightOfMinDensity)
 	{
 	{

+ 4 - 4
AnKi/Renderer/VrsSriGeneration.cpp

@@ -46,15 +46,14 @@ Error VrsSriGeneration::initInternal()
 									 | TextureUsageBit::SAMPLED_FRAGMENT;
 									 | TextureUsageBit::SAMPLED_FRAGMENT;
 	TextureInitInfo sriInitInfo =
 	TextureInitInfo sriInitInfo =
 		m_r->create2DRenderTargetInitInfo(rez.x(), rez.y(), Format::R8_UINT, texUsage, "VRS SRI");
 		m_r->create2DRenderTargetInitInfo(rez.x(), rez.y(), Format::R8_UINT, texUsage, "VRS SRI");
-	sriInitInfo.m_initialUsage = TextureUsageBit::FRAMEBUFFER_SHADING_RATE;
-	m_sriTex = m_r->createAndClearRenderTarget(sriInitInfo);
+	m_sriTex = m_r->createAndClearRenderTarget(sriInitInfo, TextureUsageBit::FRAMEBUFFER_SHADING_RATE);
 
 
 	// Descr
 	// Descr
 	m_fbDescr.m_colorAttachmentCount = 1;
 	m_fbDescr.m_colorAttachmentCount = 1;
 	m_fbDescr.bake();
 	m_fbDescr.bake();
 
 
 	// Load programs
 	// Load programs
-	ANKI_CHECK(getResourceManager().loadResource("AnKi/Shaders/VrsSriGenerationCompute.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/VrsSriGenerationCompute.ankiprogbin", m_prog));
 	ShaderProgramResourceVariantInitInfo variantInit(m_prog);
 	ShaderProgramResourceVariantInitInfo variantInit(m_prog);
 	variantInit.addMutation("SRI_TEXEL_DIMENSION", m_sriTexelDimension);
 	variantInit.addMutation("SRI_TEXEL_DIMENSION", m_sriTexelDimension);
 
 
@@ -73,7 +72,8 @@ Error VrsSriGeneration::initInternal()
 	m_prog->getOrCreateVariant(variantInit, variant);
 	m_prog->getOrCreateVariant(variantInit, variant);
 	m_grProg = variant->getProgram();
 	m_grProg = variant->getProgram();
 
 
-	ANKI_CHECK(getResourceManager().loadResource("AnKi/Shaders/VrsSriVisualizeRenderTarget.ankiprog", m_visualizeProg));
+	ANKI_CHECK(
+		getResourceManager().loadResource("ShaderBinaries/VrsSriVisualizeRenderTarget.ankiprogbin", m_visualizeProg));
 	m_visualizeProg->getOrCreateVariant(variant);
 	m_visualizeProg->getOrCreateVariant(variant);
 	m_visualizeGrProg = variant->getProgram();
 	m_visualizeGrProg = variant->getProgram();
 
 

+ 4 - 2
AnKi/Resource/CMakeLists.txt

@@ -1,2 +1,4 @@
-file(GLOB_RECURSE SOURCES *.cpp)
-anki_add_source_files(${SOURCES})
+file(GLOB_RECURSE sources *.cpp)
+add_library(AnKiResource ${sources})
+target_compile_definitions(AnKiResource PRIVATE -DANKI_SOURCE_FILE)
+target_link_libraries(AnKiResource AnKiCore AnKiGr AnKiPhysics AnKiZLib AnKiShaderCompiler)

+ 0 - 28
AnKi/Resource/Common.h

@@ -30,34 +30,6 @@ class TransferGpuAllocatorHandle;
 #define ANKI_RESOURCE_LOGW(...) ANKI_LOG("RSRC", WARNING, __VA_ARGS__)
 #define ANKI_RESOURCE_LOGW(...) ANKI_LOG("RSRC", WARNING, __VA_ARGS__)
 #define ANKI_RESOURCE_LOGF(...) ANKI_LOG("RSRC", FATAL, __VA_ARGS__)
 #define ANKI_RESOURCE_LOGF(...) ANKI_LOG("RSRC", FATAL, __VA_ARGS__)
 
 
-/// @name Constants
-/// @{
-
-enum class RayType : U8
-{
-	SHADOWS,
-	GI,
-	REFLECTIONS,
-	PATH_TRACING,
-
-	COUNT,
-	FIRST = 0
-};
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RayType)
-
-enum class RayTypeBit : U8
-{
-	NONE,
-	SHADOWS = 1 << 0,
-	GI = 1 << 1,
-	REFLECTIONS = 1 << 2,
-	PATH_TRACING = 1 << 3,
-
-	ALL = SHADOWS | GI | REFLECTIONS | PATH_TRACING
-};
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RayTypeBit)
-/// @}
-
 /// Deleter for ResourcePtr.
 /// Deleter for ResourcePtr.
 template<typename T>
 template<typename T>
 class ResourcePtrDeleter
 class ResourcePtrDeleter

+ 18 - 1
AnKi/Resource/ImageResource.cpp

@@ -73,7 +73,6 @@ Error ImageResource::load(const ResourceFilename& filename, Bool async)
 
 
 	TextureInitInfo init(filenameExt);
 	TextureInitInfo init(filenameExt);
 	init.m_usage = TextureUsageBit::ALL_SAMPLED | TextureUsageBit::TRANSFER_DESTINATION;
 	init.m_usage = TextureUsageBit::ALL_SAMPLED | TextureUsageBit::TRANSFER_DESTINATION;
-	init.m_initialUsage = TextureUsageBit::ALL_SAMPLED;
 	U32 faces = 0;
 	U32 faces = 0;
 
 
 	ResourceFilePtr file;
 	ResourceFilePtr file;
@@ -207,6 +206,24 @@ Error ImageResource::load(const ResourceFilename& filename, Bool async)
 	// Create the texture
 	// Create the texture
 	m_tex = getManager().getGrManager().newTexture(init);
 	m_tex = getManager().getGrManager().newTexture(init);
 
 
+	// Transition it. TODO remove that eventually
+	{
+		CommandBufferInitInfo cmdbinit;
+		cmdbinit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
+		CommandBufferPtr cmdb = getManager().getGrManager().newCommandBuffer(cmdbinit);
+
+		TextureSubresourceInfo subresource;
+		subresource.m_faceCount = textureTypeIsCube(init.m_type) ? 6 : 1;
+		subresource.m_layerCount = init.m_layerCount;
+		subresource.m_mipmapCount = init.m_mipmapCount;
+
+		cmdb->setTextureBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::ALL_SAMPLED, subresource);
+
+		FencePtr outFence;
+		cmdb->flush({}, &outFence);
+		outFence->clientWait(60.0_sec);
+	}
+
 	// Set the context
 	// Set the context
 	ctx->m_faces = faces;
 	ctx->m_faces = faces;
 	ctx->m_layerCount = init.m_layerCount;
 	ctx->m_layerCount = init.m_layerCount;

File diff suppressed because it is too large
+ 489 - 547
AnKi/Resource/MaterialResource.cpp


+ 75 - 263
AnKi/Resource/MaterialResource.h

@@ -11,7 +11,7 @@
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Resource/ImageResource.h>
 #include <AnKi/Math.h>
 #include <AnKi/Math.h>
 #include <AnKi/Util/Enum.h>
 #include <AnKi/Util/Enum.h>
-#include <AnKi/Shaders/Include/ModelTypes.h>
+#include <AnKi/Shaders/Include/MaterialTypes.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -21,26 +21,11 @@ class XmlElement;
 /// @addtogroup resource
 /// @addtogroup resource
 /// @{
 /// @{
 
 
-/// The ID of a buildin material variable.
-enum class BuiltinMaterialVariableId : U8
-{
-	NONE = 0,
-	TRANSFORM,
-	PREVIOUS_TRANSFORM,
-	ROTATION,
-	GLOBAL_SAMPLER,
-
-	COUNT,
-	FIRST = 0,
-};
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(BuiltinMaterialVariableId)
-
 /// The ID of builtin mutators.
 /// The ID of builtin mutators.
 enum class BuiltinMutatorId : U8
 enum class BuiltinMutatorId : U8
 {
 {
 	NONE = 0,
 	NONE = 0,
-	INSTANCED,
-	PASS,
+	TECHNIQUE,
 	LOD,
 	LOD,
 	BONES,
 	BONES,
 	VELOCITY,
 	VELOCITY,
@@ -73,26 +58,14 @@ public:
 	MaterialVariable& operator=(MaterialVariable&& b)
 	MaterialVariable& operator=(MaterialVariable&& b)
 	{
 	{
 		m_name = std::move(b.m_name);
 		m_name = std::move(b.m_name);
-		m_index = b.m_index;
-		m_indexInBinary = b.m_indexInBinary;
-		m_indexInBinary2ndElement = b.m_indexInBinary2ndElement;
+		m_offsetInLocalUniforms = b.m_offsetInLocalUniforms;
 		m_opaqueBinding = b.m_opaqueBinding;
 		m_opaqueBinding = b.m_opaqueBinding;
-		m_constant = b.m_constant;
-		m_instanced = b.m_instanced;
-		m_numericValueIsSet = b.m_numericValueIsSet;
 		m_dataType = b.m_dataType;
 		m_dataType = b.m_dataType;
-		m_builtin = b.m_builtin;
 		m_Mat4 = b.m_Mat4;
 		m_Mat4 = b.m_Mat4;
 		m_image = std::move(b.m_image);
 		m_image = std::move(b.m_image);
 		return *this;
 		return *this;
 	}
 	}
 
 
-	/// Get the builtin info.
-	BuiltinMaterialVariableId getBuiltin() const
-	{
-		return m_builtin;
-	}
-
 	CString getName() const
 	CString getName() const
 	{
 	{
 		return m_name;
 		return m_name;
@@ -101,35 +74,20 @@ public:
 	template<typename T>
 	template<typename T>
 	const T& getValue() const;
 	const T& getValue() const;
 
 
-	Bool isTexture() const
+	Bool isBoundableTexture() const
 	{
 	{
 		return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
 		return m_dataType >= ShaderVariableDataType::TEXTURE_FIRST
 			   && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
 			   && m_dataType <= ShaderVariableDataType::TEXTURE_LAST;
 	}
 	}
 
 
-	Bool isSampler() const
+	Bool isBindlessTexture() const
 	{
 	{
-		return m_dataType == ShaderVariableDataType::SAMPLER;
+		return m_dataType == ShaderVariableDataType::U32 && m_image.get();
 	}
 	}
 
 
-	Bool inBlock() const
+	Bool isUniform() const
 	{
 	{
-		return !m_constant && !isTexture() && !isSampler();
-	}
-
-	Bool isConstant() const
-	{
-		return m_constant;
-	}
-
-	Bool isInstanced() const
-	{
-		return m_instanced;
-	}
-
-	Bool isBuildin() const
-	{
-		return m_builtin != BuiltinMaterialVariableId::NONE;
+		return !isBoundableTexture();
 	}
 	}
 
 
 	ShaderVariableDataType getDataType() const
 	ShaderVariableDataType getDataType() const
@@ -139,40 +97,35 @@ public:
 	}
 	}
 
 
 	/// Get the binding of a texture or a sampler type of material variable.
 	/// Get the binding of a texture or a sampler type of material variable.
-	U32 getOpaqueBinding() const
+	U32 getTextureBinding() const
 	{
 	{
-		ANKI_ASSERT(m_opaqueBinding != MAX_U32 && (isTexture() || isSampler()));
+		ANKI_ASSERT(m_opaqueBinding != MAX_U32 && isBoundableTexture());
 		return m_opaqueBinding;
 		return m_opaqueBinding;
 	}
 	}
 
 
+	U32 getOffsetInLocalUniforms() const
+	{
+		ANKI_ASSERT(m_offsetInLocalUniforms != MAX_U32);
+		return m_offsetInLocalUniforms;
+	}
+
 protected:
 protected:
 	String m_name;
 	String m_name;
-	U32 m_index = MAX_U32;
-	U32 m_indexInBinary = MAX_U32;
-	U32 m_indexInBinary2ndElement = MAX_U32; ///< To calculate the stride.
+	U32 m_offsetInLocalUniforms = MAX_U32;
 	U32 m_opaqueBinding = MAX_U32; ///< Binding for textures and samplers.
 	U32 m_opaqueBinding = MAX_U32; ///< Binding for textures and samplers.
-	Bool m_constant = false;
-	Bool m_instanced = false;
-	Bool m_numericValueIsSet = false; ///< The unamed union bellow is set
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
-	BuiltinMaterialVariableId m_builtin = BuiltinMaterialVariableId::NONE;
 
 
-	/// Values for non-builtins
+	/// Values
 	/// @{
 	/// @{
 	union
 	union
 	{
 	{
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) type ANKI_CONCATENATE(m_, type);
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) type ANKI_CONCATENATE(m_, type);
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #undef ANKI_SVDT_MACRO
 #undef ANKI_SVDT_MACRO
 	};
 	};
 
 
 	ImageResourcePtr m_image;
 	ImageResourcePtr m_image;
 	/// @}
 	/// @}
-
-	Bool valueSetByMaterial() const
-	{
-		return m_image.isCreated() || m_numericValueIsSet;
-	}
 };
 };
 
 
 // Specialize the MaterialVariable::getValue
 // Specialize the MaterialVariable::getValue
@@ -181,11 +134,10 @@ protected:
 	inline const t_& MaterialVariable::getValue<t_>() const \
 	inline const t_& MaterialVariable::getValue<t_>() const \
 	{ \
 	{ \
 		ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
 		ANKI_ASSERT(m_dataType == ShaderVariableDataType::shaderType_); \
-		ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE); \
 		return var_; \
 		return var_; \
 	}
 	}
 
 
-#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
+#define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount, isIntagralType) \
 	ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type), capital)
 	ANKI_SPECIALIZE_GET_VALUE(type, ANKI_CONCATENATE(m_, type), capital)
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #include <AnKi/Gr/ShaderVariableDataType.defs.h>
 #undef ANKI_SVDT_MACRO
 #undef ANKI_SVDT_MACRO
@@ -195,8 +147,7 @@ protected:
 template<>
 template<>
 inline const ImageResourcePtr& MaterialVariable::getValue() const
 inline const ImageResourcePtr& MaterialVariable::getValue() const
 {
 {
-	ANKI_ASSERT(isTexture());
-	ANKI_ASSERT(m_builtin == BuiltinMaterialVariableId::NONE);
+	ANKI_ASSERT(m_image.get());
 	return m_image;
 	return m_image;
 }
 }
 
 
@@ -212,92 +163,55 @@ public:
 
 
 	MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
 	MaterialVariant& operator=(const MaterialVariant&) = delete; // Non-copyable
 
 
-	/// Return true of the the variable is active.
-	Bool isVariableActive(const MaterialVariable& var) const
-	{
-		return m_activeVars.get(var.m_index);
-	}
-
 	const ShaderProgramPtr& getShaderProgram() const
 	const ShaderProgramPtr& getShaderProgram() const
 	{
 	{
 		return m_prog;
 		return m_prog;
 	}
 	}
 
 
-	U32 getPerDrawUniformBlockSize() const
+	U32 getRtShaderGroupHandleIndex() const
 	{
 	{
-		return m_perDrawUboSize;
+		ANKI_ASSERT(m_rtShaderGroupHandleIndex != MAX_U32);
+		return m_rtShaderGroupHandleIndex;
 	}
 	}
 
 
-	U32 getPerInstanceUniformBlockSize(U32 instanceCount) const
-	{
-		ANKI_ASSERT(instanceCount > 0 && instanceCount <= MAX_INSTANCE_COUNT);
-		return m_perInstanceUboSizeSingleInstance * instanceCount;
-	}
+private:
+	ShaderProgramPtr m_prog;
+	U32 m_rtShaderGroupHandleIndex = MAX_U32;
 
 
-	ShaderVariableBlockInfo getBlockInfo(const MaterialVariable& var, U32 instanceCount) const
+	MaterialVariant(MaterialVariant&& b)
 	{
 	{
-		ANKI_ASSERT(isVariableActive(var));
-		ANKI_ASSERT(var.inBlock());
-		ANKI_ASSERT(m_blockInfos[var.m_index].m_offset >= 0);
-		if(var.isInstanced())
-		{
-			ANKI_ASSERT(m_blockInfos[var.m_index].m_arraySize == I16(MAX_INSTANCE_COUNT));
-			ANKI_ASSERT(instanceCount > 0 && instanceCount <= MAX_INSTANCE_COUNT);
-		}
-		else
-		{
-			ANKI_ASSERT(m_blockInfos[var.m_index].m_arraySize == 1);
-			ANKI_ASSERT(instanceCount == 1);
-		}
-
-		ShaderVariableBlockInfo out = m_blockInfos[var.m_index];
-		out.m_arraySize = I16(instanceCount);
-		return out;
+		*this = std::move(b);
 	}
 	}
 
 
-	template<typename T>
-	void writeShaderBlockMemory(const MaterialVariable& var, const T* elements, U32 elementCount, void* buffBegin,
-								const void* buffEnd) const
+	MaterialVariant& operator=(MaterialVariant&& b)
 	{
 	{
-		ANKI_ASSERT(isVariableActive(var));
-		ANKI_ASSERT(getShaderVariableTypeFromTypename<T>() == var.getDataType());
-		const ShaderVariableBlockInfo blockInfo = getBlockInfo(var, elementCount);
-		anki::writeShaderBlockMemory(var.getDataType(), blockInfo, elements, elementCount, buffBegin, buffEnd);
+		m_prog = std::move(b.m_prog);
+		m_rtShaderGroupHandleIndex = b.m_rtShaderGroupHandleIndex;
+		return *this;
 	}
 	}
-
-private:
-	ShaderProgramPtr m_prog;
-	DynamicArray<ShaderVariableBlockInfo> m_blockInfos;
-	BitSet<128, U32> m_activeVars = {false};
-	U32 m_perDrawUboSize = 0;
-	U32 m_perInstanceUboSizeSingleInstance = 0;
 };
 };
 
 
 /// Material resource.
 /// Material resource.
 ///
 ///
 /// Material XML file format:
 /// Material XML file format:
 /// @code
 /// @code
-/// <material [shadow="0 | 1"] [forwardShading="0 | 1"] shaderProgram="path">
-///		[<mutation>
-///			<mutator name="str" value="value"/>
-///		</mutation>]
+///	<material [shadows="0|1"]>
+/// 	<shaderPrograms>
+///			<shaderProgram name="name of the shader">
+///				[<mutation>
+///					<mutator name="str" value="value"/>
+///				</mutation>]
+///			</shaderProgram>
+///
+///			[<shaderProgram ...>
+///				...
+///			</shaderProgram>]
+/// 	</shaderPrograms>
 ///
 ///
 ///		[<inputs>
 ///		[<inputs>
-///			<input shaderVar="name to shaderProg var" value="values"/> (1)
+///			<input name="name in AnKiMaterialUniforms struct or opaque type" value="value(s)"/> (1)
 ///		</inputs>]
 ///		</inputs>]
-/// </material>
-///
-/// [<rtMaterial>
-///		<rayType shaderProgram="path" type="shadows|gi|reflections|pathTracing">
-///			[<mutation>
-///				<mutator name="str" value="value"/>
-///			</mutation>]
-///		</rayType>
-///
-/// 	[<inputs>
-/// 		<input name="name" value="value" />
-/// 	</inputs>]
-/// </rtMaterial>]
+///	</material>
 /// @endcode
 /// @endcode
 ///
 ///
 /// (1): Only for non-builtins.
 /// (1): Only for non-builtins.
@@ -311,29 +225,9 @@ public:
 	/// Load a material file
 	/// Load a material file
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename, Bool async);
 
 
-	U32 getLodCount() const
-	{
-		return m_lodCount;
-	}
-
 	Bool castsShadow() const
 	Bool castsShadow() const
 	{
 	{
-		return m_shadow;
-	}
-
-	Bool hasTessellation() const
-	{
-		return !!(m_prog->getStages() & (ShaderTypeBit::TESSELLATION_CONTROL | ShaderTypeBit::TESSELLATION_EVALUATION));
-	}
-
-	Bool isForwardShading() const
-	{
-		return m_forwardShading;
-	}
-
-	Bool isInstanced() const
-	{
-		return m_builtinMutators[BuiltinMutatorId::INSTANCED] != nullptr;
+		return !!(m_techniquesMask & (RenderingTechniqueBit::SHADOW | RenderingTechniqueBit::RT_SHADOW));
 	}
 	}
 
 
 	ConstWeakArray<MaterialVariable> getVariables() const
 	ConstWeakArray<MaterialVariable> getVariables() const
@@ -341,142 +235,64 @@ public:
 		return m_vars;
 		return m_vars;
 	}
 	}
 
 
-	U32 getDescriptorSetIndex() const
-	{
-		ANKI_ASSERT(m_descriptorSetIdx != MAX_U8);
-		return m_descriptorSetIdx;
-	}
-
-	U32 getBoneTransformsStorageBlockBinding() const
-	{
-		ANKI_ASSERT(supportsSkinning());
-		return m_boneTrfsBinding;
-	}
-
-	U32 getPrevFrameBoneTransformsStorageBlockBinding() const
-	{
-		ANKI_ASSERT(supportsSkinning());
-		return m_prevFrameBoneTrfsBinding;
-	}
-
 	Bool supportsSkinning() const
 	Bool supportsSkinning() const
 	{
 	{
-		ANKI_ASSERT((m_boneTrfsBinding == MAX_U32 && m_prevFrameBoneTrfsBinding == MAX_U32)
-					|| (m_boneTrfsBinding != MAX_U32 && m_prevFrameBoneTrfsBinding != MAX_U32));
-		return m_boneTrfsBinding != MAX_U32;
-	}
-
-	U32 getPerDrawUniformBlockBinding() const
-	{
-		ANKI_ASSERT(m_perDrawUboBinding != MAX_U32);
-		return m_perDrawUboBinding;
+		return m_supportsSkinning;
 	}
 	}
 
 
-	U32 getPerInstanceUniformBlockBinding() const
+	RenderingTechniqueBit getRenderingTechniques() const
 	{
 	{
-		ANKI_ASSERT(isInstanced() && m_perInstanceUboBinding != MAX_U32);
-		return m_perInstanceUboBinding;
+		ANKI_ASSERT(!!m_techniquesMask);
+		return m_techniquesMask;
 	}
 	}
 
 
-	U32 getGlobalUniformsUniformBlockBinding() const
+	/// Get all GPU resources of this material. Will be used for GPU refcounting.
+	ConstWeakArray<TexturePtr> getAllTextures() const
 	{
 	{
-		ANKI_ASSERT(m_globalUniformsUboBinding != MAX_U32);
-		return m_globalUniformsUboBinding;
+		return m_textures;
 	}
 	}
 
 
+	/// @note It's thread-safe.
 	const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
 	const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
 
 
-	U32 getShaderGroupHandleIndex(RayType type) const
-	{
-		ANKI_ASSERT(!!(m_rayTypes & RayTypeBit(1 << type)));
-		ANKI_ASSERT(m_rtShaderGroupHandleIndices[type] < MAX_U32);
-		return m_rtShaderGroupHandleIndices[type];
-	}
-
-	RayTypeBit getSupportedRayTracingTypes() const
+	/// Get a buffer with prefilled uniforms.
+	ConstWeakArray<U8> getPrefilledLocalUniforms() const
 	{
 	{
-		return m_rayTypes;
-	}
-
-	const MaterialGpuDescriptor& getMaterialGpuDescriptor() const
-	{
-		return m_materialGpuDescriptor;
-	}
-
-	/// Get all texture views that the MaterialGpuDescriptor returned by getMaterialGpuDescriptor(), references. Used
-	/// for lifetime management.
-	ConstWeakArray<TextureViewPtr> getAllTextureViews() const
-	{
-		return ConstWeakArray<TextureViewPtr>((m_textureViewCount) ? &m_textureViews[0] : nullptr, m_textureViewCount);
+		return ConstWeakArray<U8>(static_cast<const U8*>(m_prefilledLocalUniforms), m_localUniformsSize);
 	}
 	}
 
 
 private:
 private:
-	class SubMutation
+	class PartialMutation
 	{
 	{
 	public:
 	public:
 		const ShaderProgramResourceMutator* m_mutator;
 		const ShaderProgramResourceMutator* m_mutator;
 		MutatorValue m_value;
 		MutatorValue m_value;
 	};
 	};
 
 
-	ShaderProgramResourcePtr m_prog;
-
-	Array<const ShaderProgramResourceMutator*, U32(BuiltinMutatorId::COUNT)> m_builtinMutators = {};
+	class Program;
 
 
-	Bool m_shadow = true;
-	Bool m_forwardShading = false;
-	U8 m_lodCount = 1;
-	U8 m_descriptorSetIdx = MAX_U8; ///< The material set.
-	U32 m_perDrawUboIdx = MAX_U32; ///< The b_perDraw UBO inside the binary.
-	U32 m_perInstanceUboIdx = MAX_U32; ///< The b_perInstance UBO inside the binary.
-	U32 m_perDrawUboBinding = MAX_U32;
-	U32 m_perInstanceUboBinding = MAX_U32;
-	U32 m_boneTrfsBinding = MAX_U32;
-	U32 m_prevFrameBoneTrfsBinding = MAX_U32;
-	U32 m_globalUniformsUboBinding = MAX_U32;
+	DynamicArray<Program> m_programs;
 
 
-	/// Matrix of variants.
-	mutable Array5d<MaterialVariant, U(Pass::COUNT), MAX_LOD_COUNT, 2, 2, 2> m_variantMatrix;
-	mutable RWMutex m_variantMatrixMtx;
+	Array<U8, U(RenderingTechnique::COUNT)> m_techniqueToProgram;
+	RenderingTechniqueBit m_techniquesMask = RenderingTechniqueBit::NONE;
 
 
 	DynamicArray<MaterialVariable> m_vars;
 	DynamicArray<MaterialVariable> m_vars;
 
 
-	DynamicArray<SubMutation> m_nonBuiltinsMutation;
+	Bool m_supportsSkinning = false;
 
 
-	Array<ShaderProgramResourcePtr, U(RayType::COUNT)> m_rtPrograms;
-	Array<U32, U(RayType::COUNT)> m_rtShaderGroupHandleIndices = {};
+	DynamicArray<TexturePtr> m_textures;
 
 
-	MaterialGpuDescriptor m_materialGpuDescriptor;
+	void* m_prefilledLocalUniforms = nullptr;
+	U32 m_localUniformsSize = 0;
 
 
-	Array<ImageResourcePtr, U(TextureChannelId::COUNT)> m_images; ///< Keep the resources alive.
-	Array<TextureViewPtr, U(TextureChannelId::COUNT)> m_textureViews; ///< Cache the GPU objects.
-	U8 m_textureViewCount = 0;
+	ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl, Program& prog);
+	ANKI_USE_RESULT Error parseShaderProgram(XmlElement techniqueEl, Bool async);
+	ANKI_USE_RESULT Error parseInput(XmlElement inputEl, Bool async, BitSet<128>& varsSet);
+	ANKI_USE_RESULT Error findBuiltinMutators(Program& prog);
+	ANKI_USE_RESULT Error createVars(Program& prog);
+	void prefillLocalUniforms();
 
 
-	RayTypeBit m_rayTypes = RayTypeBit::NONE;
-
-	ANKI_USE_RESULT Error createVars();
-
-	static ANKI_USE_RESULT Error parseVariable(CString fullVarName, Bool instanced, U32& idx, CString& name);
-
-	/// Parse whatever is inside the <inputs> tag.
-	ANKI_USE_RESULT Error parseInputs(XmlElement inputsEl, Bool async);
-
-	ANKI_USE_RESULT Error parseMutators(XmlElement mutatorsEl);
-	ANKI_USE_RESULT Error findBuiltinMutators();
-
-	void initVariant(const ShaderProgramResourceVariant& progVariant, MaterialVariant& variant, Bool instanced) const;
-
-	const MaterialVariable* tryFindVariableInternal(CString name) const
-	{
-		for(const MaterialVariable& v : m_vars)
-		{
-			if(v.m_name == name)
-			{
-				return &v;
-			}
-		}
-
-		return nullptr;
-	}
+	const MaterialVariable* tryFindVariableInternal(CString name) const;
 
 
 	const MaterialVariable* tryFindVariable(CString name) const
 	const MaterialVariable* tryFindVariable(CString name) const
 	{
 	{
@@ -487,10 +303,6 @@ private:
 	{
 	{
 		return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
 		return const_cast<MaterialVariable*>(tryFindVariableInternal(name));
 	}
 	}
-
-	ANKI_USE_RESULT Error parseRtMaterial(XmlElement rootEl);
-
-	ANKI_USE_RESULT Error findGlobalUniformsUbo();
 };
 };
 /// @}
 /// @}
 
 

+ 31 - 50
AnKi/Resource/ModelResource.cpp

@@ -11,9 +11,9 @@
 
 
 namespace anki {
 namespace anki {
 
 
-static Bool attributeIsRequired(VertexAttributeId loc, Pass pass, Bool hasSkin)
+static Bool attributeIsRequired(VertexAttributeId loc, RenderingTechnique technique, Bool hasSkin)
 {
 {
-	if(pass == Pass::GB || pass == Pass::FS)
+	if(technique == RenderingTechnique::GBUFFER || technique == RenderingTechnique::FORWARD)
 	{
 	{
 		return true;
 		return true;
 	}
 	}
@@ -30,7 +30,7 @@ static Bool attributeIsRequired(VertexAttributeId loc, Pass pass, Bool hasSkin)
 
 
 void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& inf) const
 void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& inf) const
 {
 {
-	ANKI_ASSERT(!(!m_model->supportsSkinning() && key.isSkinned()));
+	ANKI_ASSERT(!(!supportsSkinning() && key.getSkinned()));
 	const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
 	const U32 meshLod = min<U32>(key.getLod(), m_meshLodCount - 1);
 
 
 	// Vertex attributes & bindings
 	// Vertex attributes & bindings
@@ -43,7 +43,8 @@ void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& i
 
 
 		for(VertexAttributeId loc : EnumIterable<VertexAttributeId>())
 		for(VertexAttributeId loc : EnumIterable<VertexAttributeId>())
 		{
 		{
-			if(!m_presentVertexAttributes.get(loc) || !attributeIsRequired(loc, key.getPass(), key.isSkinned()))
+			if(!m_presentVertexAttributes.get(loc)
+			   || !attributeIsRequired(loc, key.getRenderingTechnique(), key.getSkinned()))
 			{
 			{
 				continue;
 				continue;
 			}
 			}
@@ -88,59 +89,24 @@ void ModelPatch::getRenderingInfo(const RenderingKey& key, ModelRenderingInfo& i
 	inf.m_indexType = m_indexType;
 	inf.m_indexType = m_indexType;
 
 
 	// Get program
 	// Get program
-	{
-		RenderingKey mtlKey = key;
-		mtlKey.setLod(min(key.getLod(), m_mtl->getLodCount() - 1));
-
-		const MaterialVariant& variant = m_mtl->getOrCreateVariant(mtlKey);
-
-		inf.m_program = variant.getShaderProgram();
-
-		if(m_mtl->supportsSkinning())
-		{
-			inf.m_boneTransformsBinding = m_mtl->getBoneTransformsStorageBlockBinding();
-			inf.m_prevFrameBoneTransformsBinding = m_mtl->getPrevFrameBoneTransformsStorageBlockBinding();
-		}
-		else
-		{
-			inf.m_boneTransformsBinding = inf.m_prevFrameBoneTransformsBinding = MAX_U32;
-		}
-	}
+	const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
+	inf.m_program = variant.getShaderProgram();
 }
 }
 
 
-void ModelPatch::getRayTracingInfo(U32 lod, ModelRayTracingInfo& info) const
+void ModelPatch::getRayTracingInfo(const RenderingKey& key, ModelRayTracingInfo& info) const
 {
 {
-	ANKI_ASSERT(m_mtl->getSupportedRayTracingTypes() != RayTypeBit::NONE);
-
-	info.m_grObjectReferenceCount = 0;
-	memset(&info.m_descriptor, 0, sizeof(info.m_descriptor));
+	ANKI_ASSERT(!!(m_mtl->getRenderingTechniques() & RenderingTechniqueBit(1 << key.getRenderingTechnique())));
 
 
 	// Mesh
 	// Mesh
-	const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshLodCount - 1), lod)];
+	const MeshResourcePtr& mesh = m_meshes[min(U32(m_meshLodCount - 1), key.getLod())];
 	info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
 	info.m_bottomLevelAccelerationStructure = mesh->getBottomLevelAccelerationStructure();
-	info.m_descriptor.m_mesh = mesh->getMeshGpuDescriptor();
-	info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getIndexBuffer();
-	info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getVertexBuffer();
 
 
 	// Material
 	// Material
-	info.m_descriptor.m_material = m_mtl->getMaterialGpuDescriptor();
-	for(RayType rayType : EnumIterable<RayType>())
-	{
-		if(!!(m_mtl->getSupportedRayTracingTypes() & RayTypeBit(1 << rayType)))
-		{
-			info.m_shaderGroupHandleIndices[rayType] = m_mtl->getShaderGroupHandleIndex(rayType);
-		}
-		else
-		{
-			info.m_shaderGroupHandleIndices[rayType] = MAX_U32;
-		}
-	}
+	const MaterialVariant& variant = m_mtl->getOrCreateVariant(key);
+	info.m_shaderGroupHandleIndex = variant.getRtShaderGroupHandleIndex();
 
 
-	ConstWeakArray<TextureViewPtr> textureViews = m_mtl->getAllTextureViews();
-	for(U32 i = 0; i < textureViews.getSize(); ++i)
-	{
-		info.m_grObjectReferences[info.m_grObjectReferenceCount++] = textureViews[i];
-	}
+	// Misc
+	info.m_grObjectReferences = m_grObjectRefs;
 }
 }
 
 
 Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName,
 Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames, const CString& mtlFName,
@@ -154,6 +120,17 @@ Error ModelPatch::init(ModelResource* model, ConstWeakArray<CString> meshFNames,
 	// Load material
 	// Load material
 	ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
 	ANKI_CHECK(manager->loadResource(mtlFName, m_mtl, async));
 
 
+	// Gather the material refs
+	if(m_mtl->getAllTextures().getSize())
+	{
+		m_grObjectRefs.resizeStorage(model->getAllocator(), m_mtl->getAllTextures().getSize());
+
+		for(U32 i = 0; i < m_mtl->getAllTextures().getSize(); ++i)
+		{
+			m_grObjectRefs.emplaceBack(model->getAllocator(), m_mtl->getAllTextures()[i]);
+		}
+	}
+
 	// Load meshes
 	// Load meshes
 	m_meshLodCount = 0;
 	m_meshLodCount = 0;
 	for(U32 lod = 0; lod < meshFNames.getSize(); lod++)
 	for(U32 lod = 0; lod < meshFNames.getSize(); lod++)
@@ -267,6 +244,12 @@ ModelResource::ModelResource(ResourceManager* manager)
 ModelResource::~ModelResource()
 ModelResource::~ModelResource()
 {
 {
 	auto alloc = getAllocator();
 	auto alloc = getAllocator();
+
+	for(ModelPatch& patch : m_modelPatches)
+	{
+		patch.m_grObjectRefs.destroy(alloc);
+	}
+
 	m_modelPatches.destroy(alloc);
 	m_modelPatches.destroy(alloc);
 }
 }
 
 
@@ -361,8 +344,6 @@ Error ModelResource::load(const ResourceFilename& filename, Bool async)
 			return Error::USER_DATA;
 			return Error::USER_DATA;
 		}
 		}
 
 
-		m_skinning = m_modelPatches[count].supportsSkinning();
-
 		// Move to next
 		// Move to next
 		ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
 		ANKI_CHECK(modelPatchEl.getNextSiblingElement("modelPatch", modelPatchEl));
 		++count;
 		++count;

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