Browse Source

Merge branch 'master' of https://github.com/godlikepanos/anki-3d-engine into DLSS_Integration_DONOTPUSH

# Conflicts:
#	AnKi/Gr/GrManager.h
#	AnKi/Gr/Vulkan/Common.h
#	AnKi/Renderer/VrsSriGeneration.cpp
#	AnKi/Shaders/VrsSriGeneration.glsl
Sergio Alapont 3 years ago
parent
commit
a86b6d4d8f
100 changed files with 874 additions and 809 deletions
  1. 2 1
      AnKi/Collision/Aabb.cpp
  2. 1 1
      AnKi/Collision/Aabb.h
  3. 2 2
      AnKi/Collision/ConvexHullShape.h
  4. 6 6
      AnKi/Collision/FunctionsTestCollision.cpp
  5. 2 1
      AnKi/Collision/Obb.cpp
  6. 1 1
      AnKi/Collision/Obb.h
  7. 3 3
      AnKi/Collision/Ray.h
  8. 2 1
      AnKi/Collision/Sphere.cpp
  9. 0 2
      AnKi/Config.h.cmake
  10. 4 4
      AnKi/Core/App.cpp
  11. 5 6
      AnKi/Core/App.h
  12. 3 3
      AnKi/Core/ConfigSet.h
  13. 1 2
      AnKi/Core/CoreTracer.cpp
  14. 1 1
      AnKi/Core/CoreTracer.h
  15. 1 1
      AnKi/Core/DeveloperConsole.h
  16. 1 1
      AnKi/Core/GpuMemoryPools.cpp
  17. 3 3
      AnKi/Core/GpuMemoryPools.h
  18. 1 1
      AnKi/Core/NativeWindow.h
  19. 1 1
      AnKi/Core/NativeWindowAndroid.h
  20. 0 2
      AnKi/Core/NativeWindowSdl.cpp
  21. 1 1
      AnKi/Core/NativeWindowSdl.h
  22. 1 1
      AnKi/Core/StatsUi.h
  23. 1 1
      AnKi/Core/StdinListener.h
  24. 2 2
      AnKi/Gr/AccelerationStructure.h
  25. 1 1
      AnKi/Gr/Buffer.h
  26. 3 3
      AnKi/Gr/CommandBuffer.h
  27. 1 1
      AnKi/Gr/Common.h
  28. 1 1
      AnKi/Gr/DLSSCtx.h
  29. 1 1
      AnKi/Gr/Fence.h
  30. 1 1
      AnKi/Gr/Framebuffer.h
  31. 14 14
      AnKi/Gr/GrManager.h
  32. 1 1
      AnKi/Gr/OcclusionQuery.h
  33. 7 9
      AnKi/Gr/RenderGraph.cpp
  34. 2 3
      AnKi/Gr/RenderGraph.h
  35. 5 10
      AnKi/Gr/RenderGraph.inl.h
  36. 1 1
      AnKi/Gr/Sampler.h
  37. 1 1
      AnKi/Gr/Shader.h
  38. 1 1
      AnKi/Gr/ShaderProgram.h
  39. 1 1
      AnKi/Gr/Texture.h
  40. 1 5
      AnKi/Gr/TextureView.h
  41. 1 1
      AnKi/Gr/TimestampQuery.h
  42. 1 1
      AnKi/Gr/Utils/FrameGpuAllocator.h
  43. 4 2
      AnKi/Gr/Utils/Functions.cpp
  44. 1 1
      AnKi/Gr/Vulkan/AccelerationStructureImpl.h
  45. 93 3
      AnKi/Gr/Vulkan/BufferImpl.cpp
  46. 9 2
      AnKi/Gr/Vulkan/BufferImpl.h
  47. 7 5
      AnKi/Gr/Vulkan/CommandBuffer.cpp
  48. 2 4
      AnKi/Gr/Vulkan/CommandBufferFactory.cpp
  49. 4 4
      AnKi/Gr/Vulkan/CommandBufferFactory.h
  50. 23 8
      AnKi/Gr/Vulkan/CommandBufferImpl.cpp
  51. 9 1
      AnKi/Gr/Vulkan/CommandBufferImpl.h
  52. 21 16
      AnKi/Gr/Vulkan/CommandBufferImpl.inl.h
  53. 4 4
      AnKi/Gr/Vulkan/Common.cpp
  54. 54 48
      AnKi/Gr/Vulkan/Common.h
  55. 1 1
      AnKi/Gr/Vulkan/DLSSCtxImpl.h
  56. 256 195
      AnKi/Gr/Vulkan/DescriptorSet.cpp
  57. 38 62
      AnKi/Gr/Vulkan/DescriptorSet.h
  58. 6 0
      AnKi/Gr/Vulkan/FrameGarbageCollector.cpp
  59. 1 0
      AnKi/Gr/Vulkan/FrameGarbageCollector.h
  60. 3 4
      AnKi/Gr/Vulkan/FramebufferImpl.cpp
  61. 2 2
      AnKi/Gr/Vulkan/FramebufferImpl.h
  62. 4 8
      AnKi/Gr/Vulkan/GpuMemoryManager.cpp
  63. 2 2
      AnKi/Gr/Vulkan/GpuMemoryManager.h
  64. 61 106
      AnKi/Gr/Vulkan/GrManagerImpl.cpp
  65. 26 37
      AnKi/Gr/Vulkan/GrManagerImpl.h
  66. 1 1
      AnKi/Gr/Vulkan/OcclusionQueryImpl.h
  67. 2 3
      AnKi/Gr/Vulkan/PipelineCache.h
  68. 2 2
      AnKi/Gr/Vulkan/PipelineLayout.h
  69. 1 1
      AnKi/Gr/Vulkan/QueryFactory.h
  70. 1 1
      AnKi/Gr/Vulkan/SamplerFactory.cpp
  71. 3 3
      AnKi/Gr/Vulkan/SamplerFactory.h
  72. 1 1
      AnKi/Gr/Vulkan/SamplerImpl.h
  73. 14 1
      AnKi/Gr/Vulkan/ShaderImpl.cpp
  74. 1 1
      AnKi/Gr/Vulkan/ShaderImpl.h
  75. 4 2
      AnKi/Gr/Vulkan/SwapchainFactory.cpp
  76. 1 1
      AnKi/Gr/Vulkan/SwapchainFactory.h
  77. 17 43
      AnKi/Gr/Vulkan/TextureImpl.cpp
  78. 13 21
      AnKi/Gr/Vulkan/TextureImpl.h
  79. 1 8
      AnKi/Gr/Vulkan/TextureView.cpp
  80. 4 7
      AnKi/Gr/Vulkan/TextureViewImpl.cpp
  81. 3 4
      AnKi/Gr/Vulkan/TextureViewImpl.h
  82. 1 1
      AnKi/Gr/Vulkan/TimestampQueryImpl.h
  83. 6 4
      AnKi/Importer/GltfImporter.cpp
  84. 15 16
      AnKi/Importer/GltfImporter.h
  85. 27 33
      AnKi/Importer/ImageImporter.cpp
  86. 3 3
      AnKi/Importer/ImageImporter.h
  87. 3 3
      AnKi/Input/Input.h
  88. 1 1
      AnKi/Input/InputAndroid.h
  89. 2 2
      AnKi/Math/Mat.h
  90. 1 2
      AnKi/Math/Transform.h
  91. 5 5
      AnKi/Physics/Common.h
  92. 5 4
      AnKi/Physics/PhysicsDrawer.h
  93. 2 1
      AnKi/Physics/PhysicsPlayerController.h
  94. 3 3
      AnKi/Physics/PhysicsTrigger.h
  95. 1 3
      AnKi/Physics/PhysicsWorld.cpp
  96. 2 2
      AnKi/Physics/PhysicsWorld.h
  97. 1 1
      AnKi/Renderer/AccelerationStructureBuilder.h
  98. 4 4
      AnKi/Renderer/Bloom.h
  99. 2 1
      AnKi/Renderer/ClusterBinning.cpp
  100. 1 1
      AnKi/Renderer/ClusterBinning.h

+ 2 - 1
AnKi/Collision/Aabb.cpp

@@ -38,7 +38,8 @@ Aabb Aabb::getCompoundShape(const Aabb& b) const
 	return out;
 }
 
-void Aabb::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride, PtrSize buffSize)
+void Aabb::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride,
+							 [[maybe_unused]] PtrSize buffSize)
 {
 	// Preconditions
 	ANKI_ASSERT(pointBuffer);

+ 1 - 1
AnKi/Collision/Aabb.h

@@ -92,7 +92,7 @@ public:
 	}
 
 	/// Compute the GJK support.
-	ANKI_USE_RESULT Vec4 computeSupport(const Vec4& dir) const;
+	[[nodiscard]] Vec4 computeSupport(const Vec4& dir) const;
 
 	/// It uses a nice trick to avoid unwanted calculations
 	Aabb getTransformed(const Transform& transform) const;

+ 2 - 2
AnKi/Collision/ConvexHullShape.h

@@ -82,10 +82,10 @@ public:
 	void setTransform(const Transform& trf);
 
 	/// Get a transformed.
-	ANKI_USE_RESULT ConvexHullShape getTransformed(const Transform& trf) const;
+	[[nodiscard]] ConvexHullShape getTransformed(const Transform& trf) const;
 
 	/// Compute the GJK support.
-	ANKI_USE_RESULT Vec4 computeSupport(const Vec4& dir) const;
+	[[nodiscard]] Vec4 computeSupport(const Vec4& dir) const;
 
 private:
 	Transform m_trf;

+ 6 - 6
AnKi/Collision/FunctionsTestCollision.cpp

@@ -161,7 +161,7 @@ Bool testCollision(const Aabb& aabb, const LineSegment& ls)
 	return true;
 }
 
-Bool testCollision(const Aabb& aabb, const Cone& cone)
+Bool testCollision([[maybe_unused]] const Aabb& aabb, [[maybe_unused]] const Cone& cone)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;
@@ -294,7 +294,7 @@ Bool testCollision(const Obb& obb, const LineSegment& ls)
 	return true;
 }
 
-Bool testCollision(const Obb& obb, const Cone& cone)
+Bool testCollision([[maybe_unused]] const Obb& obb, [[maybe_unused]] const Cone& cone)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;
@@ -305,25 +305,25 @@ Bool testCollision(const ConvexHullShape& a, const ConvexHullShape& b)
 	return testCollisionGjk(a, b);
 }
 
-Bool testCollision(const ConvexHullShape& hull, const LineSegment& ls)
+Bool testCollision([[maybe_unused]] const ConvexHullShape& hull, [[maybe_unused]] const LineSegment& ls)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;
 }
 
-Bool testCollision(const ConvexHullShape& hull, const Cone& cone)
+Bool testCollision([[maybe_unused]] const ConvexHullShape& hull, [[maybe_unused]] const Cone& cone)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;
 }
 
-Bool testCollision(const LineSegment& a, const LineSegment& b)
+Bool testCollision([[maybe_unused]] const LineSegment& a, [[maybe_unused]] const LineSegment& b)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;
 }
 
-Bool testCollision(const Cone& a, const Cone& b)
+Bool testCollision([[maybe_unused]] const Cone& a, [[maybe_unused]] const Cone& b)
 {
 	ANKI_ASSERT(!"TODO");
 	return false;

+ 2 - 1
AnKi/Collision/Obb.cpp

@@ -74,7 +74,8 @@ void Obb::getExtremePoints(Array<Vec4, 8>& points) const
 	}
 }
 
-void Obb::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride, PtrSize buffSize)
+void Obb::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride,
+							[[maybe_unused]] PtrSize buffSize)
 {
 	// Preconditions
 	ANKI_ASSERT(pointBuffer);

+ 1 - 1
AnKi/Collision/Obb.h

@@ -105,7 +105,7 @@ public:
 	void getExtremePoints(Array<Vec4, 8>& points) const;
 
 	/// Compute the GJK support.
-	ANKI_USE_RESULT Vec4 computeSupport(const Vec4& dir) const;
+	[[nodiscard]] Vec4 computeSupport(const Vec4& dir) const;
 
 private:
 	Vec4 m_center

+ 3 - 3
AnKi/Collision/Ray.h

@@ -62,7 +62,7 @@ public:
 		m_origin = origin.xyz0();
 	}
 
-	ANKI_USE_RESULT const Vec4& getOrigin() const
+	[[nodiscard]] const Vec4& getOrigin() const
 	{
 		check();
 		return m_origin;
@@ -78,13 +78,13 @@ public:
 		m_dir = dir.xyz0();
 	}
 
-	ANKI_USE_RESULT const Vec4& getDirection() const
+	[[nodiscard]] const Vec4& getDirection() const
 	{
 		check();
 		return m_dir;
 	}
 
-	ANKI_USE_RESULT Ray getTransformed(const Transform& trf) const
+	[[nodiscard]] Ray getTransformed(const Transform& trf) const
 	{
 		check();
 		Ray out;

+ 2 - 1
AnKi/Collision/Sphere.cpp

@@ -31,7 +31,8 @@ Sphere Sphere::getCompoundShape(const Sphere& b) const
 	return Sphere((ca + cb) / 2.0f, (ca - cb).getLength() / 2.0f);
 }
 
-void Sphere::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride, PtrSize buffSize)
+void Sphere::setFromPointCloud(const Vec3* pointBuffer, U pointCount, PtrSize pointStride,
+							   [[maybe_unused]] PtrSize buffSize)
 {
 	// Calc center
 	{

+ 0 - 2
AnKi/Config.h.cmake

@@ -167,7 +167,6 @@
 #	define ANKI_LIKELY(x) __builtin_expect(!!(x), 1)
 #	define ANKI_UNLIKELY(x) __builtin_expect(!!(x), 0)
 #	define ANKI_RESTRICT __restrict
-#	define ANKI_USE_RESULT __attribute__((warn_unused_result))
 #	define ANKI_FORCE_INLINE __attribute__((always_inline))
 #	define ANKI_DONT_INLINE __attribute__((noinline))
 #	define ANKI_UNUSED __attribute__((__unused__))
@@ -181,7 +180,6 @@
 #	define ANKI_LIKELY(x) (x)
 #	define ANKI_UNLIKELY(x) (x)
 #	define ANKI_RESTRICT
-#	define ANKI_USE_RESULT
 #	define ANKI_FORCE_INLINE
 #	define ANKI_DONT_INLINE
 #	define ANKI_UNUSED

+ 4 - 4
AnKi/Core/App.cpp

@@ -43,7 +43,7 @@ namespace anki {
 android_app* g_androidApp = nullptr;
 #endif
 
-void* App::MemStats::allocCallback(void* userData, void* ptr, PtrSize size, PtrSize alignment)
+void* App::MemStats::allocCallback(void* userData, void* ptr, PtrSize size, [[maybe_unused]] PtrSize alignment)
 {
 	ANKI_ASSERT(userData);
 
@@ -154,11 +154,11 @@ void App::cleanup()
 	m_cacheDir.destroy(m_heapAlloc);
 }
 
-Error App::init(ConfigSet* config, CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData)
+Error App::init(ConfigSet* config, AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 	ANKI_ASSERT(config);
 	m_config = config;
-	const Error err = initInternal(executableFilename, allocCb, allocCbUserData);
+	const Error err = initInternal(allocCb, allocCbUserData);
 	if(err)
 	{
 		ANKI_CORE_LOGE("App initialization failed. Shutting down");
@@ -168,7 +168,7 @@ Error App::init(ConfigSet* config, CString executableFilename, AllocAlignedCallb
 	return err;
 }
 
-Error App::initInternal(CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData)
+Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 	LoggerSingleton::get().enableVerbosity(m_config->getCoreVerboseLog());
 

+ 5 - 6
AnKi/Core/App.h

@@ -42,8 +42,7 @@ public:
 
 	/// Initialize the application.
 	/// @param[in,out] config The config. Needs to be alive as long as the app is alive.
-	ANKI_USE_RESULT Error init(ConfigSet* config, CString executableFilename, AllocAlignedCallback allocCb,
-							   void* allocCbUserData);
+	Error init(ConfigSet* config, AllocAlignedCallback allocCb, void* allocCbUserData);
 
 	const String& getSettingsDirectory() const
 	{
@@ -81,10 +80,10 @@ public:
 	}
 
 	/// Run the main loop.
-	ANKI_USE_RESULT Error mainLoop();
+	Error mainLoop();
 
 	/// The user code to run along with the other main loop code.
-	virtual ANKI_USE_RESULT Error userMainLoop(Bool& quit, Second elapsedTime)
+	virtual Error userMainLoop([[maybe_unused]] Bool& quit, [[maybe_unused]] Second elapsedTime)
 	{
 		// Do nothing
 		return Error::NONE;
@@ -200,9 +199,9 @@ private:
 
 	void initMemoryCallbacks(AllocAlignedCallback allocCb, void* allocCbUserData);
 
-	ANKI_USE_RESULT Error initInternal(CString executableFilename, AllocAlignedCallback allocCb, void* allocCbUserData);
+	Error initInternal(AllocAlignedCallback allocCb, void* allocCbUserData);
 
-	ANKI_USE_RESULT Error initDirs();
+	Error initDirs();
 	void cleanup();
 
 	/// Inject a new UI element in the render queue for displaying various stuff.

+ 3 - 3
AnKi/Core/ConfigSet.h

@@ -37,11 +37,11 @@ public:
 
 	void init(AllocAlignedCallback allocCb, void* allocCbUserData);
 
-	ANKI_USE_RESULT Error loadFromFile(CString filename);
+	Error loadFromFile(CString filename);
 
-	ANKI_USE_RESULT Error saveToFile(CString filename) const;
+	Error saveToFile(CString filename) const;
 
-	ANKI_USE_RESULT Error setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[]);
+	Error setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[]);
 
 	// Define getters and setters
 #if ANKI_EXTRA_CHECKS

+ 1 - 2
AnKi/Core/CoreTracer.cpp

@@ -70,8 +70,7 @@ CoreTracer::~CoreTracer()
 		m_quit = true;
 		m_cvar.notifyOne();
 	}
-	Error err = m_thread.join();
-	(void)err;
+	[[maybe_unused]] Error err = m_thread.join();
 
 	// Finalize trace file
 	if(m_traceJsonFile.isOpen())

+ 1 - 1
AnKi/Core/CoreTracer.h

@@ -25,7 +25,7 @@ public:
 	~CoreTracer();
 
 	/// @param directory The directory to store the trace and counters.
-	ANKI_USE_RESULT Error init(GenericMemoryPoolAllocator<U8> alloc, CString directory);
+	Error init(GenericMemoryPoolAllocator<U8> alloc, CString directory);
 
 	/// It will flush everything.
 	void flushFrame(U64 frame);

+ 1 - 1
AnKi/Core/DeveloperConsole.h

@@ -26,7 +26,7 @@ public:
 
 	~DeveloperConsole();
 
-	ANKI_USE_RESULT Error init(AllocAlignedCallback allocCb, void* allocCbUserData, ScriptManager* scriptManager);
+	Error init(AllocAlignedCallback allocCb, void* allocCbUserData, ScriptManager* scriptManager);
 
 	void build(CanvasPtr ctx) override;
 

+ 1 - 1
AnKi/Core/GpuMemoryPools.cpp

@@ -42,7 +42,7 @@ Error VertexGpuMemoryPool::init(GenericMemoryPoolAllocator<U8> alloc, GrManager*
 	return Error::NONE;
 }
 
-ANKI_USE_RESULT Error VertexGpuMemoryPool::allocate(PtrSize size, PtrSize& offset)
+Error VertexGpuMemoryPool::allocate(PtrSize size, PtrSize& offset)
 {
 	U32 offset32;
 	const Bool success = m_buddyAllocator.allocate(size, 4, offset32);

+ 3 - 3
AnKi/Core/GpuMemoryPools.h

@@ -30,9 +30,9 @@ public:
 
 	VertexGpuMemoryPool& operator=(const VertexGpuMemoryPool&) = delete; // Non-copyable
 
-	ANKI_USE_RESULT Error init(GenericMemoryPoolAllocator<U8> alloc, GrManager* gr, const ConfigSet& cfg);
+	Error init(GenericMemoryPoolAllocator<U8> alloc, GrManager* gr, const ConfigSet& cfg);
 
-	ANKI_USE_RESULT Error allocate(PtrSize size, PtrSize& offset);
+	Error allocate(PtrSize size, PtrSize& offset);
 
 	void free(PtrSize size, PtrSize offset);
 
@@ -103,7 +103,7 @@ public:
 
 	StagingGpuMemoryPool& operator=(const StagingGpuMemoryPool&) = delete; // Non-copyable
 
-	ANKI_USE_RESULT Error init(GrManager* gr, const ConfigSet& cfg);
+	Error init(GrManager* gr, const ConfigSet& cfg);
 
 	void endFrame();
 

+ 1 - 1
AnKi/Core/NativeWindow.h

@@ -38,7 +38,7 @@ public:
 class NativeWindow
 {
 public:
-	static ANKI_USE_RESULT Error newInstance(const NativeWindowInitInfo& initInfo, NativeWindow*& nativeWindow);
+	static Error newInstance(const NativeWindowInitInfo& initInfo, NativeWindow*& nativeWindow);
 
 	static void deleteInstance(NativeWindow* nativeWindow);
 

+ 1 - 1
AnKi/Core/NativeWindowAndroid.h

@@ -18,7 +18,7 @@ public:
 
 	~NativeWindowAndroid();
 
-	ANKI_USE_RESULT Error init(const NativeWindowInitInfo& init);
+	Error init(const NativeWindowInitInfo& init);
 };
 
 } // end namespace anki

+ 0 - 2
AnKi/Core/NativeWindowSdl.cpp

@@ -95,8 +95,6 @@ Error NativeWindowSdl::init(const NativeWindowInitInfo& init)
 	if(init.m_fullscreenDesktopRez)
 	{
 #if ANKI_OS_WINDOWS
-		flags |= SDL_WINDOW_FULLSCREEN;
-
 		if(init.m_exclusiveFullscreen)
 		{
 			flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;

+ 1 - 1
AnKi/Core/NativeWindowSdl.h

@@ -18,7 +18,7 @@ public:
 
 	~NativeWindowSdl();
 
-	ANKI_USE_RESULT Error init(const NativeWindowInitInfo& init);
+	Error init(const NativeWindowInitInfo& init);
 
 private:
 	static constexpr U32 INIT_SUBSYSTEMS =

+ 1 - 1
AnKi/Core/StatsUi.h

@@ -26,7 +26,7 @@ public:
 
 	~StatsUi();
 
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	void build(CanvasPtr ctx) override;
 

+ 1 - 1
AnKi/Core/StdinListener.h

@@ -26,7 +26,7 @@ public:
 
 	~StdinListener();
 
-	ANKI_USE_RESULT Error create(HeapAllocator<String>& alloc);
+	Error create(HeapAllocator<String>& alloc);
 
 	/// Get line from the queue or return an empty string
 	String getLine();

+ 2 - 2
AnKi/Gr/AccelerationStructure.h

@@ -137,8 +137,8 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT AccelerationStructure* newInstance(GrManager* manager,
-															  const AccelerationStructureInitInfo& init);
+	[[nodiscard]] static AccelerationStructure* newInstance(GrManager* manager,
+															const AccelerationStructureInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Buffer.h

@@ -125,7 +125,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT Buffer* newInstance(GrManager* manager, const BufferInitInfo& init);
+	[[nodiscard]] static Buffer* newInstance(GrManager* manager, const BufferInitInfo& init);
 };
 /// @}
 

+ 3 - 3
AnKi/Gr/CommandBuffer.h

@@ -279,8 +279,8 @@ public:
 	///              of the buffer.
 	/// @param fmt The format of the buffer.
 	/// @param arrayIdx The array index if the binding is an array.
-	void bindTextureBuffer(U32 set, U32 binding, const BufferPtr& buff, PtrSize offset, PtrSize range, Format fmt,
-						   U32 arrayIdx = 0);
+	void bindReadOnlyTextureBuffer(U32 set, U32 binding, const BufferPtr& buff, PtrSize offset, PtrSize range,
+								   Format fmt, U32 arrayIdx = 0);
 
 	/// Bind an acceleration structure.
 	/// @param set The set to bind to.
@@ -467,7 +467,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT CommandBuffer* newInstance(GrManager* manager, const CommandBufferInitInfo& init);
+	[[nodiscard]] static CommandBuffer* newInstance(GrManager* manager, const CommandBufferInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Common.h

@@ -44,7 +44,7 @@ constexpr U32 MAX_BINDINGS_PER_DESCRIPTOR_SET = 32;
 constexpr U32 MAX_FRAMES_IN_FLIGHT = 3; ///< Triple buffering.
 constexpr U32 MAX_GR_OBJECT_NAME_LENGTH = 31;
 constexpr U32 MAX_BINDLESS_TEXTURES = 512;
-constexpr U32 MAX_BINDLESS_IMAGES = 64;
+constexpr U32 MAX_BINDLESS_READONLY_TEXTURE_BUFFERS = 512;
 
 /// The number of commands in a command buffer that make it a small batch command buffer.
 constexpr U32 COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS = 100;

+ 1 - 1
AnKi/Gr/DLSSCtx.h

@@ -57,7 +57,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT DLSSCtx* newInstance(GrManager* manager, const DLSSCtxInitInfo& init);
+	static [[nodiscard]] DLSSCtx* newInstance(GrManager* manager, const DLSSCtxInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Fence.h

@@ -39,7 +39,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT Fence* newInstance(GrManager* manager);
+	[[nodiscard]] static Fence* newInstance(GrManager* manager);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Framebuffer.h

@@ -130,7 +130,7 @@ protected:
 	}
 
 private:
-	static ANKI_USE_RESULT Framebuffer* newInstance(GrManager* manager, const FramebufferInitInfo& init);
+	[[nodiscard]] static Framebuffer* newInstance(GrManager* manager, const FramebufferInitInfo& init);
 };
 /// @}
 

+ 14 - 14
AnKi/Gr/GrManager.h

@@ -50,7 +50,7 @@ class GrManager
 {
 public:
 	/// Create.
-	static ANKI_USE_RESULT Error newInstance(GrManagerInitInfo& init, GrManager*& gr);
+	static Error newInstance(GrManagerInitInfo& init, GrManager*& gr);
 
 	/// Destroy.
 	static void deleteInstance(GrManager* gr);
@@ -72,19 +72,19 @@ public:
 
 	/// @name Object creation methods. They are thread-safe.
 	/// @{
-	ANKI_USE_RESULT BufferPtr newBuffer(const BufferInitInfo& init);
-	ANKI_USE_RESULT TexturePtr newTexture(const TextureInitInfo& init);
-	ANKI_USE_RESULT TextureViewPtr newTextureView(const TextureViewInitInfo& init);
-	ANKI_USE_RESULT SamplerPtr newSampler(const SamplerInitInfo& init);
-	ANKI_USE_RESULT ShaderPtr newShader(const ShaderInitInfo& init);
-	ANKI_USE_RESULT ShaderProgramPtr newShaderProgram(const ShaderProgramInitInfo& init);
-	ANKI_USE_RESULT CommandBufferPtr newCommandBuffer(const CommandBufferInitInfo& init);
-	ANKI_USE_RESULT FramebufferPtr newFramebuffer(const FramebufferInitInfo& init);
-	ANKI_USE_RESULT OcclusionQueryPtr newOcclusionQuery();
-	ANKI_USE_RESULT TimestampQueryPtr newTimestampQuery();
-	ANKI_USE_RESULT RenderGraphPtr newRenderGraph();
-	ANKI_USE_RESULT DLSSCtxPtr newDLSSCtx(const DLSSCtxInitInfo& init);
-	ANKI_USE_RESULT AccelerationStructurePtr newAccelerationStructure(const AccelerationStructureInitInfo& init);
+	[[nodiscard]] BufferPtr newBuffer(const BufferInitInfo& init);
+	[[nodiscard]] TexturePtr newTexture(const TextureInitInfo& init);
+	[[nodiscard]] TextureViewPtr newTextureView(const TextureViewInitInfo& init);
+	[[nodiscard]] SamplerPtr newSampler(const SamplerInitInfo& init);
+	[[nodiscard]] ShaderPtr newShader(const ShaderInitInfo& init);
+	[[nodiscard]] ShaderProgramPtr newShaderProgram(const ShaderProgramInitInfo& init);
+	[[nodiscard]] CommandBufferPtr newCommandBuffer(const CommandBufferInitInfo& init);
+	[[nodiscard]] FramebufferPtr newFramebuffer(const FramebufferInitInfo& init);
+	[[nodiscard]] OcclusionQueryPtr newOcclusionQuery();
+	[[nodiscard]] TimestampQueryPtr newTimestampQuery();
+	[[nodiscard]] RenderGraphPtr newRenderGraph();
+	[[nodiscard]] DLSSCtxPtr newDLSSCtx(const DLSSCtxInitInfo& init);
+	[[nodiscard]] AccelerationStructurePtr newAccelerationStructure(const AccelerationStructureInitInfo& init);
 	/// @}
 
 	GrManagerStats getStats() const;

+ 1 - 1
AnKi/Gr/OcclusionQuery.h

@@ -37,7 +37,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT OcclusionQuery* newInstance(GrManager* manager);
+	[[nodiscard]] static OcclusionQuery* newInstance(GrManager* manager);
 };
 /// @}
 

+ 7 - 9
AnKi/Gr/RenderGraph.cpp

@@ -449,6 +449,10 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 
 	hash = appendHash(&uuids[0], sizeof(U64) * count, hash);
 
+	// Hash the name of the pass. If you don't the code bellow may fetch an FB with some another name and that will
+	// cause problems with tools. The FB name is used as a debug marker
+	hash = appendHash(name.cstr(), name.getLength(), hash);
+
 	FramebufferPtr fb;
 	auto it = m_fbCache.find(hash);
 	if(it != m_fbCache.getEnd())
@@ -508,11 +512,7 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 		}
 
 		// Set FB name
-		Array<char, MAX_GR_OBJECT_NAME_LENGTH + 1> cutName;
-		const U cutNameLen = min<U>(name.getLength(), MAX_GR_OBJECT_NAME_LENGTH);
-		memcpy(&cutName[0], &name[0], cutNameLen);
-		cutName[cutNameLen] = '\0';
-		fbInit.setName(&cutName[0]);
+		fbInit.setName(name);
 
 		// Create
 		fb = getManager().newFramebuffer(fbInit);
@@ -1021,7 +1021,7 @@ void RenderGraph::setTextureBarrier(Batch& batch, const RenderPassDependency& de
 
 					crntUsage |= depUsage;
 
-					Bool found = false;
+					[[maybe_unused]] Bool found = false;
 					for(TextureBarrier& b : batch.m_textureBarriersBefore)
 					{
 						if(b.m_idx == rtIdx && b.m_surface == surf)
@@ -1032,7 +1032,6 @@ void RenderGraph::setTextureBarrier(Batch& batch, const RenderPassDependency& de
 						}
 					}
 
-					(void)found;
 					ANKI_ASSERT(found);
 				}
 				else
@@ -1439,8 +1438,7 @@ void RenderGraph::getStatistics(RenderGraphStatistics& statistics) const
 	if(m_statistics.m_timestamps[oldFrame * 2] && m_statistics.m_timestamps[oldFrame * 2 + 1])
 	{
 		Second start, end;
-		TimestampQueryResult res = m_statistics.m_timestamps[oldFrame * 2]->getResult(start);
-		(void)res;
+		[[maybe_unused]] TimestampQueryResult res = m_statistics.m_timestamps[oldFrame * 2]->getResult(start);
 		ANKI_ASSERT(res == TimestampQueryResult::AVAILABLE);
 
 		res = m_statistics.m_timestamps[oldFrame * 2 + 1]->getResult(end);

+ 2 - 3
AnKi/Gr/RenderGraph.h

@@ -708,7 +708,7 @@ private:
 
 	~RenderGraph();
 
-	static ANKI_USE_RESULT RenderGraph* newInstance(GrManager* manager);
+	[[nodiscard]] static RenderGraph* newInstance(GrManager* manager);
 
 	BakeContext* newContext(const RenderGraphDescription& descr, StackAllocator<U8>& alloc);
 	void initRenderPassesAndSetDeps(const RenderGraphDescription& descr, StackAllocator<U8>& alloc);
@@ -739,8 +739,7 @@ private:
 
 	/// @name Dump the dependency graph into a file.
 	/// @{
-	ANKI_USE_RESULT Error dumpDependencyDotFile(const RenderGraphDescription& descr, const BakeContext& ctx,
-												CString path) const;
+	Error dumpDependencyDotFile(const RenderGraphDescription& descr, const BakeContext& ctx, CString path) const;
 	static StringAuto textureUsageToStr(StackAllocator<U8>& alloc, TextureUsageBit usage);
 	static StringAuto bufferUsageToStr(StackAllocator<U8>& alloc, BufferUsageBit usage);
 	static StringAuto asUsageToStr(StackAllocator<U8>& alloc, AccelerationStructureUsageBit usage);

+ 5 - 10
AnKi/Gr/RenderGraph.inl.h

@@ -72,8 +72,7 @@ inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& d
 	// Validate dep
 	if(dep.m_type == RenderPassDependency::Type::TEXTURE)
 	{
-		const TextureUsageBit usage = dep.m_texture.m_usage;
-		(void)usage;
+		[[maybe_unused]] const TextureUsageBit usage = dep.m_texture.m_usage;
 		if(m_type == Type::GRAPHICS)
 		{
 			ANKI_ASSERT(!(usage & TextureUsageBit::ALL_COMPUTE));
@@ -87,8 +86,7 @@ inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& d
 	}
 	else if(dep.m_type == RenderPassDependency::Type::BUFFER)
 	{
-		const BufferUsageBit usage = dep.m_buffer.m_usage;
-		(void)usage;
+		[[maybe_unused]] const BufferUsageBit usage = dep.m_buffer.m_usage;
 		if(m_type == Type::GRAPHICS)
 		{
 			ANKI_ASSERT(!(usage & BufferUsageBit::ALL_COMPUTE));
@@ -259,9 +257,8 @@ inline ComputeRenderPassDescription& RenderGraphDescription::newComputeRenderPas
 
 inline RenderTargetHandle RenderGraphDescription::importRenderTarget(TexturePtr tex, TextureUsageBit usage)
 {
-	for(const RT& rt : m_renderTargets)
+	for([[maybe_unused]] const RT& rt : m_renderTargets)
 	{
-		(void)rt;
 		ANKI_ASSERT(rt.m_importedTex != tex && "Already imported");
 	}
 
@@ -312,9 +309,8 @@ inline BufferHandle RenderGraphDescription::importBuffer(BufferPtr buff, BufferU
 		ANKI_ASSERT((offset + range) <= buff->getSize());
 	}
 
-	for(const Buffer& bb : m_buffers)
+	for([[maybe_unused]] const Buffer& bb : m_buffers)
 	{
-		(void)bb;
 		ANKI_ASSERT((bb.m_importedBuff != buff || !bufferRangeOverlaps(bb.m_offset, bb.m_range, offset, range))
 					&& "Range already imported");
 	}
@@ -334,9 +330,8 @@ inline BufferHandle RenderGraphDescription::importBuffer(BufferPtr buff, BufferU
 inline AccelerationStructureHandle
 RenderGraphDescription::importAccelerationStructure(AccelerationStructurePtr as, AccelerationStructureUsageBit usage)
 {
-	for(const AS& a : m_as)
+	for([[maybe_unused]] const AS& a : m_as)
 	{
-		(void)a;
 		ANKI_ASSERT(a.m_importedAs != as && "Already imported");
 	}
 

+ 1 - 1
AnKi/Gr/Sampler.h

@@ -67,7 +67,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT Sampler* newInstance(GrManager* manager, const SamplerInitInfo& init);
+	[[nodiscard]] static Sampler* newInstance(GrManager* manager, const SamplerInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Shader.h

@@ -114,7 +114,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT Shader* newInstance(GrManager* manager, const ShaderInitInfo& init);
+	[[nodiscard]] static Shader* newInstance(GrManager* manager, const ShaderInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/ShaderProgram.h

@@ -85,7 +85,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT ShaderProgram* newInstance(GrManager* manager, const ShaderProgramInitInfo& init);
+	[[nodiscard]] static ShaderProgram* newInstance(GrManager* manager, const ShaderProgramInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Texture.h

@@ -266,7 +266,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT Texture* newInstance(GrManager* manager, const TextureInitInfo& init);
+	[[nodiscard]] static Texture* newInstance(GrManager* manager, const TextureInitInfo& init);
 };
 /// @}
 

+ 1 - 5
AnKi/Gr/TextureView.h

@@ -92,10 +92,6 @@ public:
 	/// @note It's thread-safe
 	U32 getOrCreateBindlessTextureIndex();
 
-	/// Returns an index to be used for bindless access. For image read/write.
-	/// @note It's thread-safe
-	U32 getOrCreateBindlessImageIndex();
-
 protected:
 	TextureType m_texType = TextureType::COUNT;
 	TextureSubresourceInfo m_subresource;
@@ -131,7 +127,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT TextureView* newInstance(GrManager* manager, const TextureViewInitInfo& init);
+	[[nodiscard]] static TextureView* newInstance(GrManager* manager, const TextureViewInitInfo& init);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/TimestampQuery.h

@@ -37,7 +37,7 @@ protected:
 
 private:
 	/// Allocate and initialize a new instance.
-	static ANKI_USE_RESULT TimestampQuery* newInstance(GrManager* manager);
+	[[nodiscard]] static TimestampQuery* newInstance(GrManager* manager);
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Utils/FrameGpuAllocator.h

@@ -37,7 +37,7 @@ public:
 	void init(PtrSize size, U32 alignment, PtrSize maxAllocationSize = MAX_PTR_SIZE);
 
 	/// Allocate memory for a dynamic buffer.
-	ANKI_USE_RESULT Error allocate(PtrSize size, PtrSize& outOffset);
+	Error allocate(PtrSize size, PtrSize& outOffset);
 
 	/// Call this at the end of the frame.
 	/// @return The bytes that were not used. Used for statistics.

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

@@ -8,8 +8,10 @@
 namespace anki {
 
 template<typename T>
-static void writeShaderBlockMemorySanityChecks(const ShaderVariableBlockInfo& varBlkInfo, const void* elements,
-											   U32 elementsCount, void* buffBegin, const void* buffEnd)
+static void writeShaderBlockMemorySanityChecks(const ShaderVariableBlockInfo& varBlkInfo,
+											   [[maybe_unused]] const void* elements,
+											   [[maybe_unused]] U32 elementsCount, [[maybe_unused]] void* buffBegin,
+											   [[maybe_unused]] const void* buffEnd)
 {
 	// Check args
 	ANKI_ASSERT(elements != nullptr);

+ 1 - 1
AnKi/Gr/Vulkan/AccelerationStructureImpl.h

@@ -27,7 +27,7 @@ public:
 
 	~AccelerationStructureImpl();
 
-	ANKI_USE_RESULT Error init(const AccelerationStructureInitInfo& inf);
+	Error init(const AccelerationStructureInitInfo& inf);
 
 	VkAccelerationStructureKHR getHandle() const
 	{

+ 93 - 3
AnKi/Gr/Vulkan/BufferImpl.cpp

@@ -15,6 +15,19 @@ BufferImpl::~BufferImpl()
 	BufferGarbage* garbage = getAllocator().newInstance<BufferGarbage>();
 	garbage->m_bufferHandle = m_handle;
 	garbage->m_memoryHandle = m_memHandle;
+
+	if(m_views.getSize())
+	{
+		garbage->m_viewHandles.create(getAllocator(), U32(m_views.getSize()));
+
+		U32 count = 0;
+		for(auto it : m_views)
+		{
+			const VkBufferView view = it;
+			garbage->m_viewHandles[count++] = view;
+		}
+	}
+
 	getGrManagerImpl().getFrameGarbageCollector().newBufferGarbage(garbage);
 
 #if ANKI_EXTRA_CHECKS
@@ -28,6 +41,8 @@ BufferImpl::~BufferImpl()
 		ANKI_VK_LOGW("Buffer needed invalidation but you never invalidated: %s", getName().cstr());
 	}
 #endif
+
+	m_views.destroy(getAllocator());
 }
 
 Error BufferImpl::init(const BufferInitInfo& inf)
@@ -64,7 +79,7 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 	ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
 	ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
 	ANKI_VK_CHECK(vkCreateBuffer(getDevice(), &ci, nullptr, &m_handle));
-	getGrManagerImpl().trySetVulkanHandleName(inf.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m_handle);
+	getGrManagerImpl().trySetVulkanHandleName(inf.getName(), VK_OBJECT_TYPE_BUFFER, m_handle);
 
 	// Get mem requirements
 	VkMemoryRequirements req;
@@ -178,7 +193,7 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 
 	// Allocate
 	const U32 alignment = U32(max(m_mappedMemoryRangeAlignment, req.alignment));
-	getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, req.size, alignment, true, m_memHandle);
+	getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, req.size, alignment, m_memHandle);
 
 	// Bind mem to buffer
 	{
@@ -208,7 +223,7 @@ Error BufferImpl::init(const BufferInitInfo& inf)
 	return Error::NONE;
 }
 
-void* BufferImpl::map(PtrSize offset, PtrSize range, BufferMapAccessBit access)
+void* BufferImpl::map(PtrSize offset, PtrSize range, [[maybe_unused]] BufferMapAccessBit access)
 {
 	ANKI_ASSERT(isCreated());
 	ANKI_ASSERT(access != BufferMapAccessBit::NONE);
@@ -362,4 +377,79 @@ void BufferImpl::computeBarrierInfo(BufferUsageBit before, BufferUsageBit after,
 	dstAccesses = computeAccessMask(after);
 }
 
+VkBufferView BufferImpl::getOrCreateBufferView(Format fmt, PtrSize offset, PtrSize range) const
+{
+	if(range == MAX_PTR_SIZE)
+	{
+		ANKI_ASSERT(m_size >= offset);
+		range = m_size - offset;
+	}
+
+	// Checks
+	ANKI_ASSERT(!!(m_usage & BufferUsageBit::ALL_TEXTURE));
+	ANKI_ASSERT(offset + range <= m_size);
+
+	ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_textureBufferBindOffsetAlignment,
+						  m_memHandle.m_offset + offset)
+				&& "Offset not aligned");
+
+	ANKI_ASSERT((range % getFormatInfo(fmt).m_texelSize) == 0
+				&& "Range doesn't align with the number of texel elements");
+
+	[[maybe_unused]] const PtrSize elementCount = range / getFormatInfo(fmt).m_texelSize;
+	ANKI_ASSERT(elementCount <= getGrManagerImpl().getPhysicalDeviceProperties().limits.maxTexelBufferElements);
+
+	// Hash
+	ANKI_BEGIN_PACKED_STRUCT
+	class HashData
+	{
+	public:
+		PtrSize m_offset;
+		PtrSize m_range;
+		Format m_fmt;
+	} toHash;
+	ANKI_END_PACKED_STRUCT
+
+	toHash.m_fmt = fmt;
+	toHash.m_offset = offset;
+	toHash.m_range = range;
+
+	const U64 hash = computeHash(&toHash, sizeof(toHash));
+
+	// Check if exists
+	{
+		RLockGuard<RWMutex> lock(m_viewsMtx);
+
+		auto it = m_views.find(hash);
+		if(it != m_views.getEnd())
+		{
+			return *it;
+		}
+	}
+
+	WLockGuard<RWMutex> lock(m_viewsMtx);
+
+	// Check again
+	auto it = m_views.find(hash);
+	if(it != m_views.getEnd())
+	{
+		return *it;
+	}
+
+	// Doesn't exist, need to create it
+	VkBufferViewCreateInfo viewCreateInfo = {};
+	viewCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
+	viewCreateInfo.buffer = m_handle;
+	viewCreateInfo.format = convertFormat(fmt);
+	viewCreateInfo.offset = offset;
+	viewCreateInfo.range = range;
+
+	VkBufferView view;
+	ANKI_VK_CHECKF(vkCreateBufferView(getDevice(), &viewCreateInfo, nullptr, &view));
+
+	m_views.emplace(getAllocator(), hash, view);
+
+	return view;
+}
+
 } // end namespace anki

+ 9 - 2
AnKi/Gr/Vulkan/BufferImpl.h

@@ -8,6 +8,7 @@
 #include <AnKi/Gr/Buffer.h>
 #include <AnKi/Gr/Vulkan/VulkanObject.h>
 #include <AnKi/Gr/Vulkan/GpuMemoryManager.h>
+#include <AnKi/Util/HashMap.h>
 
 namespace anki {
 
@@ -27,9 +28,9 @@ public:
 
 	~BufferImpl();
 
-	ANKI_USE_RESULT Error init(const BufferInitInfo& inf);
+	Error init(const BufferInitInfo& inf);
 
-	ANKI_USE_RESULT void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access);
+	[[nodiscard]] void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access);
 
 	void unmap()
 	{
@@ -88,6 +89,9 @@ public:
 		}
 	}
 
+	/// Only for texture buffers.
+	VkBufferView getOrCreateBufferView(Format fmt, PtrSize offset, PtrSize range) const;
+
 private:
 	VkBuffer m_handle = VK_NULL_HANDLE;
 	GpuMemoryHandle m_memHandle;
@@ -97,6 +101,9 @@ private:
 	Bool m_needsFlush : 1;
 	Bool m_needsInvalidate : 1;
 
+	mutable HashMap<U64, VkBufferView> m_views; ///< Only for texture buffers.
+	mutable RWMutex m_viewsMtx;
+
 #if ANKI_EXTRA_CHECKS
 	Bool m_mapped = false;
 	mutable Atomic<U32> m_flushCount = {0};

+ 7 - 5
AnKi/Gr/Vulkan/CommandBuffer.cpp

@@ -226,10 +226,11 @@ void CommandBuffer::bindAccelerationStructure(U32 set, U32 binding, const Accele
 	self.bindAccelerationStructureInternal(set, binding, as, arrayIdx);
 }
 
-void CommandBuffer::bindTextureBuffer(U32 set, U32 binding, const BufferPtr& buff, PtrSize offset, PtrSize range,
-									  Format fmt, U32 arrayIdx)
+void CommandBuffer::bindReadOnlyTextureBuffer(U32 set, U32 binding, const BufferPtr& buff, PtrSize offset,
+											  PtrSize range, Format fmt, U32 arrayIdx)
 {
-	ANKI_ASSERT(!"TODO");
+	ANKI_VK_SELF(CommandBufferImpl);
+	self.bindReadOnlyTextureBufferInternal(set, binding, buff, offset, range, fmt, arrayIdx);
 }
 
 void CommandBuffer::bindAllBindless(U32 set)
@@ -311,12 +312,13 @@ void CommandBuffer::generateMipmaps2d(const TextureViewPtr& texView)
 	self.generateMipmaps2dInternal(texView);
 }
 
-void CommandBuffer::generateMipmaps3d(const TextureViewPtr& texView)
+void CommandBuffer::generateMipmaps3d([[maybe_unused]] const TextureViewPtr& texView)
 {
 	ANKI_ASSERT(!"TODO");
 }
 
-void CommandBuffer::blitTextureViews(const TextureViewPtr& srcView, const TextureViewPtr& destView)
+void CommandBuffer::blitTextureViews([[maybe_unused]] const TextureViewPtr& srcView,
+									 [[maybe_unused]] const TextureViewPtr& destView)
 {
 	ANKI_ASSERT(!"TODO");
 }

+ 2 - 4
AnKi/Gr/Vulkan/CommandBufferFactory.cpp

@@ -32,9 +32,8 @@ MicroCommandBuffer::~MicroCommandBuffer()
 		vkFreeCommandBuffers(m_threadAlloc->m_factory->m_dev, m_threadAlloc->m_pools[m_queue], 1, &m_handle);
 		m_handle = {};
 
-		const U32 count = m_threadAlloc->m_factory->m_createdCmdBufferCount.fetchSub(1);
+		[[maybe_unused]] const U32 count = m_threadAlloc->m_factory->m_createdCmdBufferCount.fetchSub(1);
 		ANKI_ASSERT(count > 0);
-		(void)count;
 	}
 }
 
@@ -151,9 +150,8 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 	}
 	else
 	{
-		for(GrObjectType type : EnumIterable<GrObjectType>())
+		for([[maybe_unused]] GrObjectType type : EnumIterable<GrObjectType>())
 		{
-			(void)type;
 			ANKI_ASSERT(out->m_objectRefs[type].getSize() == 0);
 		}
 	}

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

@@ -169,14 +169,14 @@ public:
 	{
 	}
 
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	void destroy();
 
 	GrAllocator<U8>& getAllocator();
 
 	/// Request a new command buffer.
-	ANKI_USE_RESULT Error newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
+	Error newCommandBuffer(CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
 
 	/// It will recycle it.
 	void deleteCommandBuffer(MicroCommandBuffer* ptr);
@@ -208,12 +208,12 @@ public:
 
 	CommandBufferFactory& operator=(const CommandBufferFactory&) = delete; // Non-copyable
 
-	ANKI_USE_RESULT Error init(GrAllocator<U8> alloc, VkDevice dev, const VulkanQueueFamilies& queueFamilies);
+	Error init(GrAllocator<U8> alloc, VkDevice dev, const VulkanQueueFamilies& queueFamilies);
 
 	void destroy();
 
 	/// Request a new command buffer.
-	ANKI_USE_RESULT Error newCommandBuffer(ThreadId tid, CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
+	Error newCommandBuffer(ThreadId tid, CommandBufferFlag cmdbFlags, MicroCommandBufferPtr& ptr);
 
 	/// Stats.
 	U32 getCreatedCommandBufferCount() const

+ 23 - 8
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -162,6 +162,8 @@ void CommandBufferImpl::beginRenderPassInternal()
 {
 	FramebufferImpl& impl = static_cast<FramebufferImpl&>(*m_activeFb);
 
+	flushBatches(CommandBufferCommandType::ANY_OTHER_COMMAND); // Flush before the marker
+
 	m_state.beginRenderPass(&impl);
 
 	VkRenderPassBeginInfo bi = {};
@@ -204,18 +206,30 @@ void CommandBufferImpl::beginRenderPassInternal()
 	bi.renderArea.extent.width = m_renderArea[2];
 	bi.renderArea.extent.height = m_renderArea[3];
 
-	getGrManagerImpl().beginMarker(m_handle, impl.getName());
+	getGrManagerImpl().beginMarker(m_handle, impl.getName(), Vec3(0.0f, 1.0f, 0.0f));
+
+#if !ANKI_PLATFORM_MOBILE
+	// nVidia SRI cache workaround
+	if(impl.hasSri())
+	{
+		VkMemoryBarrier memBarrier = {};
+		memBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+		memBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
+
+		const VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+		const VkPipelineStageFlags dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+
+		vkCmdPipelineBarrier(m_handle, srcStages, dstStages, 0, 1, &memBarrier, 0, nullptr, 0, nullptr);
+	}
+#endif
 
 	VkSubpassBeginInfo subpassBeginInfo = {};
 	subpassBeginInfo.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO;
 	subpassBeginInfo.contents = m_subpassContents;
 
-	ANKI_CMD(vkCmdBeginRenderPass2KHR(m_handle, &bi, &subpassBeginInfo), ANY_OTHER_COMMAND);
+	vkCmdBeginRenderPass2KHR(m_handle, &bi, &subpassBeginInfo);
 
-	if(impl.hasPresentableTexture())
-	{
-		m_renderedToDefaultFb = true;
-	}
+	m_renderedToDefaultFb = m_renderedToDefaultFb || impl.hasPresentableTexture();
 }
 
 void CommandBufferImpl::endRenderPassInternal()
@@ -224,6 +238,7 @@ void CommandBufferImpl::endRenderPassInternal()
 	ANKI_ASSERT(insideRenderPass());
 	if(m_rpCommandCount == 0)
 	{
+		// Empty pass
 		m_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
 		beginRenderPassInternal();
 	}
@@ -635,8 +650,8 @@ void CommandBufferImpl::flushWriteQueryResults()
 	m_writeQueryAtoms.resize(m_alloc, 0);
 }
 
-void CommandBufferImpl::copyBufferToTextureViewInternal(const BufferPtr& buff, PtrSize offset, PtrSize range,
-														const TextureViewPtr& texView)
+void CommandBufferImpl::copyBufferToTextureViewInternal(const BufferPtr& buff, PtrSize offset,
+														[[maybe_unused]] PtrSize range, const TextureViewPtr& texView)
 {
 	commandCommon();
 

+ 9 - 1
AnKi/Gr/Vulkan/CommandBufferImpl.h

@@ -58,7 +58,7 @@ public:
 
 	~CommandBufferImpl();
 
-	ANKI_USE_RESULT Error init(const CommandBufferInitInfo& init);
+	Error init(const CommandBufferInitInfo& init);
 
 	void setFence(MicroFencePtr& fence)
 	{
@@ -380,6 +380,14 @@ public:
 		m_microCmdb->pushObjectRef(buff);
 	}
 
+	void bindReadOnlyTextureBufferInternal(U32 set, U32 binding, const BufferPtr& buff, PtrSize offset, PtrSize range,
+										   Format fmt, U32 arrayIdx)
+	{
+		commandCommon();
+		m_dsetState[set].bindReadOnlyTextureBuffer(binding, arrayIdx, buff.get(), offset, range, fmt);
+		m_microCmdb->pushObjectRef(buff);
+	}
+
 	void copyBufferToTextureViewInternal(const BufferPtr& buff, PtrSize offset, PtrSize range,
 										 const TextureViewPtr& texView);
 

+ 21 - 16
AnKi/Gr/Vulkan/CommandBufferImpl.inl.h

@@ -256,9 +256,10 @@ inline void CommandBufferImpl::setBufferBarrierInternal(const BufferPtr& buff, B
 	m_microCmdb->pushObjectRef(buff);
 }
 
-inline void CommandBufferImpl::setAccelerationStructureBarrierInternal(const AccelerationStructurePtr& as,
-																	   AccelerationStructureUsageBit prevUsage,
-																	   AccelerationStructureUsageBit nextUsage)
+inline void
+CommandBufferImpl::setAccelerationStructureBarrierInternal([[maybe_unused]] const AccelerationStructurePtr& as,
+														   AccelerationStructureUsageBit prevUsage,
+														   AccelerationStructureUsageBit nextUsage)
 {
 	commandCommon();
 
@@ -288,6 +289,8 @@ inline void CommandBufferImpl::setAccelerationStructureBarrierInternal(const Acc
 #else
 	ANKI_ASSERT(!"TODO");
 #endif
+
+	// No need to hold reference since noone touches the AS
 }
 
 inline void CommandBufferImpl::drawArraysInternal(PrimitiveTopology topology, U32 count, U32 instanceCount, U32 first,
@@ -342,7 +345,9 @@ inline void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 grou
 
 	commandCommon();
 
-	getGrManagerImpl().beginMarker(m_handle, m_computeProg->getName());
+	flushBatches(CommandBufferCommandType::ANY_OTHER_COMMAND); // Do that before setting the markers
+
+	getGrManagerImpl().beginMarker(m_handle, m_computeProg->getName(), Vec3(1.0f, 1.0f, 0.0f));
 
 	// Bind descriptors
 	for(U32 i = 0; i < MAX_DESCRIPTOR_SETS; ++i)
@@ -353,8 +358,8 @@ inline void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 grou
 			Bool dirty;
 			Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET> dynamicOffsetsPtrSize;
 			U32 dynamicOffsetCount;
-			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(
-				   m_tid, m_alloc, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize, dynamicOffsetCount))
+			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(m_alloc, m_dsetState[i], dset, dirty,
+																			 dynamicOffsetsPtrSize, dynamicOffsetCount))
 			{
 				ANKI_VK_LOGF("Cannot recover");
 			}
@@ -378,7 +383,7 @@ inline void CommandBufferImpl::dispatchComputeInternal(U32 groupCountX, U32 grou
 		}
 	}
 
-	ANKI_CMD(vkCmdDispatch(m_handle, groupCountX, groupCountY, groupCountZ), ANY_OTHER_COMMAND);
+	vkCmdDispatch(m_handle, groupCountX, groupCountY, groupCountZ);
 
 	getGrManagerImpl().endMarker(m_handle);
 }
@@ -398,14 +403,15 @@ inline void CommandBufferImpl::traceRaysInternal(const BufferPtr& sbtBuffer, Ptr
 	ANKI_ASSERT(rayTypeCount == sprog.getMissShaderCount() && "All the miss shaders should be in use");
 	ANKI_ASSERT((hitGroupSbtRecordCount % rayTypeCount) == 0);
 	const PtrSize sbtRecordCount = 1 + rayTypeCount + hitGroupSbtRecordCount;
-	const PtrSize sbtBufferSize = sbtRecordCount * sbtRecordSize;
-	(void)sbtBufferSize;
+	[[maybe_unused]] const PtrSize sbtBufferSize = sbtRecordCount * sbtRecordSize;
 	ANKI_ASSERT(sbtBufferSize + sbtBufferOffset <= sbtBuffer->getSize());
 	ANKI_ASSERT(isAligned(getGrManagerImpl().getDeviceCapabilities().m_sbtRecordAlignment, sbtBufferOffset));
 
 	commandCommon();
 
-	getGrManagerImpl().beginMarker(m_handle, m_rtProg->getName());
+	flushBatches(CommandBufferCommandType::ANY_OTHER_COMMAND); // Do that before setting the markers
+
+	getGrManagerImpl().beginMarker(m_handle, m_rtProg->getName(), Vec3(0.0f, 0.0f, 1.0f));
 
 	// Bind descriptors
 	for(U32 i = 0; i < MAX_DESCRIPTOR_SETS; ++i)
@@ -416,8 +422,8 @@ inline void CommandBufferImpl::traceRaysInternal(const BufferPtr& sbtBuffer, Ptr
 			Bool dirty;
 			Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET> dynamicOffsetsPtrSize;
 			U32 dynamicOffsetCount;
-			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(
-				   m_tid, m_alloc, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize, dynamicOffsetCount))
+			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(m_alloc, m_dsetState[i], dset, dirty,
+																			 dynamicOffsetsPtrSize, dynamicOffsetCount))
 			{
 				ANKI_VK_LOGF("Cannot recover");
 			}
@@ -463,8 +469,7 @@ inline void CommandBufferImpl::traceRaysInternal(const BufferPtr& sbtBuffer, Ptr
 	// Callable, nothing for now
 	regions[3] = VkStridedDeviceAddressRegionKHR();
 
-	ANKI_CMD(vkCmdTraceRaysKHR(m_handle, &regions[0], &regions[1], &regions[2], &regions[3], width, height, depth),
-			 ANY_OTHER_COMMAND);
+	vkCmdTraceRaysKHR(m_handle, &regions[0], &regions[1], &regions[2], &regions[3], width, height, depth);
 
 	getGrManagerImpl().endMarker(m_handle);
 }
@@ -654,8 +659,8 @@ inline void CommandBufferImpl::drawcallCommon()
 			Bool dirty;
 			Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET> dynamicOffsetsPtrSize;
 			U32 dynamicOffsetCount;
-			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(
-				   m_tid, m_alloc, m_dsetState[i], dset, dirty, dynamicOffsetsPtrSize, dynamicOffsetCount))
+			if(getGrManagerImpl().getDescriptorSetFactory().newDescriptorSet(m_alloc, m_dsetState[i], dset, dirty,
+																			 dynamicOffsetsPtrSize, dynamicOffsetCount))
 			{
 				ANKI_VK_LOGF("Cannot recover");
 			}

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

@@ -298,14 +298,14 @@ VkBufferUsageFlags convertBufferUsageBit(BufferUsageBit usageMask)
 		out |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
 	}
 
-	if(!!(usageMask & (BufferUsageBit::ALL_TEXTURE & BufferUsageBit::ALL_WRITE)))
+	if(!!(usageMask & (BufferUsageBit::ALL_TEXTURE & BufferUsageBit::ALL_READ)))
 	{
-		out |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
+		out |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
 	}
 
-	if(!!(usageMask & (BufferUsageBit::ALL_TEXTURE & BufferUsageBit::ALL_READ)))
+	if(!!(usageMask & (BufferUsageBit::ALL_TEXTURE & BufferUsageBit::ALL_WRITE)))
 	{
-		out |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
+		out |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
 	}
 
 	if(!!(usageMask & BufferUsageBit::ACCELERATION_STRUCTURE_BUILD))

+ 54 - 48
AnKi/Gr/Vulkan/Common.h

@@ -53,7 +53,8 @@ enum class DescriptorType : U8
 	UNIFORM_BUFFER,
 	STORAGE_BUFFER,
 	IMAGE,
-	TEXTURE_BUFFER,
+	READ_TEXTURE_BUFFER,
+	READ_WRITE_TEXTURE_BUFFER,
 	ACCELERATION_STRUCTURE,
 
 	COUNT
@@ -69,28 +70,27 @@ enum class VulkanExtensions : U32
 	EXT_HEADLESS_SURFACE = 1 << 5,
 	KHR_SWAPCHAIN = 1 << 6,
 	KHR_SURFACE = 1 << 7,
-	EXT_DEBUG_MARKER = 1 << 8,
-	EXT_DEBUG_REPORT = 1 << 9,
-	AMD_SHADER_INFO = 1 << 10,
-	AMD_RASTERIZATION_ORDER = 1 << 11,
-	KHR_RAY_TRACING = 1 << 12,
-	KHR_PIPELINE_EXECUTABLE_PROPERTIES = 1 << 13,
-	EXT_DESCRIPTOR_INDEXING = 1 << 14,
-	KHR_BUFFER_DEVICE_ADDRESS = 1 << 15,
-	EXT_SCALAR_BLOCK_LAYOUT = 1 << 16,
-	KHR_TIMELINE_SEMAPHORE = 1 << 17,
-	KHR_SHADER_FLOAT16_INT8 = 1 << 18,
-	KHR_SHADER_ATOMIC_INT64 = 1 << 19,
-	KHR_SPIRV_1_4 = 1 << 20,
-	KHR_SHADER_FLOAT_CONTROLS = 1 << 21,
-	EXT_SAMPLER_FILTER_MIN_MAX = 1 << 22,
-	KHR_CREATE_RENDERPASS_2 = 1 << 23,
-	KHR_FRAGMENT_SHADING_RATE = 1 << 24,
-	EXT_ASTC_DECODE_MODE = 1 << 25,
-	EXT_TEXTURE_COMPRESSION_ASTC_HDR = 1 << 26,
-	NVX_BINARY_IMPORT = 1<<27,
-	NVX_IMAGE_VIEW_HANDLE = 1<<28,
-	KHR_PUSH_DESCRIPTOR = 1<<29
+	EXT_DEBUG_UTILS = 1 << 8,
+	AMD_SHADER_INFO = 1 << 9,
+	AMD_RASTERIZATION_ORDER = 1 << 10,
+	KHR_RAY_TRACING = 1 << 11,
+	KHR_PIPELINE_EXECUTABLE_PROPERTIES = 1 << 12,
+	EXT_DESCRIPTOR_INDEXING = 1 << 13,
+	KHR_BUFFER_DEVICE_ADDRESS = 1 << 14,
+	EXT_SCALAR_BLOCK_LAYOUT = 1 << 15,
+	KHR_TIMELINE_SEMAPHORE = 1 << 16,
+	KHR_SHADER_FLOAT16_INT8 = 1 << 17,
+	KHR_SHADER_ATOMIC_INT64 = 1 << 18,
+	KHR_SPIRV_1_4 = 1 << 19,
+	KHR_SHADER_FLOAT_CONTROLS = 1 << 20,
+	EXT_SAMPLER_FILTER_MIN_MAX = 1 << 21,
+	KHR_CREATE_RENDERPASS_2 = 1 << 22,
+	KHR_FRAGMENT_SHADING_RATE = 1 << 23,
+	EXT_ASTC_DECODE_MODE = 1 << 24,
+	EXT_TEXTURE_COMPRESSION_ASTC_HDR = 1 << 25,
+	NVX_BINARY_IMPORT = 1<<26,
+	NVX_IMAGE_VIEW_HANDLE = 1<<27,
+	KHR_PUSH_DESCRIPTOR = 1<<28
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VulkanExtensions)
 
@@ -152,10 +152,10 @@ static_assert(!(BufferUsageBit::ALL & PrivateBufferUsageBit::ALL_PRIVATE), "Upda
 	} while(0)
 
 /// Convert compare op.
-ANKI_USE_RESULT VkCompareOp convertCompareOp(CompareOperation ak);
+[[nodiscard]] VkCompareOp convertCompareOp(CompareOperation ak);
 
 /// Convert format.
-ANKI_USE_RESULT inline VkFormat convertFormat(const Format ak)
+[[nodiscard]] inline VkFormat convertFormat(const Format ak)
 {
 	ANKI_ASSERT(ak != Format::NONE);
 	const VkFormat out = static_cast<VkFormat>(ak);
@@ -163,7 +163,7 @@ ANKI_USE_RESULT inline VkFormat convertFormat(const Format ak)
 }
 
 /// Get format aspect mask.
-ANKI_USE_RESULT inline DepthStencilAspectBit getImageAspectFromFormat(const Format ak)
+[[nodiscard]] inline DepthStencilAspectBit getImageAspectFromFormat(const Format ak)
 {
 	DepthStencilAspectBit out = DepthStencilAspectBit::NONE;
 	if(getFormatInfo(ak).isStencil())
@@ -180,7 +180,7 @@ ANKI_USE_RESULT inline DepthStencilAspectBit getImageAspectFromFormat(const Form
 }
 
 /// Convert image aspect.
-ANKI_USE_RESULT inline VkImageAspectFlags convertImageAspect(const DepthStencilAspectBit ak)
+[[nodiscard]] inline VkImageAspectFlags convertImageAspect(const DepthStencilAspectBit ak)
 {
 	VkImageAspectFlags out = 0;
 	if(!!(ak & DepthStencilAspectBit::DEPTH))
@@ -202,46 +202,46 @@ ANKI_USE_RESULT inline VkImageAspectFlags convertImageAspect(const DepthStencilA
 }
 
 /// Convert topology.
-ANKI_USE_RESULT VkPrimitiveTopology convertTopology(PrimitiveTopology ak);
+[[nodiscard]] VkPrimitiveTopology convertTopology(PrimitiveTopology ak);
 
 /// Convert fill mode.
-ANKI_USE_RESULT VkPolygonMode convertFillMode(FillMode ak);
+[[nodiscard]] VkPolygonMode convertFillMode(FillMode ak);
 
 /// Convert cull mode.
-ANKI_USE_RESULT VkCullModeFlags convertCullMode(FaceSelectionBit ak);
+[[nodiscard]] VkCullModeFlags convertCullMode(FaceSelectionBit ak);
 
 /// Convert blend method.
-ANKI_USE_RESULT VkBlendFactor convertBlendFactor(BlendFactor ak);
+[[nodiscard]] VkBlendFactor convertBlendFactor(BlendFactor ak);
 
 /// Convert blend function.
-ANKI_USE_RESULT VkBlendOp convertBlendOperation(BlendOperation ak);
+[[nodiscard]] VkBlendOp convertBlendOperation(BlendOperation ak);
 
 /// Convert color write mask.
-inline ANKI_USE_RESULT VkColorComponentFlags convertColorWriteMask(ColorBit ak)
+[[nodiscard]] inline VkColorComponentFlags convertColorWriteMask(ColorBit ak)
 {
 	return static_cast<VkColorComponentFlags>(ak);
 }
 
 /// Convert load op.
-ANKI_USE_RESULT VkAttachmentLoadOp convertLoadOp(AttachmentLoadOperation ak);
+[[nodiscard]] VkAttachmentLoadOp convertLoadOp(AttachmentLoadOperation ak);
 
 /// Convert store op.
-ANKI_USE_RESULT VkAttachmentStoreOp convertStoreOp(AttachmentStoreOperation ak);
+[[nodiscard]] VkAttachmentStoreOp convertStoreOp(AttachmentStoreOperation ak);
 
 /// Convert buffer usage bitmask.
-ANKI_USE_RESULT VkBufferUsageFlags convertBufferUsageBit(BufferUsageBit usageMask);
+[[nodiscard]] VkBufferUsageFlags convertBufferUsageBit(BufferUsageBit usageMask);
 
-ANKI_USE_RESULT VkImageType convertTextureType(TextureType ak);
+[[nodiscard]] VkImageType convertTextureType(TextureType ak);
 
-ANKI_USE_RESULT VkImageViewType convertTextureViewType(TextureType ak);
+[[nodiscard]] VkImageViewType convertTextureViewType(TextureType ak);
 
-ANKI_USE_RESULT VkImageUsageFlags convertTextureUsage(const TextureUsageBit ak, const Format format);
+[[nodiscard]] VkImageUsageFlags convertTextureUsage(const TextureUsageBit ak, const Format format);
 
-ANKI_USE_RESULT VkStencilOp convertStencilOp(StencilOperation ak);
+[[nodiscard]] VkStencilOp convertStencilOp(StencilOperation ak);
 
-ANKI_USE_RESULT VkShaderStageFlags convertShaderTypeBit(ShaderTypeBit bit);
+[[nodiscard]] VkShaderStageFlags convertShaderTypeBit(ShaderTypeBit bit);
 
-ANKI_USE_RESULT inline VkVertexInputRate convertVertexStepRate(VertexStepRate ak)
+[[nodiscard]] inline VkVertexInputRate convertVertexStepRate(VertexStepRate ak)
 {
 	VkVertexInputRate out;
 	switch(ak)
@@ -259,7 +259,7 @@ ANKI_USE_RESULT inline VkVertexInputRate convertVertexStepRate(VertexStepRate ak
 	return out;
 }
 
-ANKI_USE_RESULT inline VkDescriptorType convertDescriptorType(DescriptorType ak)
+[[nodiscard]] inline VkDescriptorType convertDescriptorType(DescriptorType ak)
 {
 	VkDescriptorType out;
 	switch(ak)
@@ -276,6 +276,12 @@ ANKI_USE_RESULT inline VkDescriptorType convertDescriptorType(DescriptorType ak)
 	case DescriptorType::UNIFORM_BUFFER:
 		out = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
 		break;
+	case DescriptorType::READ_TEXTURE_BUFFER:
+		out = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+		break;
+	case DescriptorType::READ_WRITE_TEXTURE_BUFFER:
+		out = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+		break;
 	case DescriptorType::STORAGE_BUFFER:
 		out = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
 		break;
@@ -293,7 +299,7 @@ ANKI_USE_RESULT inline VkDescriptorType convertDescriptorType(DescriptorType ak)
 	return out;
 }
 
-ANKI_USE_RESULT inline VkIndexType convertIndexType(IndexType ak)
+[[nodiscard]] inline VkIndexType convertIndexType(IndexType ak)
 {
 	VkIndexType out;
 	switch(ak)
@@ -312,7 +318,7 @@ ANKI_USE_RESULT inline VkIndexType convertIndexType(IndexType ak)
 	return out;
 }
 
-ANKI_USE_RESULT inline VkRasterizationOrderAMD convertRasterizationOrder(RasterizationOrder ak)
+[[nodiscard]] inline VkRasterizationOrderAMD convertRasterizationOrder(RasterizationOrder ak)
 {
 	VkRasterizationOrderAMD out;
 	switch(ak)
@@ -331,7 +337,7 @@ ANKI_USE_RESULT inline VkRasterizationOrderAMD convertRasterizationOrder(Rasteri
 	return out;
 }
 
-ANKI_USE_RESULT inline VkAccelerationStructureTypeKHR convertAccelerationStructureType(AccelerationStructureType ak)
+[[nodiscard]] inline VkAccelerationStructureTypeKHR convertAccelerationStructureType(AccelerationStructureType ak)
 {
 	VkAccelerationStructureTypeKHR out;
 	switch(ak)
@@ -350,9 +356,9 @@ ANKI_USE_RESULT inline VkAccelerationStructureTypeKHR convertAccelerationStructu
 	return out;
 }
 
-ANKI_USE_RESULT const char* vkResultToString(VkResult res);
+[[nodiscard]] const char* vkResultToString(VkResult res);
 
-ANKI_USE_RESULT inline VkExtent2D convertVrsShadingRate(VrsRate rate)
+[[nodiscard]] inline VkExtent2D convertVrsShadingRate(VrsRate rate)
 {
 	VkExtent2D out = {};
 	switch(rate)

+ 1 - 1
AnKi/Gr/Vulkan/DLSSCtxImpl.h

@@ -41,7 +41,7 @@ public:
 
 	~DLSSCtxImpl();
 
-	ANKI_USE_RESULT Error init(const DLSSCtxInitInfo& init);
+	[[nodiscard]] Error init(const DLSSCtxInitInfo& init);
 
 	Bool isNgxInitialized() const { return m_ngxInitialized; }
 

+ 256 - 195
AnKi/Gr/Vulkan/DescriptorSet.cpp

@@ -13,6 +13,8 @@
 
 namespace anki {
 
+thread_local DescriptorSetFactory::ThreadLocal* DescriptorSetFactory::m_threadLocal = nullptr;
+
 /// Wraps a global descriptor set that is used to store bindless textures.
 class DescriptorSetFactory::BindlessDescriptorSet
 {
@@ -25,9 +27,9 @@ public:
 	/// @note It's thread-safe.
 	U32 bindTexture(const VkImageView view, const VkImageLayout layout);
 
-	/// Bind a storage image.
+	/// Bind a uniform texel buffer.
 	/// @note It's thread-safe.
-	U32 bindImage(const VkImageView view);
+	U32 bindUniformTexelBuffer(VkBufferView view);
 
 	/// @note It's thread-safe.
 	void unbindTexture(U32 idx)
@@ -36,9 +38,9 @@ public:
 	}
 
 	/// @note It's thread-safe.
-	void unbindImage(U32 idx)
+	void unbindUniformTexelBuffer(U32 idx)
 	{
-		unbindCommon(idx, m_freeImgIndices, m_freeImgIndexCount);
+		unbindCommon(idx, m_freeTexelBufferIndices, m_freeTexelBufferIndexCount);
 	}
 
 	DescriptorSet getDescriptorSet() const
@@ -64,18 +66,115 @@ private:
 	Mutex m_mtx;
 
 	DynamicArray<U16> m_freeTexIndices;
-	DynamicArray<U16> m_freeImgIndices;
+	DynamicArray<U16> m_freeTexelBufferIndices;
 
-	U16 m_freeTexIndexCount ANKI_DEBUG_CODE(= MAX_U16);
-	U16 m_freeImgIndexCount ANKI_DEBUG_CODE(= MAX_U16);
+	U16 m_freeTexIndexCount = MAX_U16;
+	U16 m_freeTexelBufferIndexCount = MAX_U16;
 
 	void unbindCommon(U32 idx, DynamicArray<U16>& freeIndices, U16& freeIndexCount);
 };
 
+/// Descriptor set internal class.
+class DS : public IntrusiveListEnabled<DS>
+{
+public:
+	VkDescriptorSet m_handle = {};
+	U64 m_lastFrameUsed = MAX_U64;
+	U64 m_hash;
+};
+
+/// Per thread allocator.
+class DescriptorSetFactory::DSAllocator
+{
+public:
+	DSAllocator(const DSAllocator&) = delete; // Non-copyable
+
+	DSAllocator& operator=(const DSAllocator&) = delete; // Non-copyable
+
+	DSAllocator(const DSLayoutCacheEntry* layout)
+		: m_layoutEntry(layout)
+	{
+		ANKI_ASSERT(m_layoutEntry);
+	}
+
+	~DSAllocator();
+
+	Error init();
+	Error createNewPool();
+
+	Error getOrCreateSet(U64 hash, const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
+						 StackAllocator<U8>& tmpAlloc, const DS*& out)
+	{
+		out = tryFindSet(hash);
+		if(out == nullptr)
+		{
+			ANKI_CHECK(newSet(hash, bindings, tmpAlloc, out));
+		}
+
+		return Error::NONE;
+	}
+
+private:
+	const DSLayoutCacheEntry* m_layoutEntry; ///< Know your father.
+
+	DynamicArray<VkDescriptorPool> m_pools;
+	U32 m_lastPoolDSCount = 0;
+	U32 m_lastPoolFreeDSCount = 0;
+
+	IntrusiveList<DS> m_list; ///< At the left of the list are the least used sets.
+	HashMap<U64, DS*> m_hashmap;
+
+	[[nodiscard]] const DS* tryFindSet(U64 hash);
+	Error newSet(U64 hash, const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
+				 StackAllocator<U8>& tmpAlloc, const DS*& out);
+	void writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings, const DS& set,
+				  StackAllocator<U8>& tmpAlloc);
+};
+
+class alignas(ANKI_CACHE_LINE_SIZE) DescriptorSetFactory::ThreadLocal
+{
+public:
+	DynamicArray<DSAllocator*> m_allocators;
+};
+
+/// Cache entry. It's built around a specific descriptor set layout.
+class DSLayoutCacheEntry
+{
+public:
+	DescriptorSetFactory* m_factory;
+
+	U64 m_hash = 0; ///< Layout hash.
+	VkDescriptorSetLayout m_layoutHandle = {};
+	BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U32> m_activeBindings = {false};
+	Array<U32, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindingArraySize = {};
+	Array<DescriptorType, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindingType = {};
+	U32 m_minBinding = MAX_U32;
+	U32 m_maxBinding = 0;
+	U32 m_index = 0; ///< Index in DescriptorSetFactory::m_caches
+
+	// Cache the create info
+	Array<VkDescriptorPoolSize, U(DescriptorType::COUNT)> m_poolSizesCreateInf = {};
+	VkDescriptorPoolCreateInfo m_poolCreateInf = {};
+
+	DSLayoutCacheEntry(DescriptorSetFactory* factory, U32 index)
+		: m_factory(factory)
+		, m_index(index)
+	{
+	}
+
+	~DSLayoutCacheEntry();
+
+	Error init(const DescriptorBinding* bindings, U32 bindingCount, U64 hash);
+
+	/// @note Thread-safe.
+	Error getOrCreateDSAllocator(DescriptorSetFactory::DSAllocator*& alloc);
+};
+
 DescriptorSetFactory::BindlessDescriptorSet::~BindlessDescriptorSet()
 {
 	ANKI_ASSERT(m_freeTexIndexCount == m_freeTexIndices.getSize() && "Forgot to unbind some textures");
-	ANKI_ASSERT(m_freeImgIndexCount == m_freeImgIndices.getSize() && "Forgot to unbind some images");
+	ANKI_ASSERT(m_freeTexelBufferIndexCount == m_freeTexelBufferIndices.getSize()
+				&& "Forgot to unbind some texel buffers");
 
 	if(m_pool)
 	{
@@ -90,12 +189,12 @@ DescriptorSetFactory::BindlessDescriptorSet::~BindlessDescriptorSet()
 		m_layout = VK_NULL_HANDLE;
 	}
 
-	m_freeImgIndices.destroy(m_alloc);
 	m_freeTexIndices.destroy(m_alloc);
+	m_freeTexelBufferIndices.destroy(m_alloc);
 }
 
 Error DescriptorSetFactory::BindlessDescriptorSet::init(const GrAllocator<U8>& alloc, VkDevice dev,
-														U32 bindlessTextureCount, U32 bindlessImageCount)
+														U32 bindlessTextureCount, U32 bindlessTextureBuffers)
 {
 	ANKI_ASSERT(dev);
 	m_alloc = alloc;
@@ -110,8 +209,8 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(const GrAllocator<U8>& a
 		bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
 		bindings[1].binding = 1;
 		bindings[1].stageFlags = VK_SHADER_STAGE_ALL;
-		bindings[1].descriptorCount = bindlessImageCount;
-		bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+		bindings[1].descriptorCount = bindlessTextureBuffers;
+		bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
 
 		Array<VkDescriptorBindingFlagsEXT, 2> bindingFlags = {};
 		bindingFlags[0] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT
@@ -139,8 +238,8 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(const GrAllocator<U8>& a
 		Array<VkDescriptorPoolSize, 2> sizes = {};
 		sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
 		sizes[0].descriptorCount = bindlessTextureCount;
-		sizes[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
-		sizes[1].descriptorCount = bindlessImageCount;
+		sizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+		sizes[1].descriptorCount = bindlessTextureBuffers;
 
 		VkDescriptorPoolCreateInfo ci = {};
 		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
@@ -173,12 +272,12 @@ Error DescriptorSetFactory::BindlessDescriptorSet::init(const GrAllocator<U8>& a
 			m_freeTexIndices[i] = U16(m_freeTexIndices.getSize() - i - 1);
 		}
 
-		m_freeImgIndices.create(m_alloc, bindlessImageCount);
-		m_freeImgIndexCount = U16(m_freeImgIndices.getSize());
+		m_freeTexelBufferIndices.create(m_alloc, bindlessTextureBuffers);
+		m_freeTexelBufferIndexCount = U16(m_freeTexelBufferIndices.getSize());
 
-		for(U32 i = 0; i < m_freeImgIndices.getSize(); ++i)
+		for(U32 i = 0; i < m_freeTexelBufferIndices.getSize(); ++i)
 		{
-			m_freeImgIndices[i] = U16(m_freeImgIndices.getSize() - i - 1);
+			m_freeTexelBufferIndices[i] = U16(m_freeTexelBufferIndices.getSize() - i - 1);
 		}
 	}
 
@@ -218,31 +317,27 @@ U32 DescriptorSetFactory::BindlessDescriptorSet::bindTexture(const VkImageView v
 	return idx;
 }
 
-U32 DescriptorSetFactory::BindlessDescriptorSet::bindImage(const VkImageView view)
+U32 DescriptorSetFactory::BindlessDescriptorSet::bindUniformTexelBuffer(VkBufferView view)
 {
 	ANKI_ASSERT(view);
 	LockGuard<Mutex> lock(m_mtx);
-	ANKI_ASSERT(m_freeImgIndexCount > 0 && "Out of indices");
+	ANKI_ASSERT(m_freeTexelBufferIndexCount > 0 && "Out of indices");
 
-	// Get the index
-	--m_freeImgIndexCount;
-	const U32 idx = m_freeImgIndices[m_freeImgIndexCount];
-	ANKI_ASSERT(idx < m_freeImgIndices.getSize());
+	// Pop the index
+	--m_freeTexelBufferIndexCount;
+	const U16 idx = m_freeTexelBufferIndices[m_freeTexelBufferIndexCount];
+	ANKI_ASSERT(idx < m_freeTexelBufferIndices.getSize());
 
 	// Update the set
-	VkDescriptorImageInfo imageInf = {};
-	imageInf.imageView = view;
-	imageInf.imageLayout = VK_IMAGE_LAYOUT_GENERAL; // Storage images are always in general.
-
 	VkWriteDescriptorSet write = {};
 	write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 	write.pNext = nullptr;
 	write.dstSet = m_dset;
 	write.dstBinding = 1;
 	write.descriptorCount = 1;
-	write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+	write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
 	write.dstArrayElement = idx;
-	write.pImageInfo = &imageInf;
+	write.pTexelBufferView = &view;
 
 	vkUpdateDescriptorSets(m_dev, 1, &write, 0, nullptr);
 
@@ -270,101 +365,7 @@ void DescriptorSetFactory::BindlessDescriptorSet::unbindCommon(U32 idx, DynamicA
 	}
 }
 
-/// Descriptor set internal class.
-class DS : public IntrusiveListEnabled<DS>
-{
-public:
-	VkDescriptorSet m_handle = {};
-	U64 m_lastFrameUsed = MAX_U64;
-	U64 m_hash;
-};
-
-/// Per thread allocator.
-class alignas(ANKI_CACHE_LINE_SIZE) DSThreadAllocator
-{
-public:
-	DSThreadAllocator(const DSThreadAllocator&) = delete; // Non-copyable
-
-	DSThreadAllocator& operator=(const DSThreadAllocator&) = delete; // Non-copyable
-
-	const DSLayoutCacheEntry* m_layoutEntry; ///< Know your father.
-
-	ThreadId m_tid;
-	DynamicArray<VkDescriptorPool> m_pools;
-	U32 m_lastPoolDSCount = 0;
-	U32 m_lastPoolFreeDSCount = 0;
-
-	IntrusiveList<DS> m_list; ///< At the left of the list are the least used sets.
-	HashMap<U64, DS*> m_hashmap;
-
-	DSThreadAllocator(const DSLayoutCacheEntry* layout, ThreadId tid)
-		: m_layoutEntry(layout)
-		, m_tid(tid)
-	{
-		ANKI_ASSERT(m_layoutEntry);
-	}
-
-	~DSThreadAllocator();
-
-	ANKI_USE_RESULT Error init();
-	ANKI_USE_RESULT Error createNewPool();
-
-	ANKI_USE_RESULT Error getOrCreateSet(U64 hash,
-										 const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
-										 StackAllocator<U8>& tmpAlloc, const DS*& out)
-	{
-		out = tryFindSet(hash);
-		if(out == nullptr)
-		{
-			ANKI_CHECK(newSet(hash, bindings, tmpAlloc, out));
-		}
-
-		return Error::NONE;
-	}
-
-private:
-	ANKI_USE_RESULT const DS* tryFindSet(U64 hash);
-	ANKI_USE_RESULT Error newSet(U64 hash, const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
-								 StackAllocator<U8>& tmpAlloc, const DS*& out);
-	void writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings, const DS& set,
-				  StackAllocator<U8>& tmpAlloc);
-};
-
-/// Cache entry. It's built around a specific descriptor set layout.
-class DSLayoutCacheEntry
-{
-public:
-	DescriptorSetFactory* m_factory;
-
-	U64 m_hash = 0; ///< Layout hash.
-	VkDescriptorSetLayout m_layoutHandle = {};
-	BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U32> m_activeBindings = {false};
-	Array<U32, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindingArraySize = {};
-	Array<DescriptorType, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindingType = {};
-	U32 m_minBinding = MAX_U32;
-	U32 m_maxBinding = 0;
-
-	// Cache the create info
-	Array<VkDescriptorPoolSize, U(DescriptorType::COUNT)> m_poolSizesCreateInf = {};
-	VkDescriptorPoolCreateInfo m_poolCreateInf = {};
-
-	DynamicArray<DSThreadAllocator*> m_threadAllocs;
-	RWMutex m_threadAllocsMtx;
-
-	DSLayoutCacheEntry(DescriptorSetFactory* factory)
-		: m_factory(factory)
-	{
-	}
-
-	~DSLayoutCacheEntry();
-
-	ANKI_USE_RESULT Error init(const DescriptorBinding* bindings, U32 bindingCount, U64 hash);
-
-	/// @note Thread-safe.
-	ANKI_USE_RESULT Error getOrCreateThreadAllocator(ThreadId tid, DSThreadAllocator*& alloc);
-};
-
-DSThreadAllocator::~DSThreadAllocator()
+DescriptorSetFactory::DSAllocator::~DSAllocator()
 {
 	auto alloc = m_layoutEntry->m_factory->m_alloc;
 
@@ -385,13 +386,13 @@ DSThreadAllocator::~DSThreadAllocator()
 	m_hashmap.destroy(alloc);
 }
 
-Error DSThreadAllocator::init()
+Error DescriptorSetFactory::DSAllocator::init()
 {
 	ANKI_CHECK(createNewPool());
 	return Error::NONE;
 }
 
-Error DSThreadAllocator::createNewPool()
+Error DescriptorSetFactory::DSAllocator::createNewPool()
 {
 	m_lastPoolDSCount = (m_lastPoolDSCount != 0) ? U32(F32(m_lastPoolDSCount) * DESCRIPTOR_POOL_SIZE_SCALE)
 												 : DESCRIPTOR_POOL_INITIAL_SIZE;
@@ -424,7 +425,7 @@ Error DSThreadAllocator::createNewPool()
 	return Error::NONE;
 }
 
-const DS* DSThreadAllocator::tryFindSet(U64 hash)
+const DS* DescriptorSetFactory::DSAllocator::tryFindSet(U64 hash)
 {
 	ANKI_ASSERT(hash > 0);
 
@@ -446,8 +447,9 @@ const DS* DSThreadAllocator::tryFindSet(U64 hash)
 	}
 }
 
-Error DSThreadAllocator::newSet(U64 hash, const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
-								StackAllocator<U8>& tmpAlloc, const DS*& out_)
+Error DescriptorSetFactory::DSAllocator::newSet(
+	U64 hash, const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings, StackAllocator<U8>& tmpAlloc,
+	const DS*& out_)
 {
 	DS* out = nullptr;
 
@@ -495,8 +497,7 @@ Error DSThreadAllocator::newSet(U64 hash, const Array<AnyBindingExtended, MAX_BI
 		ci.descriptorSetCount = 1;
 
 		VkDescriptorSet handle;
-		VkResult rez = vkAllocateDescriptorSets(m_layoutEntry->m_factory->m_dev, &ci, &handle);
-		(void)rez;
+		[[maybe_unused]] VkResult rez = vkAllocateDescriptorSets(m_layoutEntry->m_factory->m_dev, &ci, &handle);
 		ANKI_ASSERT(rez == VK_SUCCESS && "That allocation can't fail");
 		ANKI_TRACE_INC_COUNTER(VK_DESCRIPTOR_SET_CREATE, 1);
 
@@ -518,13 +519,15 @@ Error DSThreadAllocator::newSet(U64 hash, const Array<AnyBindingExtended, MAX_BI
 	return Error::NONE;
 }
 
-void DSThreadAllocator::writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings,
-								 const DS& set, StackAllocator<U8>& tmpAlloc)
+void DescriptorSetFactory::DSAllocator::writeSet(
+	const Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET>& bindings, const DS& set,
+	StackAllocator<U8>& tmpAlloc)
 {
 	DynamicArrayAuto<VkWriteDescriptorSet> writeInfos(tmpAlloc);
 	DynamicArrayAuto<VkDescriptorImageInfo> texInfos(tmpAlloc);
 	DynamicArrayAuto<VkDescriptorBufferInfo> buffInfos(tmpAlloc);
 	DynamicArrayAuto<VkWriteDescriptorSetAccelerationStructureKHR> asInfos(tmpAlloc);
+	DynamicArrayAuto<VkBufferView> bufferViews(tmpAlloc);
 
 	// First pass: Populate the VkDescriptorImageInfo and VkDescriptorBufferInfo
 	for(U bindingIdx = m_layoutEntry->m_minBinding; bindingIdx <= m_layoutEntry->m_maxBinding; ++bindingIdx)
@@ -572,6 +575,13 @@ void DSThreadAllocator::writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PE
 					info.range = (b.m_buff.m_range == MAX_PTR_SIZE) ? VK_WHOLE_SIZE : b.m_buff.m_range;
 					break;
 				}
+				case DescriptorType::READ_TEXTURE_BUFFER:
+				case DescriptorType::READ_WRITE_TEXTURE_BUFFER:
+				{
+					VkBufferView& view = *bufferViews.emplaceBack();
+					view = b.m_textureBuffer.m_buffView;
+					break;
+				}
 				case DescriptorType::IMAGE:
 				{
 					VkDescriptorImageInfo& info = *texInfos.emplaceBack();
@@ -600,8 +610,9 @@ void DSThreadAllocator::writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PE
 	U32 texCounter = 0;
 	U32 buffCounter = 0;
 	U32 asCounter = 0;
+	U32 buffViewsCounter = 0;
 
-	VkWriteDescriptorSet writeTemplate{};
+	VkWriteDescriptorSet writeTemplate = {};
 	writeTemplate.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 	writeTemplate.pNext = nullptr;
 	writeTemplate.dstSet = set.m_handle;
@@ -633,6 +644,10 @@ void DSThreadAllocator::writeSet(const Array<AnyBindingExtended, MAX_BINDINGS_PE
 				case DescriptorType::STORAGE_BUFFER:
 					writeInfo.pBufferInfo = &buffInfos[buffCounter++];
 					break;
+				case DescriptorType::READ_TEXTURE_BUFFER:
+				case DescriptorType::READ_WRITE_TEXTURE_BUFFER:
+					writeInfo.pTexelBufferView = &bufferViews[buffViewsCounter++];
+					break;
 				case DescriptorType::ACCELERATION_STRUCTURE:
 					writeInfo.pNext = &asInfos[asCounter++];
 					break;
@@ -652,13 +667,6 @@ DSLayoutCacheEntry::~DSLayoutCacheEntry()
 {
 	auto alloc = m_factory->m_alloc;
 
-	for(DSThreadAllocator* a : m_threadAllocs)
-	{
-		alloc.deleteInstance(a);
-	}
-
-	m_threadAllocs.destroy(alloc);
-
 	if(m_layoutHandle)
 	{
 		vkDestroyDescriptorSetLayout(m_factory->m_dev, m_layoutHandle, nullptr);
@@ -740,61 +748,92 @@ Error DSLayoutCacheEntry::init(const DescriptorBinding* bindings, U32 bindingCou
 	return Error::NONE;
 }
 
-Error DSLayoutCacheEntry::getOrCreateThreadAllocator(ThreadId tid, DSThreadAllocator*& alloc)
+Error DSLayoutCacheEntry::getOrCreateDSAllocator(DescriptorSetFactory::DSAllocator*& alloc)
 {
 	alloc = nullptr;
 
-	class Comp
+	// Get or create thread-local
+	DescriptorSetFactory::ThreadLocal* threadLocal = DescriptorSetFactory::m_threadLocal;
+	if(ANKI_UNLIKELY(threadLocal == nullptr))
 	{
-	public:
-		Bool operator()(const DSThreadAllocator* a, ThreadId tid) const
-		{
-			return a->m_tid < tid;
-		}
+		threadLocal = m_factory->m_alloc.newInstance<DescriptorSetFactory::ThreadLocal>();
+		DescriptorSetFactory::m_threadLocal = threadLocal;
 
-		Bool operator()(ThreadId tid, const DSThreadAllocator* a) const
-		{
-			return tid < a->m_tid;
-		}
-	};
+		LockGuard<Mutex> lock(m_factory->m_allThreadLocalsMtx);
+		m_factory->m_allThreadLocals.emplaceBack(m_factory->m_alloc, threadLocal);
+	}
 
-	// Find using binary search
+	// Get or create the allocator
+	if(ANKI_UNLIKELY(m_index >= threadLocal->m_allocators.getSize()))
 	{
-		RLockGuard<RWMutex> lock(m_threadAllocsMtx);
-		auto it = binarySearch(m_threadAllocs.getBegin(), m_threadAllocs.getEnd(), tid, Comp());
-		alloc = (it != m_threadAllocs.getEnd()) ? *it : nullptr;
+		threadLocal->m_allocators.resize(m_factory->m_alloc, m_index + 1, nullptr);
+		alloc = m_factory->m_alloc.newInstance<DescriptorSetFactory::DSAllocator>(this);
+		ANKI_CHECK(alloc->init());
+		threadLocal->m_allocators[m_index] = alloc;
 	}
-
-	if(alloc == nullptr)
+	else if(ANKI_UNLIKELY(threadLocal->m_allocators[m_index] == nullptr))
 	{
-		// Need to create one
+		alloc = m_factory->m_alloc.newInstance<DescriptorSetFactory::DSAllocator>(this);
+		ANKI_CHECK(alloc->init());
+		threadLocal->m_allocators[m_index] = alloc;
+	}
+	else
+	{
+		alloc = threadLocal->m_allocators[m_index];
+	}
 
-		WLockGuard<RWMutex> lock(m_threadAllocsMtx);
+	ANKI_ASSERT(alloc);
+	return Error::NONE;
+}
 
-		// Search again
-		auto it = binarySearch(m_threadAllocs.getBegin(), m_threadAllocs.getEnd(), tid, Comp());
-		alloc = (it != m_threadAllocs.getEnd()) ? *it : nullptr;
+AnyBinding& DescriptorSetState::getBindingToPopulate(U32 bindingIdx, U32 arrayIdx)
+{
+	ANKI_ASSERT(bindingIdx < MAX_BINDINGS_PER_DESCRIPTOR_SET);
 
-		// Create
-		if(alloc == nullptr)
-		{
-			alloc = m_factory->m_alloc.newInstance<DSThreadAllocator>(this, tid);
-			ANKI_CHECK(alloc->init());
+	AnyBindingExtended& extended = m_bindings[bindingIdx];
+	AnyBinding* out;
+	const Bool bindingIsSet = m_bindingSet.get(bindingIdx);
+	m_bindingSet.set(bindingIdx);
+	extended.m_arraySize = (!bindingIsSet) ? 0 : extended.m_arraySize;
 
-			m_threadAllocs.resize(m_factory->m_alloc, m_threadAllocs.getSize() + 1);
-			m_threadAllocs[m_threadAllocs.getSize() - 1] = alloc;
+	if(ANKI_LIKELY(arrayIdx == 0 && extended.m_arraySize <= 1))
+	{
+		// Array idx is zero, most common case
+		out = &extended.m_single;
+		extended.m_arraySize = 1;
+	}
+	else if(arrayIdx < extended.m_arraySize)
+	{
+		// It's (or was) an array and there enough space in thar array
+		out = &extended.m_array[arrayIdx];
+	}
+	else
+	{
+		// Need to grow
+		const U32 newSize = max(extended.m_arraySize * 2, arrayIdx + 1);
+		AnyBinding* newArr = m_alloc.newArray<AnyBinding>(newSize);
 
-			// Sort for fast find
-			std::sort(m_threadAllocs.getBegin(), m_threadAllocs.getEnd(),
-					  [](const DSThreadAllocator* a, const DSThreadAllocator* b) {
-						  return a->m_tid < b->m_tid;
-					  });
+		if(extended.m_arraySize == 1)
+		{
+			newArr[0] = extended.m_single;
+		}
+		else if(extended.m_arraySize > 1)
+		{
+			// Copy old to new.
+			memcpy(newArr, extended.m_array, sizeof(AnyBinding) * extended.m_arraySize);
 		}
+
+		// Zero the rest
+		memset(newArr + extended.m_arraySize, 0, sizeof(AnyBinding) * (newSize - extended.m_arraySize));
+		extended.m_arraySize = newSize;
+		extended.m_array = newArr;
+
+		// Return
+		out = &extended.m_array[arrayIdx];
 	}
 
-	ANKI_ASSERT(alloc);
-	ANKI_ASSERT(alloc->m_tid == tid);
-	return Error::NONE;
+	ANKI_ASSERT(out);
+	return *out;
 }
 
 void DescriptorSetState::flush(U64& hash, Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets,
@@ -885,6 +924,16 @@ void DescriptorSetState::flush(U64& hash, Array<PtrSize, MAX_BINDINGS_PER_DESCRI
 						dynamicOffsets[dynamicOffsetCount++] = anyBinding.m_buff.m_offset;
 						dynamicOffsetsDirty = dynamicOffsetsDirty || crntBindingDirty;
 						break;
+					case DescriptorType::READ_TEXTURE_BUFFER:
+						ANKI_ASSERT(anyBinding.m_type == DescriptorType::READ_TEXTURE_BUFFER
+									&& "Have bound the wrong type");
+						toHash[toHashCount++] = anyBinding.m_uuids[1];
+						break;
+					case DescriptorType::READ_WRITE_TEXTURE_BUFFER:
+						ANKI_ASSERT(anyBinding.m_type == DescriptorType::READ_WRITE_TEXTURE_BUFFER
+									&& "Have bound the wrong type");
+						toHash[toHashCount++] = anyBinding.m_uuids[1];
+						break;
 					case DescriptorType::IMAGE:
 						ANKI_ASSERT(anyBinding.m_type == DescriptorType::IMAGE && "Have bound the wrong type");
 						break;
@@ -935,21 +984,34 @@ DescriptorSetFactory::~DescriptorSetFactory()
 }
 
 Error DescriptorSetFactory::init(const GrAllocator<U8>& alloc, VkDevice dev, U32 bindlessTextureCount,
-								 U32 bindlessImageCount)
+								 U32 bindlessTextureBuffers)
 {
 	m_alloc = alloc;
 	m_dev = dev;
 
 	m_bindless = m_alloc.newInstance<BindlessDescriptorSet>();
-	ANKI_CHECK(m_bindless->init(alloc, dev, bindlessTextureCount, bindlessImageCount));
+	ANKI_CHECK(m_bindless->init(alloc, dev, bindlessTextureCount, bindlessTextureBuffers));
 	m_bindlessTextureCount = bindlessTextureCount;
-	m_bindlessImageCount = bindlessImageCount;
+	m_bindlessUniformTexelBufferCount = bindlessTextureBuffers;
 
 	return Error::NONE;
 }
 
 void DescriptorSetFactory::destroy()
 {
+	for(ThreadLocal* threadLocal : m_allThreadLocals)
+	{
+		for(DSAllocator* alloc : threadLocal->m_allocators)
+		{
+			m_alloc.deleteInstance(alloc);
+		}
+
+		threadLocal->m_allocators.destroy(m_alloc);
+		m_alloc.deleteInstance(threadLocal);
+	}
+
+	m_allThreadLocals.destroy(m_alloc);
+
 	for(DSLayoutCacheEntry* l : m_caches)
 	{
 		m_alloc.deleteInstance(l);
@@ -999,8 +1061,8 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 			{
 				// All good
 			}
-			else if(binding.m_binding == 1 && binding.m_type == DescriptorType::IMAGE
-					&& binding.m_arraySize == m_bindlessImageCount)
+			else if(binding.m_binding == 1 && binding.m_type == DescriptorType::READ_TEXTURE_BUFFER
+					&& binding.m_arraySize == m_bindlessUniformTexelBufferCount)
 			{
 				// All good
 			}
@@ -1035,11 +1097,10 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 
 		if(cache == nullptr)
 		{
-			cache = m_alloc.newInstance<DSLayoutCacheEntry>(this);
+			cache = m_alloc.newInstance<DSLayoutCacheEntry>(this, m_caches.getSize());
 			ANKI_CHECK(cache->init(bindings.getBegin(), bindingCount, hash));
 
-			m_caches.resize(m_alloc, m_caches.getSize() + 1);
-			m_caches[m_caches.getSize() - 1] = cache;
+			m_caches.emplaceBack(m_alloc, cache);
 		}
 
 		// Set the layout
@@ -1050,7 +1111,7 @@ Error DescriptorSetFactory::newDescriptorSetLayout(const DescriptorSetLayoutInit
 	return Error::NONE;
 }
 
-Error DescriptorSetFactory::newDescriptorSet(ThreadId tid, StackAllocator<U8>& tmpAlloc, DescriptorSetState& state,
+Error DescriptorSetFactory::newDescriptorSet(StackAllocator<U8>& tmpAlloc, DescriptorSetState& state,
 											 DescriptorSet& set, Bool& dirty,
 											 Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets,
 											 U32& dynamicOffsetCount)
@@ -1076,8 +1137,8 @@ Error DescriptorSetFactory::newDescriptorSet(ThreadId tid, StackAllocator<U8>& t
 			DSLayoutCacheEntry& entry = *layout.m_entry;
 
 			// Get thread allocator
-			DSThreadAllocator* alloc;
-			ANKI_CHECK(entry.getOrCreateThreadAllocator(tid, alloc));
+			DSAllocator* alloc;
+			ANKI_CHECK(entry.getOrCreateDSAllocator(alloc));
 
 			// Finally, allocate
 			const DS* s;
@@ -1100,10 +1161,10 @@ U32 DescriptorSetFactory::bindBindlessTexture(const VkImageView view, const VkIm
 	return m_bindless->bindTexture(view, layout);
 }
 
-U32 DescriptorSetFactory::bindBindlessImage(const VkImageView view)
+U32 DescriptorSetFactory::bindBindlessUniformTexelBuffer(const VkBufferView view)
 {
 	ANKI_ASSERT(m_bindless);
-	return m_bindless->bindImage(view);
+	return m_bindless->bindUniformTexelBuffer(view);
 }
 
 void DescriptorSetFactory::unbindBindlessTexture(U32 idx)
@@ -1112,10 +1173,10 @@ void DescriptorSetFactory::unbindBindlessTexture(U32 idx)
 	m_bindless->unbindTexture(idx);
 }
 
-void DescriptorSetFactory::unbindBindlessImage(U32 idx)
+void DescriptorSetFactory::unbindBindlessUniformTexelBuffer(U32 idx)
 {
 	ANKI_ASSERT(m_bindless);
-	m_bindless->unbindImage(idx);
+	m_bindless->unbindUniformTexelBuffer(idx);
 }
 
 } // end namespace anki

+ 38 - 62
AnKi/Gr/Vulkan/DescriptorSet.h

@@ -17,7 +17,6 @@
 namespace anki {
 
 // Forward
-class DSThreadAllocator;
 class DSLayoutCacheEntry;
 
 /// @addtogroup vulkan
@@ -112,6 +111,12 @@ public:
 	VkAccelerationStructureKHR m_accelerationStructureHandle;
 };
 
+class TextureBufferBinding
+{
+public:
+	VkBufferView m_buffView;
+};
+
 class AnyBinding
 {
 public:
@@ -125,6 +130,7 @@ public:
 		BufferBinding m_buff;
 		ImageBinding m_image;
 		AsBinding m_accelerationStructure;
+		TextureBufferBinding m_textureBuffer;
 	};
 
 	DescriptorType m_type;
@@ -266,6 +272,22 @@ public:
 		unbindBindlessDSet();
 	}
 
+	void bindReadOnlyTextureBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range,
+								   Format fmt)
+	{
+		const VkBufferView view = static_cast<const BufferImpl*>(buff)->getOrCreateBufferView(fmt, offset, range);
+		AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
+		b = {};
+		b.m_type = DescriptorType::READ_TEXTURE_BUFFER;
+		b.m_uuids[0] = ptrToNumber(view);
+		b.m_uuids[1] = buff->getUuid();
+
+		b.m_textureBuffer.m_buffView = view;
+
+		m_dirtyBindings.set(binding);
+		unbindBindlessDSet();
+	}
+
 	void bindImage(U32 binding, U32 arrayIdx, const TextureView* texView)
 	{
 		ANKI_ASSERT(texView);
@@ -327,80 +349,28 @@ private:
 		m_bindlessDSetBound = false;
 	}
 
-	AnyBinding& getBindingToPopulate(U32 bindingIdx, U32 arrayIdx)
-	{
-		ANKI_ASSERT(bindingIdx < MAX_BINDINGS_PER_DESCRIPTOR_SET);
-
-		AnyBindingExtended& extended = m_bindings[bindingIdx];
-		AnyBinding* out;
-		const Bool bindingIsSet = m_bindingSet.get(bindingIdx);
-		m_bindingSet.set(bindingIdx);
-		extended.m_arraySize = (!bindingIsSet) ? 0 : extended.m_arraySize;
-
-		if(ANKI_LIKELY(arrayIdx == 0 && extended.m_arraySize <= 1))
-		{
-			// Array idx is zero, most common case
-			out = &extended.m_single;
-			extended.m_arraySize = 1;
-		}
-		else if(arrayIdx < extended.m_arraySize)
-		{
-			// It's (or was) an array and there enough space in thar array
-			out = &extended.m_array[arrayIdx];
-		}
-		else
-		{
-			// Need to grow
-			const U32 newSize = max(extended.m_arraySize * 2, arrayIdx + 1);
-			AnyBinding* newArr = m_alloc.newArray<AnyBinding>(newSize);
-
-			if(extended.m_arraySize == 1)
-			{
-				newArr[0] = extended.m_single;
-			}
-			else if(extended.m_arraySize > 1)
-			{
-				// Copy old to new.
-				memcpy(newArr, extended.m_array, sizeof(AnyBinding) * extended.m_arraySize);
-			}
-
-			// Zero the rest
-			memset(newArr + extended.m_arraySize, 0, sizeof(AnyBinding) * (newSize - extended.m_arraySize));
-			extended.m_arraySize = newSize;
-			extended.m_array = newArr;
-
-			// Return
-			out = &extended.m_array[arrayIdx];
-		}
-
-		ANKI_ASSERT(out);
-		return *out;
-	}
+	AnyBinding& getBindingToPopulate(U32 bindingIdx, U32 arrayIdx);
 };
 
 /// Creates new descriptor set layouts and descriptor sets.
 class DescriptorSetFactory
 {
 	friend class DSLayoutCacheEntry;
-	friend class DSThreadAllocator;
 
 public:
 	DescriptorSetFactory() = default;
 	~DescriptorSetFactory();
 
-	ANKI_USE_RESULT Error init(const GrAllocator<U8>& alloc, VkDevice dev, U32 bindlessTextureCount,
-							   U32 bindlessImageCount);
+	Error init(const GrAllocator<U8>& alloc, VkDevice dev, U32 bindlessTextureCount, U32 bindlessTextureBuffers);
 
 	void destroy();
 
 	/// @note It's thread-safe.
-	ANKI_USE_RESULT Error newDescriptorSetLayout(const DescriptorSetLayoutInitInfo& init, DescriptorSetLayout& layout);
+	Error newDescriptorSetLayout(const DescriptorSetLayoutInitInfo& init, DescriptorSetLayout& layout);
 
 	/// @note It's thread-safe.
-	ANKI_USE_RESULT Error newDescriptorSet(ThreadId tid, StackAllocator<U8>& tmpAlloc, DescriptorSetState& state,
-										   DescriptorSet& set, Bool& dirty,
-										   Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets,
-										   U32& dynamicOffsetCount);
+	Error newDescriptorSet(StackAllocator<U8>& tmpAlloc, DescriptorSetState& state, DescriptorSet& set, Bool& dirty,
+						   Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets, U32& dynamicOffsetCount);
 
 	void endFrame()
 	{
@@ -411,18 +381,24 @@ public:
 	/// @note It's thread-safe.
 	U32 bindBindlessTexture(const VkImageView view, const VkImageLayout layout);
 
-	/// Bind a storage image.
+	/// Bind a uniform texel buffer.
 	/// @note It's thread-safe.
-	U32 bindBindlessImage(const VkImageView view);
+	U32 bindBindlessUniformTexelBuffer(const VkBufferView view);
 
 	/// @note It's thread-safe.
 	void unbindBindlessTexture(U32 idx);
 
 	/// @note It's thread-safe.
-	void unbindBindlessImage(U32 idx);
+	void unbindBindlessUniformTexelBuffer(U32 idx);
 
 private:
 	class BindlessDescriptorSet;
+	class DSAllocator;
+	class ThreadLocal;
+
+	static thread_local ThreadLocal* m_threadLocal;
+	DynamicArray<ThreadLocal*> m_allThreadLocals;
+	Mutex m_allThreadLocalsMtx;
 
 	GrAllocator<U8> m_alloc;
 	VkDevice m_dev = VK_NULL_HANDLE;
@@ -433,7 +409,7 @@ private:
 
 	BindlessDescriptorSet* m_bindless = nullptr;
 	U32 m_bindlessTextureCount = MAX_U32;
-	U32 m_bindlessImageCount = MAX_U32;
+	U32 m_bindlessUniformTexelBufferCount = MAX_U32;
 };
 /// @}
 

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

@@ -73,6 +73,12 @@ void FrameGarbageCollector::collectGarbage()
 		{
 			BufferGarbage* bufferGarbage = frame.m_bufferGarbage.popBack();
 
+			for(VkBufferView view : bufferGarbage->m_viewHandles)
+			{
+				vkDestroyBufferView(dev, view, nullptr);
+			}
+			bufferGarbage->m_viewHandles.destroy(alloc);
+
 			if(bufferGarbage->m_bufferHandle)
 			{
 				vkDestroyBuffer(dev, bufferGarbage->m_bufferHandle, nullptr);

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

@@ -31,6 +31,7 @@ class BufferGarbage : public IntrusiveListEnabled<BufferGarbage>
 {
 public:
 	VkBuffer m_bufferHandle = VK_NULL_HANDLE;
+	DynamicArray<VkBufferView> m_viewHandles;
 	GpuMemoryHandle m_memoryHandle;
 };
 

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

@@ -55,8 +55,7 @@ Error FramebufferImpl::init(const FramebufferInitInfo& init)
 	// Create a renderpass.
 	initRpassCreateInfo(init);
 	ANKI_VK_CHECK(vkCreateRenderPass2KHR(getDevice(), &m_rpassCi, nullptr, &m_compatibleRenderpassHandle));
-	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
-											  m_compatibleRenderpassHandle);
+	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_RENDER_PASS, m_compatibleRenderpassHandle);
 
 	// Create the FB
 	ANKI_CHECK(initFbs(init));
@@ -177,7 +176,7 @@ Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
 	ANKI_ASSERT(count == ci.attachmentCount);
 
 	ANKI_VK_CHECK(vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_fbHandle));
-	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, m_fbHandle);
+	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_FRAMEBUFFER, m_fbHandle);
 
 	return Error::NONE;
 }
@@ -375,7 +374,7 @@ VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX
 			}
 
 			ANKI_VK_CHECKF(vkCreateRenderPass2KHR(getDevice(), &ci, nullptr, &out));
-			getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, out);
+			getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_RENDER_PASS, out);
 
 			m_renderpassHandles.emplace(getAllocator(), hash, out);
 		}

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

@@ -30,7 +30,7 @@ public:
 
 	~FramebufferImpl();
 
-	ANKI_USE_RESULT Error init(const FramebufferInitInfo& init);
+	Error init(const FramebufferInitInfo& init);
 
 	/// Good for pipeline creation.
 	VkRenderPass getCompatibleRenderPass() const
@@ -144,7 +144,7 @@ private:
 	VkFragmentShadingRateAttachmentInfoKHR m_sriAttachmentInfo = {};
 
 	// Methods
-	ANKI_USE_RESULT Error initFbs(const FramebufferInitInfo& init);
+	Error initFbs(const FramebufferInitInfo& init);
 	void initRpassCreateInfo(const FramebufferInitInfo& init);
 	void initClearValues(const FramebufferInitInfo& init);
 	void setupAttachmentDescriptor(const FramebufferAttachmentInfo& att, VkAttachmentDescription2& desc,

+ 4 - 8
AnKi/Gr/Vulkan/GpuMemoryManager.cpp

@@ -161,8 +161,7 @@ void GpuMemoryManager::init(VkPhysicalDevice pdev, VkDevice dev, GrAllocator<U8>
 	}
 }
 
-void GpuMemoryManager::allocateMemory(U32 memTypeIdx, PtrSize size, U32 alignment, Bool linearResource,
-									  GpuMemoryHandle& handle)
+void GpuMemoryManager::allocateMemory(U32 memTypeIdx, PtrSize size, U32 alignment, GpuMemoryHandle& handle)
 {
 	ClassAllocator& calloc = m_callocs[memTypeIdx];
 
@@ -170,8 +169,7 @@ void GpuMemoryManager::allocateMemory(U32 memTypeIdx, PtrSize size, U32 alignmen
 
 	GpuMemoryManagerChunk* chunk;
 	PtrSize offset;
-	const Error err = calloc.allocate(size, alignment, chunk, offset);
-	(void)err;
+	[[maybe_unused]] const Error err = calloc.allocate(size, alignment, chunk, offset);
 
 	handle.m_memory = chunk->m_handle;
 	handle.m_offset = offset;
@@ -212,13 +210,11 @@ void GpuMemoryManager::freeMemory(GpuMemoryHandle& handle)
 	if(handle.isDedicated())
 	{
 		vkFreeMemory(m_dev, handle.m_memory, nullptr);
-		const PtrSize prevSize = m_dedicatedAllocatedMemory.fetchSub(handle.m_size);
+		[[maybe_unused]] const PtrSize prevSize = m_dedicatedAllocatedMemory.fetchSub(handle.m_size);
 		ANKI_ASSERT(prevSize >= handle.m_size);
-		(void)prevSize;
 
-		const U32 count = m_dedicatedAllocationCount.fetchSub(1);
+		[[maybe_unused]] const U32 count = m_dedicatedAllocationCount.fetchSub(1);
 		ANKI_ASSERT(count > 0);
-		(void)count;
 	}
 	else
 	{

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

@@ -135,7 +135,7 @@ public:
 	void destroy();
 
 	/// Allocate memory.
-	void allocateMemory(U32 memTypeIdx, PtrSize size, U32 alignment, Bool linearResource, GpuMemoryHandle& handle);
+	void allocateMemory(U32 memTypeIdx, PtrSize size, U32 alignment, GpuMemoryHandle& handle);
 
 	void allocateMemoryDedicated(U32 memTypeIdx, PtrSize size, VkImage image, GpuMemoryHandle& handle);
 
@@ -143,7 +143,7 @@ public:
 	void freeMemory(GpuMemoryHandle& handle);
 
 	/// Map memory.
-	ANKI_USE_RESULT void* getMappedAddress(GpuMemoryHandle& handle);
+	[[nodiscard]] void* getMappedAddress(GpuMemoryHandle& handle);
 
 	/// Find a suitable memory type.
 	U32 findMemoryType(U32 resourceMemTypeBits, VkMemoryPropertyFlags preferFlags,

+ 61 - 106
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -82,9 +82,9 @@ GrManagerImpl::~GrManagerImpl()
 		vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
 	}
 
-	if(m_debugCallback)
+	if(m_debugUtilsMessager)
 	{
-		vkDestroyDebugReportCallbackEXT(m_instance, m_debugCallback, nullptr);
+		vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugUtilsMessager, nullptr);
 	}
 
 	if(m_instance)
@@ -98,8 +98,6 @@ GrManagerImpl::~GrManagerImpl()
 		vkDestroyInstance(m_instance, pallocCbs);
 	}
 
-	m_vkHandleToName.destroy(getAllocator());
-
 #if ANKI_PLATFORM_MOBILE
 	m_alloc.deleteInstance(m_globalCreatePipelineMtx);
 #endif
@@ -124,7 +122,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	m_config = init.m_config;
 	ANKI_ASSERT(m_config);
 
-	ANKI_CHECK(initInstance(init));
+	ANKI_CHECK(initInstance());
 	ANKI_CHECK(initSurface(init));
 	ANKI_CHECK(initDevice(init));
 
@@ -197,7 +195,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_READONLY_TEXTURE_BUFFERS));
 	m_pplineLayoutFactory.init(getAllocator(), m_device);
 
 	m_frameGarbageCollector.init(this);
@@ -205,7 +204,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	return Error::NONE;
 }
 
-Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
+Error GrManagerImpl::initInstance()
 {
 	// Init VOLK
 	//
@@ -318,31 +317,33 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 
 		for(U32 i = 0; i < extCount; ++i)
 		{
+			const CString extensionName = instExtensionInf[i].extensionName;
+
 #if ANKI_WINDOWING_SYSTEM_HEADLESS
-			if(CString(instExtensionInf[i].extensionName) == VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME)
+			if(extensionName == VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::EXT_HEADLESS_SURFACE;
 				instExtensions[instExtensionCount++] = VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME;
 			}
 #elif ANKI_OS_LINUX
-			if(CString(instExtensionInf[i].extensionName) == VK_KHR_XCB_SURFACE_EXTENSION_NAME)
+			if(extensionName == VK_KHR_XCB_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_XCB_SURFACE;
 				instExtensions[instExtensionCount++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
 			}
-			else if(CString(instExtensionInf[i].extensionName) == VK_KHR_XLIB_SURFACE_EXTENSION_NAME)
+			else if(extensionName == VK_KHR_XLIB_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_XLIB_SURFACE;
 				instExtensions[instExtensionCount++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
 			}
 #elif ANKI_OS_WINDOWS
-			if(CString(instExtensionInf[i].extensionName) == VK_KHR_WIN32_SURFACE_EXTENSION_NAME)
+			if(extensionName == VK_KHR_WIN32_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_WIN32_SURFACE;
 				instExtensions[instExtensionCount++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
 			}
 #elif ANKI_OS_ANDROID
-			if(CString(instExtensionInf[i].extensionName) == VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)
+			if(extensionName == VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_ANDROID_SURFACE;
 				instExtensions[instExtensionCount++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
@@ -350,16 +351,16 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 #else
 #	error Not implemented
 #endif
-			else if(CString(instExtensionInf[i].extensionName) == VK_KHR_SURFACE_EXTENSION_NAME)
+			else if(extensionName == VK_KHR_SURFACE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_SURFACE;
 				instExtensions[instExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
 			}
-			else if(CString(instExtensionInf[i].extensionName) == VK_EXT_DEBUG_REPORT_EXTENSION_NAME
-					&& (m_config->getGrValidation() || m_config->getGrDebugPrintf()))
+			else if(extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME
+					&& (m_config->getGrDebugMarkers() || m_config->getGrValidation() || m_config->getGrDebugPrintf()))
 			{
-				m_extensions |= VulkanExtensions::EXT_DEBUG_REPORT;
-				instExtensions[instExtensionCount++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+				m_extensions |= VulkanExtensions::EXT_DEBUG_UTILS;
+				instExtensions[instExtensionCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
 			}
 		}
 
@@ -404,23 +405,20 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 	volkLoadInstance(m_instance);
 
 	// Set debug callbacks
-	//
-	if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_REPORT))
+	if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
 	{
-		VkDebugReportCallbackCreateInfoEXT ci = {};
-		ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
-		ci.pfnCallback = debugReportCallbackEXT;
-		ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT
-				   | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
-
-		if(m_config->getGrDebugPrintf())
-		{
-			ci.flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
-		}
-
-		ci.pUserData = this;
+		VkDebugUtilsMessengerCreateInfoEXT info = {};
+		info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+		info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
+							   | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+							   | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+		info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+						   | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
+						   | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+		info.pfnUserCallback = debugReportCallbackEXT;
+		info.pUserData = this;
 
-		vkCreateDebugReportCallbackEXT(m_instance, &ci, nullptr, &m_debugCallback);
+		vkCreateDebugUtilsMessengerEXT(m_instance, &info, nullptr, &m_debugUtilsMessager);
 	}
 
 	// Create the physical device
@@ -661,11 +659,6 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 				m_extensions |= VulkanExtensions::KHR_SWAPCHAIN;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_EXT_DEBUG_MARKER_EXTENSION_NAME && m_config->getGrDebugMarkers())
-			{
-				m_extensions |= VulkanExtensions::EXT_DEBUG_MARKER;
-				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
-			}
 			else if(extensionName == VK_AMD_SHADER_INFO_EXTENSION_NAME && m_config->getCoreDisplayStats())
 			{
 				m_extensions |= VulkanExtensions::AMD_SHADER_INFO;
@@ -1102,31 +1095,6 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 
 	ANKI_VK_CHECK(vkCreateDevice(m_physicalDevice, &ci, nullptr, &m_device));
 
-	// Get debug marker
-	if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_MARKER))
-	{
-		m_pfnDebugMarkerSetObjectNameEXT = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(
-			vkGetDeviceProcAddr(m_device, "vkDebugMarkerSetObjectNameEXT"));
-		if(!m_pfnDebugMarkerSetObjectNameEXT)
-		{
-			ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkDebugMarkerSetObjectNameEXT is not there");
-		}
-
-		m_pfnCmdDebugMarkerBeginEXT =
-			reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(vkGetDeviceProcAddr(m_device, "vkCmdDebugMarkerBeginEXT"));
-		if(!m_pfnCmdDebugMarkerBeginEXT)
-		{
-			ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkCmdDebugMarkerBeginEXT is not there");
-		}
-
-		m_pfnCmdDebugMarkerEndEXT =
-			reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(vkGetDeviceProcAddr(m_device, "vkCmdDebugMarkerEndEXT"));
-		if(!m_pfnCmdDebugMarkerEndEXT)
-		{
-			ANKI_VK_LOGW("VK_EXT_debug_marker is present but vkCmdDebugMarkerEndEXT is not there");
-		}
-	}
-
 	// Get VK_AMD_shader_info entry points
 	if(!!(m_extensions & VulkanExtensions::AMD_SHADER_INFO))
 	{
@@ -1480,69 +1448,56 @@ void GrManagerImpl::finish()
 	}
 }
 
-void GrManagerImpl::trySetVulkanHandleName(CString name, VkDebugReportObjectTypeEXT type, U64 handle) const
+void GrManagerImpl::trySetVulkanHandleName(CString name, VkObjectType type, U64 handle) const
 {
-	if(name && name.getLength())
+	if(name && name.getLength() && !!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
 	{
-		if(m_pfnDebugMarkerSetObjectNameEXT)
-		{
-			VkDebugMarkerObjectNameInfoEXT inf = {};
-			inf.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
-			inf.objectType = type;
-			inf.pObjectName = name.cstr();
-			inf.object = handle;
-
-			m_pfnDebugMarkerSetObjectNameEXT(m_device, &inf);
-		}
+		VkDebugUtilsObjectNameInfoEXT info = {};
+		info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+		info.objectHandle = handle;
+		info.objectType = type;
+		info.pObjectName = name.cstr();
 
-		LockGuard<SpinLock> lock(m_vkHandleToNameLock);
-		StringAuto newName(getAllocator());
-		newName.create(name);
-		m_vkHandleToName.emplace(getAllocator(), computeHash(&handle, sizeof(handle)), std::move(newName));
+		vkSetDebugUtilsObjectNameEXT(m_device, &info);
 	}
 }
 
-StringAuto GrManagerImpl::tryGetVulkanHandleName(U64 handle) const
+VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+											   [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+											   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+											   void* pUserData)
 {
-	StringAuto out(getAllocator());
-
-	LockGuard<SpinLock> lock(m_vkHandleToNameLock);
-
-	auto it = m_vkHandleToName.find(computeHash(&handle, sizeof(handle)));
-	CString objName;
-	if(it != m_vkHandleToName.getEnd())
+	// Get all names of affected objects
+	GrManagerImpl* self = static_cast<GrManagerImpl*>(pUserData);
+	StringAuto objectNames(self->m_alloc);
+	if(pCallbackData->objectCount)
 	{
-		objName = it->toCString();
+		for(U32 i = 0; i < pCallbackData->objectCount; ++i)
+		{
+			const Char* name = pCallbackData->pObjects[i].pObjectName;
+			objectNames.append((name) ? name : "?");
+			if(i < pCallbackData->objectCount - 1)
+			{
+				objectNames.append(", ");
+			}
+		}
 	}
 	else
 	{
-		objName = "Unnamed";
+		objectNames.create("N/A");
 	}
 
-	out.create(objName);
-
-	return out;
-}
-
-VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
-											   uint64_t object, size_t location, int32_t messageCode,
-											   const char* pLayerPrefix, const char* pMessage, void* pUserData)
-{
-	// Get the object name
-	GrManagerImpl* self = static_cast<GrManagerImpl*>(pUserData);
-	StringAuto name = self->tryGetVulkanHandleName(object);
-
-	if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+	if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
 	{
-		ANKI_VK_LOGE("%s (handle: %s)", pMessage, name.cstr());
+		ANKI_VK_LOGE("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
 	}
-	else if(flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT))
+	else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
 	{
-		ANKI_VK_LOGW("%s (handle: %s)", pMessage, name.cstr());
+		ANKI_VK_LOGW("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
 	}
 	else
 	{
-		ANKI_VK_LOGI("%s (handle: %s)", pMessage, name.cstr());
+		ANKI_VK_LOGI("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
 	}
 
 	return false;

+ 26 - 37
AnKi/Gr/Vulkan/GrManagerImpl.h

@@ -45,7 +45,7 @@ public:
 
 	~GrManagerImpl();
 
-	ANKI_USE_RESULT Error init(const GrManagerInitInfo& cfg);
+	Error init(const GrManagerInitInfo& cfg);
 
 	ConstWeakArray<U32> getQueueFamilies() const
 	{
@@ -181,41 +181,37 @@ public:
 
 	/// @name Debug report
 	/// @{
-	void beginMarker(VkCommandBuffer cmdb, CString name) const
+	void beginMarker(VkCommandBuffer cmdb, CString name, Vec3 color = Vec3(1.0f, 0.0f, 0.0f)) const
 	{
 		ANKI_ASSERT(cmdb);
-		if(m_pfnCmdDebugMarkerBeginEXT)
+		if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
 		{
-			VkDebugMarkerMarkerInfoEXT markerInfo = {};
-			markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
-			markerInfo.color[0] = 1.0f;
-			markerInfo.pMarkerName = (!name.isEmpty() && name.getLength() > 0) ? name.cstr() : "Unnamed";
-			m_pfnCmdDebugMarkerBeginEXT(cmdb, &markerInfo);
+			VkDebugUtilsLabelEXT label = {};
+			label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+			label.pLabelName = name.cstr();
+			label.color[0] = color[0];
+			label.color[1] = color[1];
+			label.color[2] = color[2];
+			label.color[3] = 1.0f;
+			vkCmdBeginDebugUtilsLabelEXT(cmdb, &label);
 		}
 	}
 
 	void endMarker(VkCommandBuffer cmdb) const
 	{
 		ANKI_ASSERT(cmdb);
-		if(m_pfnCmdDebugMarkerEndEXT)
+		if(!!(m_extensions & VulkanExtensions::EXT_DEBUG_UTILS))
 		{
-			m_pfnCmdDebugMarkerEndEXT(cmdb);
+			vkCmdEndDebugUtilsLabelEXT(cmdb);
 		}
 	}
 
-	void trySetVulkanHandleName(CString name, VkDebugReportObjectTypeEXT type, U64 handle) const;
+	void trySetVulkanHandleName(CString name, VkObjectType type, U64 handle) const;
 
-	void trySetVulkanHandleName(CString name, VkDebugReportObjectTypeEXT type, void* handle) const
+	void trySetVulkanHandleName(CString name, VkObjectType type, void* handle) const
 	{
 		trySetVulkanHandleName(name, type, U64(ptrToNumber(handle)));
 	}
-
-	StringAuto tryGetVulkanHandleName(U64 handle) const;
-
-	StringAuto tryGetVulkanHandleName(void* handle) const
-	{
-		return tryGetVulkanHandleName(U64(ptrToNumber(handle)));
-	}
 	/// @}
 
 	void printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash = 0) const;
@@ -248,7 +244,6 @@ private:
 #endif
 
 	VkInstance m_instance = VK_NULL_HANDLE;
-	VkDebugReportCallbackEXT m_debugCallback = VK_NULL_HANDLE;
 	VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
 	VulkanExtensions m_extensions = VulkanExtensions::NONE;
 	VkDevice m_device = VK_NULL_HANDLE;
@@ -272,9 +267,8 @@ private:
 	VkPhysicalDeviceShaderAtomicInt64FeaturesKHR m_atomicInt64Features = {};
 	VkPhysicalDeviceFragmentShadingRateFeaturesKHR m_fragmentShadingRateFeatures = {};
 
-	PFN_vkDebugMarkerSetObjectNameEXT m_pfnDebugMarkerSetObjectNameEXT = nullptr;
-	PFN_vkCmdDebugMarkerBeginEXT m_pfnCmdDebugMarkerBeginEXT = nullptr;
-	PFN_vkCmdDebugMarkerEndEXT m_pfnCmdDebugMarkerEndEXT = nullptr;
+	VkDebugUtilsMessengerEXT m_debugUtilsMessager = VK_NULL_HANDLE;
+
 	PFN_vkGetShaderInfoAMD m_pfnGetShaderInfoAMD = nullptr;
 	mutable File m_shaderStatsFile;
 	mutable SpinLock m_shaderStatsFileMtx;
@@ -331,21 +325,17 @@ private:
 
 	PipelineCache m_pplineCache;
 
-	mutable HashMap<U64, StringAuto> m_vkHandleToName;
-	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 initInstance(const GrManagerInitInfo& init);
-	ANKI_USE_RESULT Error initSurface(const GrManagerInitInfo& init);
-	ANKI_USE_RESULT Error initDevice(const GrManagerInitInfo& init);
-	ANKI_USE_RESULT Error initFramebuffers(const GrManagerInitInfo& init);
-	ANKI_USE_RESULT Error initMemory();
+	Error initInternal(const GrManagerInitInfo& init);
+	Error initInstance();
+	Error initSurface(const GrManagerInitInfo& init);
+	Error initDevice(const GrManagerInitInfo& init);
+	Error initMemory();
 
 #if ANKI_GR_MANAGER_DEBUG_MEMMORY
 	static void* allocateCallback(void* userData, size_t size, size_t alignment,
@@ -359,12 +349,11 @@ private:
 
 	void resetFrame(PerFrame& frame);
 
-	static VkBool32 debugReportCallbackEXT(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
-										   uint64_t object, size_t location, int32_t messageCode,
-										   const char* pLayerPrefix, const char* pMessage, void* pUserData);
+	static VkBool32 debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+										   VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+										   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData);
 
-	ANKI_USE_RESULT Error printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages,
-														  U64 hash) const;
+	Error printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const;
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Vulkan/OcclusionQueryImpl.h

@@ -28,7 +28,7 @@ public:
 	~OcclusionQueryImpl();
 
 	/// Create the query.
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	/// Get query result.
 	OcclusionQueryResult getResultInternal() const;

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

@@ -21,8 +21,7 @@ class PipelineCache
 public:
 	VkPipelineCache m_cacheHandle = VK_NULL_HANDLE;
 
-	ANKI_USE_RESULT Error init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, const ConfigSet& cfg,
-							   GrAllocator<U8> alloc);
+	Error init(VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, const ConfigSet& cfg, GrAllocator<U8> alloc);
 
 	void destroy(VkDevice dev, VkPhysicalDevice pdev, GrAllocator<U8> alloc);
 
@@ -30,7 +29,7 @@ private:
 	String m_dumpFilename;
 	PtrSize m_dumpSize = 0;
 
-	ANKI_USE_RESULT Error destroyInternal(VkDevice dev, VkPhysicalDevice pdev, GrAllocator<U8> alloc);
+	Error destroyInternal(VkDevice dev, VkPhysicalDevice pdev, GrAllocator<U8> alloc);
 };
 /// @}
 

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

@@ -44,8 +44,8 @@ public:
 	void destroy();
 
 	/// @note It's thread-safe.
-	ANKI_USE_RESULT Error newPipelineLayout(const WeakArray<DescriptorSetLayout>& dsetLayouts, U32 pushConstantsSize,
-											PipelineLayout& layout);
+	Error newPipelineLayout(const WeakArray<DescriptorSetLayout>& dsetLayouts, U32 pushConstantsSize,
+							PipelineLayout& layout);
 
 private:
 	GrAllocator<U8> m_alloc;

+ 1 - 1
AnKi/Gr/Vulkan/QueryFactory.h

@@ -82,7 +82,7 @@ public:
 	}
 
 	/// @note It's thread-safe.
-	ANKI_USE_RESULT Error newQuery(MicroQuery& handle);
+	Error newQuery(MicroQuery& handle);
 
 	/// @note It's thread-safe.
 	void deleteQuery(MicroQuery& handle);

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

@@ -107,7 +107,7 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 
 	// Create
 	ANKI_VK_CHECK(vkCreateSampler(m_factory->m_gr->getDevice(), &ci, nullptr, &m_handle));
-	m_factory->m_gr->trySetVulkanHandleName(inf.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, m_handle);
+	m_factory->m_gr->trySetVulkanHandleName(inf.getName(), VK_OBJECT_TYPE_SAMPLER, m_handle);
 
 	return Error::NONE;
 }

+ 3 - 3
AnKi/Gr/Vulkan/SamplerFactory.h

@@ -59,14 +59,14 @@ private:
 
 	~MicroSampler();
 
-	ANKI_USE_RESULT Error init(const SamplerInitInfo& inf);
+	Error init(const SamplerInitInfo& inf);
 };
 
 /// MicroSamplerPtr deleter.
 class MicroSamplerPtrDeleter
 {
 public:
-	void operator()(MicroSampler* s)
+	void operator()([[maybe_unused]] MicroSampler* s)
 	{
 		ANKI_ASSERT(s);
 		// Do nothing. The samplers will be destroyed at app shutdown
@@ -96,7 +96,7 @@ public:
 	void destroy();
 
 	/// Create a new sampler. It's thread-safe.
-	ANKI_USE_RESULT Error newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& psampler);
+	Error newInstance(const SamplerInitInfo& inf, MicroSamplerPtr& psampler);
 
 private:
 	GrManagerImpl* m_gr = nullptr;

+ 1 - 1
AnKi/Gr/Vulkan/SamplerImpl.h

@@ -29,7 +29,7 @@ public:
 	{
 	}
 
-	ANKI_USE_RESULT Error init(const SamplerInitInfo& init);
+	Error init(const SamplerInitInfo& init);
 };
 /// @}
 

+ 14 - 1
AnKi/Gr/Vulkan/ShaderImpl.cpp

@@ -149,6 +149,19 @@ void ShaderImpl::doReflection(ConstWeakArray<U8> spirv, SpecConstsVector& specCo
 			m_descriptorSetMask.set(set);
 			m_activeBindingMask[set].set(set);
 
+			// Images are special, they might be texel buffers
+			if(type == DescriptorType::TEXTURE)
+			{
+				if(typeInfo.image.dim == spv::DimBuffer && typeInfo.image.sampled == 1)
+				{
+					type = DescriptorType::READ_TEXTURE_BUFFER;
+				}
+				else if(typeInfo.image.dim == spv::DimBuffer && typeInfo.image.sampled == 2)
+				{
+					type = DescriptorType::READ_WRITE_TEXTURE_BUFFER;
+				}
+			}
+
 			// Check that there are no other descriptors with the same binding
 			U32 foundIdx = MAX_U32;
 			for(U32 i = 0; i < counts[set]; ++i)
@@ -180,7 +193,7 @@ void ShaderImpl::doReflection(ConstWeakArray<U8> spirv, SpecConstsVector& specCo
 
 	func(rsrc.uniform_buffers, DescriptorType::UNIFORM_BUFFER);
 	func(rsrc.sampled_images, DescriptorType::COMBINED_TEXTURE_SAMPLER);
-	func(rsrc.separate_images, DescriptorType::TEXTURE);
+	func(rsrc.separate_images, DescriptorType::TEXTURE); // This also handles texture buffers
 	func(rsrc.separate_samplers, DescriptorType::SAMPLER);
 	func(rsrc.storage_buffers, DescriptorType::STORAGE_BUFFER);
 	func(rsrc.storage_images, DescriptorType::IMAGE);

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

@@ -36,7 +36,7 @@ public:
 
 	~ShaderImpl();
 
-	ANKI_USE_RESULT Error init(const ShaderInitInfo& init);
+	Error init(const ShaderInitInfo& init);
 
 	const VkSpecializationInfo* getSpecConstInfo() const
 	{

+ 4 - 2
AnKi/Gr/Vulkan/SwapchainFactory.cpp

@@ -260,9 +260,11 @@ MicroSwapchainPtr SwapchainFactory::newInstance()
 {
 	// Delete stale swapchains (they are stale because they are probably out of data) and always create a new one
 	m_recycler.trimCache();
-	MicroSwapchain* dummy = m_recycler.findToReuse(); // This is useless but call it to avoid assertions
+
+	// This is useless but call it to avoid assertions
+	[[maybe_unused]] MicroSwapchain* dummy = m_recycler.findToReuse();
 	ANKI_ASSERT(dummy == nullptr);
-	(void)dummy;
+
 	return MicroSwapchainPtr(m_gr->getAllocator().newInstance<MicroSwapchain>(this));
 }
 

+ 1 - 1
AnKi/Gr/Vulkan/SwapchainFactory.h

@@ -86,7 +86,7 @@ private:
 
 	MicroFencePtr m_fence;
 
-	ANKI_USE_RESULT Error initInternal();
+	Error initInternal();
 };
 
 /// Deleter for MicroSwapchainPtr smart pointer.

+ 17 - 43
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -42,33 +42,21 @@ static Bool isAstcSrgbFormat(const VkFormat format)
 	}
 }
 
-U32 MicroImageView::getOrCreateBindlessIndex(VkImageLayout layout, GrManagerImpl& gr) const
+U32 MicroImageView::getOrCreateBindlessIndex(GrManagerImpl& gr) const
 {
-	ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL || layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-
-	const U32 arrayIdx = (layout == VK_IMAGE_LAYOUT_GENERAL) ? 1 : 0;
-
-	LockGuard<SpinLock> lock(m_lock);
+	LockGuard<SpinLock> lock(m_bindlessIndexLock);
 
 	U32 outIdx;
-	if(m_bindlessIndices[arrayIdx] != MAX_U32)
+	if(m_bindlessIndex != MAX_U32)
 	{
-		outIdx = m_bindlessIndices[arrayIdx];
+		outIdx = m_bindlessIndex;
 	}
 	else
 	{
 		// Needs binding to the bindless descriptor set
 
-		if(layout == VK_IMAGE_LAYOUT_GENERAL)
-		{
-			outIdx = gr.getDescriptorSetFactory().bindBindlessImage(m_handle);
-		}
-		else
-		{
-			outIdx = gr.getDescriptorSetFactory().bindBindlessTexture(m_handle, layout);
-		}
-
-		m_bindlessIndices[arrayIdx] = outIdx;
+		outIdx = gr.getDescriptorSetFactory().bindBindlessTexture(m_handle, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+		m_bindlessIndex = outIdx;
 	}
 
 	return outIdx;
@@ -90,16 +78,10 @@ TextureImpl::~TextureImpl()
 		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)
+		if(it.m_bindlessIndex != MAX_U32)
 		{
-			garbage->m_bindlessIndices.emplaceBack(getAllocator(), it.m_bindlessIndices[1]);
-			it.m_bindlessIndices[1] = MAX_U32;
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), it.m_bindlessIndex);
+			it.m_bindlessIndex = MAX_U32;
 		}
 	}
 
@@ -110,16 +92,10 @@ TextureImpl::~TextureImpl()
 		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)
+		if(m_singleSurfaceImageView.m_bindlessIndex != MAX_U32)
 		{
-			garbage->m_bindlessIndices.emplaceBack(getAllocator(), m_singleSurfaceImageView.m_bindlessIndices[1]);
-			m_singleSurfaceImageView.m_bindlessIndices[1] = MAX_U32;
+			garbage->m_bindlessIndices.emplaceBack(getAllocator(), m_singleSurfaceImageView.m_bindlessIndex);
+			m_singleSurfaceImageView.m_bindlessIndex = MAX_U32;
 		}
 	}
 
@@ -212,7 +188,7 @@ Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& in
 		ANKI_ASSERT(m_singleSurfaceImageView.m_derivedTextureType == m_texType);
 
 		ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
-		getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
+		getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW,
 												  ptrToNumber(m_singleSurfaceImageView.m_handle));
 	}
 
@@ -307,7 +283,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 
 	ANKI_VK_CHECK(vkCreateImage(getDevice(), &ci, nullptr, &m_imageHandle));
-	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_imageHandle);
+	getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_OBJECT_TYPE_IMAGE, m_imageHandle);
 #if 0
 	printf("Creating texture %p %s\n", static_cast<void*>(m_imageHandle),
 		   init.getName() ? init.getName().cstr() : "Unnamed");
@@ -344,9 +320,8 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	// Allocate
 	if(!dedicatedRequirements.prefersDedicatedAllocation)
 	{
-		getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, requirements.memoryRequirements.size,
-																U32(requirements.memoryRequirements.alignment), false,
-																m_memHandle);
+		getGrManagerImpl().getGpuMemoryManager().allocateMemory(
+			memIdx, requirements.memoryRequirements.size, U32(requirements.memoryRequirements.alignment), m_memHandle);
 	}
 	else
 	{
@@ -615,8 +590,7 @@ const MicroImageView& TextureImpl::getOrCreateView(const TextureSubresourceInfo&
 	ANKI_ASSERT(viewTexType != TextureType::COUNT);
 
 	ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &handle));
-	getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
-											  ptrToNumber(handle));
+	getGrManagerImpl().trySetVulkanHandleName(getName(), VK_OBJECT_TYPE_IMAGE_VIEW, ptrToNumber(handle));
 
 	it = m_viewsMap.emplace(getAllocator(), subresource);
 	it->m_handle = handle;

+ 13 - 21
AnKi/Gr/Vulkan/TextureImpl.h

@@ -35,11 +35,7 @@ public:
 
 	~MicroImageView()
 	{
-		for(U32 idx : m_bindlessIndices)
-		{
-			ANKI_ASSERT(idx == MAX_U32 && "Forgot to unbind the bindless");
-			(void)idx;
-		}
+		ANKI_ASSERT(m_bindlessIndex == MAX_U32 && "Forgot to unbind the bindless");
 		ANKI_ASSERT(m_handle == VK_NULL_HANDLE);
 	}
 
@@ -47,8 +43,8 @@ public:
 	{
 		m_handle = b.m_handle;
 		b.m_handle = VK_NULL_HANDLE;
-		m_bindlessIndices = b.m_bindlessIndices;
-		b.m_bindlessIndices = {MAX_U32, MAX_U32};
+		m_bindlessIndex = b.m_bindlessIndex;
+		b.m_bindlessIndex = MAX_U32;
 		m_derivedTextureType = b.m_derivedTextureType;
 		b.m_derivedTextureType = TextureType::COUNT;
 		return *this;
@@ -61,7 +57,7 @@ public:
 	}
 
 	/// @note It's thread-safe.
-	U32 getOrCreateBindlessIndex(VkImageLayout layout, GrManagerImpl& gr) const;
+	U32 getOrCreateBindlessIndex(GrManagerImpl& gr) const;
 
 	TextureType getDerivedTextureType() const
 	{
@@ -72,12 +68,8 @@ public:
 private:
 	VkImageView m_handle = VK_NULL_HANDLE;
 
-	/// Index 0: Sampled image with SHADER_READ_ONLY layout.
-	/// Index 1: Storage image with ofcource GENERAL layout.
-	mutable Array<U32, 2> m_bindlessIndices = {MAX_U32, MAX_U32};
-
-	/// Protect the m_bindlessIndices.
-	mutable SpinLock m_lock;
+	mutable U32 m_bindlessIndex = MAX_U32;
+	mutable SpinLock m_bindlessIndexLock;
 
 	/// Because for example a single surface view of a cube texture will be a 2D view.
 	TextureType m_derivedTextureType = TextureType::COUNT;
@@ -103,12 +95,12 @@ public:
 
 	~TextureImpl();
 
-	ANKI_USE_RESULT Error init(const TextureInitInfo& init)
+	Error init(const TextureInitInfo& init)
 	{
 		return initInternal(VK_NULL_HANDLE, init);
 	}
 
-	ANKI_USE_RESULT Error initExternal(VkImage image, const TextureInitInfo& init)
+	Error initExternal(VkImage image, const TextureInitInfo& init)
 	{
 		return initInternal(image, init);
 	}
@@ -143,7 +135,7 @@ public:
 		return layer;
 	}
 
-	U32 computeVkArrayLayer(const TextureVolumeInfo& vol) const
+	U32 computeVkArrayLayer([[maybe_unused]] const TextureVolumeInfo& vol) const
 	{
 		ANKI_ASSERT(m_texType == TextureType::_3D);
 		return 0;
@@ -207,16 +199,16 @@ private:
 	mutable SpinLock m_usedForMtx;
 #endif
 
-	ANKI_USE_RESULT static VkImageCreateFlags calcCreateFlags(const TextureInitInfo& init);
+	[[nodiscard]] static VkImageCreateFlags calcCreateFlags(const TextureInitInfo& init);
 
-	ANKI_USE_RESULT Bool imageSupported(const TextureInitInfo& init);
+	[[nodiscard]] Bool imageSupported(const TextureInitInfo& init);
 
-	ANKI_USE_RESULT Error initImage(const TextureInitInfo& init);
+	Error initImage(const TextureInitInfo& init);
 
 	/// Compute the new type of a texture view.
 	TextureType computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const;
 
-	ANKI_USE_RESULT Error initInternal(VkImage externalImage, const TextureInitInfo& init);
+	Error initInternal(VkImage externalImage, const TextureInitInfo& init);
 
 	void computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
 							VkAccessFlags& accesses) const;

+ 1 - 8
AnKi/Gr/Vulkan/TextureView.cpp

@@ -26,14 +26,7 @@ U32 TextureView::getOrCreateBindlessTextureIndex()
 	ANKI_VK_SELF(TextureViewImpl);
 	ANKI_ASSERT(self.getTextureImpl().computeLayout(TextureUsageBit::ALL_SAMPLED, 0)
 				== VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-	return self.getOrCreateBindlessIndex(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-}
-
-U32 TextureView::getOrCreateBindlessImageIndex()
-{
-	ANKI_VK_SELF(TextureViewImpl);
-	ANKI_ASSERT(self.getTextureImpl().computeLayout(TextureUsageBit::ALL_IMAGE, 0) == VK_IMAGE_LAYOUT_GENERAL);
-	return self.getOrCreateBindlessIndex(VK_IMAGE_LAYOUT_GENERAL);
+	return self.getOrCreateBindlessIndex();
 }
 
 } // end namespace anki

+ 4 - 7
AnKi/Gr/Vulkan/TextureViewImpl.cpp

@@ -36,17 +36,14 @@ Error TextureViewImpl::init(const TextureViewInitInfo& inf)
 	return Error::NONE;
 }
 
-U32 TextureViewImpl::getOrCreateBindlessIndex(VkImageLayout layout)
+U32 TextureViewImpl::getOrCreateBindlessIndex()
 {
-	const U32 arrayIdx = (layout == VK_IMAGE_LAYOUT_GENERAL) ? 1 : 0;
-	U32& bindlessIdx = m_bindlessIndices[arrayIdx];
-
-	if(bindlessIdx == MAX_U32)
+	if(m_bindlessIndex == MAX_U32)
 	{
-		bindlessIdx = m_microImageView->getOrCreateBindlessIndex(layout, getGrManagerImpl());
+		m_bindlessIndex = m_microImageView->getOrCreateBindlessIndex(getGrManagerImpl());
 	}
 
-	return bindlessIdx;
+	return m_bindlessIndex;
 }
 
 } // end namespace anki

+ 3 - 4
AnKi/Gr/Vulkan/TextureViewImpl.h

@@ -25,7 +25,7 @@ public:
 
 	~TextureViewImpl();
 
-	ANKI_USE_RESULT Error init(const TextureViewInitInfo& inf);
+	Error init(const TextureViewInitInfo& inf);
 
 	VkImageSubresourceRange getVkImageSubresourceRange() const
 	{
@@ -51,12 +51,11 @@ public:
 		return static_cast<const TextureImpl&>(*m_tex);
 	}
 
-	U32 getOrCreateBindlessIndex(VkImageLayout layout);
+	U32 getOrCreateBindlessIndex();
 
 private:
 	VkImageView m_handle = {}; ///< Cache the handle.
-
-	Array<U32, 2> m_bindlessIndices = {MAX_U32, MAX_U32}; ///< Cache it.
+	U32 m_bindlessIndex = MAX_U32; ///< Cache it.
 
 	/// This is a hash that depends on the Texture and the VkImageView. It's used as a replacement of
 	/// TextureView::m_uuid since it creates less unique IDs.

+ 1 - 1
AnKi/Gr/Vulkan/TimestampQueryImpl.h

@@ -28,7 +28,7 @@ public:
 	~TimestampQueryImpl();
 
 	/// Create the query.
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	/// Get query result.
 	TimestampQueryResult getResultInternal(Second& timestamp) const;

+ 6 - 4
AnKi/Importer/GltfImporter.cpp

@@ -29,7 +29,7 @@ static F32 computeLightRadius(const Vec3 color)
 }
 
 #if 0
-static ANKI_USE_RESULT Error getUniformScale(const Mat4& m, F32& out)
+static Error getUniformScale(const Mat4& m, F32& out)
 {
 	const F32 SCALE_THRESHOLD = 0.01f; // 1 cm
 
@@ -114,7 +114,7 @@ static void getNodeTransform(const cgltf_node& node, Vec3& tsl, Mat3& rot, Vec3&
 	}
 }
 
-static ANKI_USE_RESULT Error getNodeTransform(const cgltf_node& node, Transform& trf)
+static Error getNodeTransform(const cgltf_node& node, Transform& trf)
 {
 	Vec3 tsl;
 	Mat3 rot;
@@ -712,7 +712,8 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			}
 
 			// Thread task
-			auto callback = [](void* userData, U32 threadId, ThreadHive& hive, ThreadHiveSemaphore* signalSemaphore) {
+			auto callback = [](void* userData, [[maybe_unused]] U32 threadId, [[maybe_unused]] ThreadHive& hive,
+							   [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
 				Ctx& self = *static_cast<Ctx*>(userData);
 
 				// LOD 0
@@ -1403,7 +1404,8 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 	return Error::NONE;
 }
 
-Error GltfImporter::writeCamera(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras)
+Error GltfImporter::writeCamera(const cgltf_node& node,
+								[[maybe_unused]] const HashMapAuto<CString, StringAuto>& parentExtras)
 {
 	if(node.camera->type != cgltf_camera_type_perspective)
 	{

+ 15 - 16
AnKi/Importer/GltfImporter.h

@@ -43,9 +43,9 @@ public:
 
 	~GltfImporter();
 
-	ANKI_USE_RESULT Error init(const GltfImporterInitInfo& initInfo);
+	Error init(const GltfImporterInitInfo& initInfo);
 
-	ANKI_USE_RESULT Error writeAll();
+	Error writeAll();
 
 private:
 	class PtrHasher
@@ -89,9 +89,8 @@ private:
 	U32 m_skipLodVertexCountThreshold = 256;
 
 	// Misc
-	ANKI_USE_RESULT Error getExtras(const cgltf_extras& extras, HashMapAuto<CString, StringAuto>& out);
-	ANKI_USE_RESULT Error parseArrayOfNumbers(CString str, DynamicArrayAuto<F64>& out,
-											  const U32* expectedArraySize = nullptr);
+	Error getExtras(const cgltf_extras& extras, HashMapAuto<CString, StringAuto>& out);
+	Error parseArrayOfNumbers(CString str, DynamicArrayAuto<F64>& out, const U32* expectedArraySize = nullptr);
 	void populateNodePtrToIdx();
 	void populateNodePtrToIdxInternal(const cgltf_node& node, U32& idx);
 	StringAuto getNodeName(const cgltf_node& node);
@@ -136,19 +135,19 @@ private:
 	StringAuto computeSkeletonResourceFilename(const cgltf_skin& skin) const;
 
 	// Resources
-	ANKI_USE_RESULT Error writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFactor);
-	ANKI_USE_RESULT Error writeMaterial(const cgltf_material& mtl, Bool writeRayTracing);
-	ANKI_USE_RESULT Error writeModel(const cgltf_mesh& mesh);
-	ANKI_USE_RESULT Error writeAnimation(const cgltf_animation& anim);
-	ANKI_USE_RESULT Error writeSkeleton(const cgltf_skin& skin);
+	Error writeMesh(const cgltf_mesh& mesh, U32 lod, F32 decimateFactor);
+	Error writeMaterial(const cgltf_material& mtl, Bool writeRayTracing);
+	Error writeModel(const cgltf_mesh& mesh);
+	Error writeAnimation(const cgltf_animation& anim);
+	Error writeSkeleton(const cgltf_skin& skin);
 
 	// Scene
-	ANKI_USE_RESULT Error writeTransform(const Transform& trf);
-	ANKI_USE_RESULT Error visitNode(const cgltf_node& node, const Transform& parentTrf,
-									const HashMapAuto<CString, StringAuto>& parentExtras);
-	ANKI_USE_RESULT Error writeLight(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
-	ANKI_USE_RESULT Error writeCamera(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
-	ANKI_USE_RESULT Error writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
+	Error writeTransform(const Transform& trf);
+	Error visitNode(const cgltf_node& node, const Transform& parentTrf,
+					const HashMapAuto<CString, StringAuto>& parentExtras);
+	Error writeLight(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
+	Error writeCamera(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
+	Error writeModelNode(const cgltf_node& node, const HashMapAuto<CString, StringAuto>& parentExtras);
 };
 /// @}
 

+ 27 - 33
AnKi/Importer/ImageImporter.cpp

@@ -158,7 +158,7 @@ public:
 
 } // namespace
 
-static ANKI_USE_RESULT Error checkConfig(const ImageImporterConfig& config)
+static Error checkConfig(const ImageImporterConfig& config)
 {
 #define ANKI_CFG_ASSERT(x, message) \
 	do \
@@ -212,7 +212,7 @@ static ANKI_USE_RESULT Error checkConfig(const ImageImporterConfig& config)
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error identifyImage(CString filename, U32& width, U32& height, U32& channelCount, Bool& hdr)
+static Error identifyImage(CString filename, U32& width, U32& height, U32& channelCount, Bool& hdr)
 {
 	I32 iwidth, iheight, ichannelCount;
 	const I ok = stbi_info(filename.cstr(), &iwidth, &iheight, &ichannelCount);
@@ -232,8 +232,8 @@ static ANKI_USE_RESULT Error identifyImage(CString filename, U32& width, U32& he
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error checkInputImages(const ImageImporterConfig& config, U32& width, U32& height,
-											  U32& channelCount, Bool& isHdr)
+static Error checkInputImages(const ImageImporterConfig& config, U32& width, U32& height, U32& channelCount,
+							  Bool& isHdr)
 {
 	width = 0;
 	height = 0;
@@ -271,8 +271,8 @@ static ANKI_USE_RESULT Error checkInputImages(const ImageImporterConfig& config,
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error resizeImage(CString inImageFilename, U32 outWidth, U32 outHeight, CString tempDirectory,
-										 GenericMemoryPoolAllocator<U8> alloc, StringAuto& tmpFilename)
+static Error resizeImage(CString inImageFilename, U32 outWidth, U32 outHeight, CString tempDirectory,
+						 GenericMemoryPoolAllocator<U8> alloc, StringAuto& tmpFilename)
 {
 	U32 inWidth, inHeight, channelCount;
 	Bool hdr;
@@ -403,14 +403,14 @@ static void linearToSRgbBatch(WeakArray<TVec> pixels, TFunc func)
 		}
 		else
 		{
-			pixel.x() = p.x();
-			pixel.y() = p.y();
-			pixel.z() = p.z();
+			pixel.x() = S(p.x());
+			pixel.y() = S(p.y());
+			pixel.z() = S(p.z());
 		}
 	}
 }
 
-static ANKI_USE_RESULT Error loadFirstMipmap(const ImageImporterConfig& config, ImageImporterContext& ctx)
+static Error loadFirstMipmap(const ImageImporterConfig& config, ImageImporterContext& ctx)
 {
 	GenericMemoryPoolAllocator<U8> alloc = ctx.getAllocator();
 
@@ -587,9 +587,9 @@ static void generateSurfaceMipmap(ConstWeakArray<U8, PtrSize> inBuffer, U32 inWi
 	}
 }
 
-static ANKI_USE_RESULT Error compressS3tc(GenericMemoryPoolAllocator<U8> alloc, CString tempDirectory,
-										  CString compressonatorPath, ConstWeakArray<U8, PtrSize> inPixels, U32 inWidth,
-										  U32 inHeight, U32 channelCount, Bool hdr, WeakArray<U8, PtrSize> outPixels)
+static Error compressS3tc(GenericMemoryPoolAllocator<U8> alloc, CString tempDirectory, CString compressonatorFilename,
+						  ConstWeakArray<U8, PtrSize> inPixels, U32 inWidth, U32 inHeight, U32 channelCount, Bool hdr,
+						  WeakArray<U8, PtrSize> outPixels)
 {
 	ANKI_ASSERT(inPixels.getSizeInBytes()
 				== PtrSize(inWidth) * inHeight * channelCount * ((hdr) ? sizeof(F32) : sizeof(U8)));
@@ -635,15 +635,13 @@ static ANKI_USE_RESULT Error compressS3tc(GenericMemoryPoolAllocator<U8> alloc,
 
 	ANKI_IMPORTER_LOGV("Will invoke process: compressonatorcli %s %s %s %s %s", args[0].cstr(), args[1].cstr(),
 					   args[2].cstr(), args[3].cstr(), args[4].cstr());
-	ANKI_CHECK(proc.start("compressonatorcli", args,
-						  (compressonatorPath.isEmpty()) ? ConstWeakArray<CString>()
-														 : Array<CString, 2>{{"PATH", compressonatorPath}}));
+	ANKI_CHECK(proc.start(compressonatorFilename, args));
 	CleanupFile ddsCleanup(alloc, ddsFilename);
 	ProcessStatus status;
 	I32 exitCode;
-	ANKI_CHECK(proc.wait(60.0, &status, &exitCode));
+	ANKI_CHECK(proc.wait(60.0_sec, &status, &exitCode));
 
-	if(status != ProcessStatus::NORMAL_EXIT || exitCode != 0)
+	if(!(status == ProcessStatus::NOT_RUNNING && exitCode == 0))
 	{
 		StringAuto errStr(alloc);
 		if(exitCode != 0)
@@ -701,13 +699,11 @@ static ANKI_USE_RESULT Error compressS3tc(GenericMemoryPoolAllocator<U8> alloc,
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error compressAstc(GenericMemoryPoolAllocator<U8> alloc, CString tempDirectory,
-										  CString astcencPath, ConstWeakArray<U8, PtrSize> inPixels, U32 inWidth,
-										  U32 inHeight, U32 inChannelCount, UVec2 blockSize, Bool hdr,
-										  WeakArray<U8, PtrSize> outPixels)
+static Error compressAstc(GenericMemoryPoolAllocator<U8> alloc, CString tempDirectory, CString astcencFilename,
+						  ConstWeakArray<U8, PtrSize> inPixels, U32 inWidth, U32 inHeight, U32 inChannelCount,
+						  UVec2 blockSize, Bool hdr, WeakArray<U8, PtrSize> outPixels)
 {
-	const PtrSize blockBytes = 16;
-	(void)blockBytes;
+	[[maybe_unused]] const PtrSize blockBytes = 16;
 	ANKI_ASSERT(inPixels.getSizeInBytes()
 				== PtrSize(inWidth) * inHeight * inChannelCount * ((hdr) ? sizeof(F32) : sizeof(U8)));
 	ANKI_ASSERT(inWidth > 0 && isPowerOfTwo(inWidth) && inHeight > 0 && isPowerOfTwo(inHeight));
@@ -753,16 +749,14 @@ static ANKI_USE_RESULT Error compressAstc(GenericMemoryPoolAllocator<U8> alloc,
 
 	ANKI_IMPORTER_LOGV("Will invoke process: astcenc-avx2 %s %s %s %s %s", args[0].cstr(), args[1].cstr(),
 					   args[2].cstr(), args[3].cstr(), args[4].cstr());
-	ANKI_CHECK(
-		proc.start("astcenc-avx2", args,
-				   (astcencPath.isEmpty()) ? ConstWeakArray<CString>() : Array<CString, 2>{{"PATH", astcencPath}}));
+	ANKI_CHECK(proc.start(astcencFilename, args));
 
 	CleanupFile astcCleanup(alloc, astcFilename);
 	ProcessStatus status;
 	I32 exitCode;
-	ANKI_CHECK(proc.wait(60.0, &status, &exitCode));
+	ANKI_CHECK(proc.wait(60.0_sec, &status, &exitCode));
 
-	if(status != ProcessStatus::NORMAL_EXIT || exitCode != 0)
+	if(!(status == ProcessStatus::NOT_RUNNING && exitCode == 0))
 	{
 		StringAuto errStr(alloc);
 		if(exitCode != 0)
@@ -819,7 +813,7 @@ static ANKI_USE_RESULT Error compressAstc(GenericMemoryPoolAllocator<U8> alloc,
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error storeAnkiImage(const ImageImporterConfig& config, const ImageImporterContext& ctx)
+static Error storeAnkiImage(const ImageImporterConfig& config, const ImageImporterContext& ctx)
 {
 	ANKI_IMPORTER_LOGV("Storing to %s", config.m_outFilename.cstr());
 
@@ -912,7 +906,7 @@ static ANKI_USE_RESULT Error storeAnkiImage(const ImageImporterConfig& config, c
 	return Error::NONE;
 }
 
-static ANKI_USE_RESULT Error importImageInternal(const ImageImporterConfig& configOriginal)
+static Error importImageInternal(const ImageImporterConfig& configOriginal)
 {
 	GenericMemoryPoolAllocator<U8> alloc = configOriginal.m_allocator;
 	ImageImporterConfig config = configOriginal;
@@ -1096,7 +1090,7 @@ static ANKI_USE_RESULT Error importImageInternal(const ImageImporterConfig& conf
 
 					surface.m_s3tcPixels.create(s3tcImageSize);
 
-					ANKI_CHECK(compressS3tc(alloc, config.m_tempDirectory, config.m_compressonatorPath,
+					ANKI_CHECK(compressS3tc(alloc, config.m_tempDirectory, config.m_compressonatorFilename,
 											ConstWeakArray<U8, PtrSize>(surface.m_pixels), width, height,
 											ctx.m_channelCount, ctx.m_hdr,
 											WeakArray<U8, PtrSize>(surface.m_s3tcPixels)));
@@ -1126,7 +1120,7 @@ static ANKI_USE_RESULT Error importImageInternal(const ImageImporterConfig& conf
 
 					surface.m_astcPixels.create(astcImageSize);
 
-					ANKI_CHECK(compressAstc(alloc, config.m_tempDirectory, config.m_astcencPath,
+					ANKI_CHECK(compressAstc(alloc, config.m_tempDirectory, config.m_astcencFilename,
 											ConstWeakArray<U8, PtrSize>(surface.m_pixels), width, height,
 											ctx.m_channelCount, config.m_astcBlockSize, ctx.m_hdr,
 											WeakArray<U8, PtrSize>(surface.m_astcPixels)));

+ 3 - 3
AnKi/Importer/ImageImporter.h

@@ -27,8 +27,8 @@ public:
 	U32 m_mipmapCount = MAX_U32;
 	Bool m_noAlpha = true;
 	CString m_tempDirectory;
-	CString m_compressonatorPath; ///< Optional.
-	CString m_astcencPath; ///< Optional.
+	CString m_compressonatorFilename; ///< Optional.
+	CString m_astcencFilename; ///< Optional.
 	UVec2 m_astcBlockSize = UVec2(8u);
 	Bool m_sRgbToLinear = false;
 	Bool m_linearToSRgb = false;
@@ -36,7 +36,7 @@ public:
 };
 
 /// Converts images to AnKi's specific format.
-ANKI_USE_RESULT Error importImage(const ImageImporterConfig& config);
+Error importImage(const ImageImporterConfig& config);
 /// @}
 
 } // end namespace anki

+ 3 - 3
AnKi/Input/Input.h

@@ -32,8 +32,8 @@ class Input
 	ANKI_FRIEND_ALLOCATOR
 
 public:
-	static ANKI_USE_RESULT Error newInstance(AllocAlignedCallback allocCallback, void* allocCallbackUserData,
-											 NativeWindow* nativeWindow, Input*& input);
+	static Error newInstance(AllocAlignedCallback allocCallback, void* allocCallbackUserData,
+							 NativeWindow* nativeWindow, Input*& input);
 
 	static void deleteInstance(Input* input);
 
@@ -78,7 +78,7 @@ public:
 	}
 
 	/// Populate the key and button with the new state
-	ANKI_USE_RESULT Error handleEvents();
+	Error handleEvents();
 
 	/// Move the mouse cursor to a position inside the window. Useful for locking the cursor into a fixed location (eg
 	/// in the center of the screen)

+ 1 - 1
AnKi/Input/InputAndroid.h

@@ -15,7 +15,7 @@ namespace anki {
 class InputAndroid : public Input
 {
 public:
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	void handleAndroidEvents(android_app* app, int32_t cmd);
 	int handleAndroidInput(android_app* app, AInputEvent* event);

+ 2 - 2
AnKi/Math/Mat.h

@@ -1345,7 +1345,7 @@ public:
 
 	/// Calculate a perspective projection matrix. The z is mapped in [0, 1] range just like DX and Vulkan.
 	ANKI_ENABLE_METHOD(I == 4 && J == 4)
-	static ANKI_USE_RESULT TMat calculatePerspectiveProjectionMatrix(T fovX, T fovY, T near, T far)
+	[[nodiscard]] static TMat calculatePerspectiveProjectionMatrix(T fovX, T fovY, T near, T far)
 	{
 		ANKI_ASSERT(fovX > T(0) && fovY > T(0) && near > T(0) && far > T(0));
 		const T g = near - far;
@@ -1374,7 +1374,7 @@ public:
 
 	/// Calculate an orthographic projection matrix. The z is mapped in [0, 1] range just like DX and Vulkan.
 	ANKI_ENABLE_METHOD(I == 4 && J == 4)
-	static ANKI_USE_RESULT TMat calculateOrthographicProjectionMatrix(T right, T left, T top, T bottom, T near, T far)
+	[[nodiscard]] static TMat calculateOrthographicProjectionMatrix(T right, T left, T top, T bottom, T near, T far)
 	{
 		ANKI_ASSERT(right != T(0) && left != T(0) && top != T(0) && bottom != T(0) && near != T(0) && far != T(0));
 		const T difx = right - left;

+ 1 - 2
AnKi/Math/Transform.h

@@ -38,8 +38,7 @@ public:
 		const TVec<T, 3> s2 = m4.getColumn(2).xyz();
 
 		const TVec<T, 3> scales(s0.getLength(), s1.getLength(), s2.getLength());
-		const T E = T(0.001);
-		(void)E;
+		[[maybe_unused]] const T E = T(0.001);
 		ANKI_ASSERT(isZero(scales.x() - scales.y(), E) && isZero(scales.y() - scales.z(), E)
 					&& "Expecting uniform scale");
 

+ 5 - 5
AnKi/Physics/Common.h

@@ -90,17 +90,17 @@ enum class PhysicsMaterialBit : U64
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(PhysicsMaterialBit)
 
-ANKI_USE_RESULT inline Vec3 toAnki(const btVector3& v)
+[[nodiscard]] inline Vec3 toAnki(const btVector3& v)
 {
 	return Vec3(v.getX(), v.getY(), v.getZ());
 }
 
-ANKI_USE_RESULT inline btVector3 toBt(const Vec3& v)
+[[nodiscard]] inline btVector3 toBt(const Vec3& v)
 {
 	return btVector3(v.x(), v.y(), v.z());
 }
 
-ANKI_USE_RESULT inline btTransform toBt(const Transform& a)
+[[nodiscard]] inline btTransform toBt(const Transform& a)
 {
 	Mat4 mat(a);
 	mat.transpose();
@@ -109,14 +109,14 @@ ANKI_USE_RESULT inline btTransform toBt(const Transform& a)
 	return out;
 }
 
-ANKI_USE_RESULT inline Mat3x4 toAnki(const btMatrix3x3& m)
+[[nodiscard]] inline Mat3x4 toAnki(const btMatrix3x3& m)
 {
 	Mat3x4 m3;
 	m3.setRows(Vec4(toAnki(m[0]), 0.0f), Vec4(toAnki(m[1]), 0.0f), Vec4(toAnki(m[2]), 0.0f));
 	return m3;
 }
 
-ANKI_USE_RESULT inline Transform toAnki(const btTransform& t)
+[[nodiscard]] inline Transform toAnki(const btTransform& t)
 {
 	Transform out;
 	out.setRotation(toAnki(t.getBasis()));

+ 5 - 4
AnKi/Physics/PhysicsDrawer.h

@@ -43,8 +43,9 @@ private:
 			m_drawer->drawLines(&lines[0], 2, Vec4(toAnki(color), 1.0f));
 		}
 
-		void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime,
-							  const btVector3& color) override
+		void drawContactPoint([[maybe_unused]] const btVector3& PointOnB, [[maybe_unused]] const btVector3& normalOnB,
+							  [[maybe_unused]] btScalar distance, [[maybe_unused]] int lifeTime,
+							  [[maybe_unused]] const btVector3& color) override
 		{
 			// TODO
 		}
@@ -54,12 +55,12 @@ private:
 			ANKI_PHYS_LOGW("%s", warningString);
 		}
 
-		void draw3dText(const btVector3& location, const char* textString) override
+		void draw3dText([[maybe_unused]] const btVector3& location, [[maybe_unused]] const char* textString) override
 		{
 			// TODO
 		}
 
-		void setDebugMode(int debugMode) override
+		void setDebugMode([[maybe_unused]] int debugMode) override
 		{
 			// TODO
 		}

+ 2 - 1
AnKi/Physics/PhysicsPlayerController.h

@@ -32,7 +32,8 @@ class PhysicsPlayerController final : public PhysicsFilteredObject
 
 public:
 	// Update the state machine
-	void setVelocity(F32 forwardSpeed, F32 strafeSpeed, F32 jumpSpeed, const Vec4& forwardDir)
+	void setVelocity(F32 forwardSpeed, [[maybe_unused]] F32 strafeSpeed, [[maybe_unused]] F32 jumpSpeed,
+					 const Vec4& forwardDir)
 	{
 		m_controller->setWalkDirection(toBt((forwardDir * forwardSpeed).xyz()));
 	}

+ 3 - 3
AnKi/Physics/PhysicsTrigger.h

@@ -21,17 +21,17 @@ class PhysicsTriggerProcessContactCallback
 {
 public:
 	/// Will be called whenever a contact first touches a trigger.
-	virtual void onTriggerEnter(PhysicsTrigger& trigger, PhysicsFilteredObject& obj)
+	virtual void onTriggerEnter([[maybe_unused]] PhysicsTrigger& trigger, [[maybe_unused]] PhysicsFilteredObject& obj)
 	{
 	}
 
 	/// Will be called whenever a contact touches a trigger.
-	virtual void onTriggerInside(PhysicsTrigger& trigger, PhysicsFilteredObject& obj)
+	virtual void onTriggerInside([[maybe_unused]] PhysicsTrigger& trigger, [[maybe_unused]] PhysicsFilteredObject& obj)
 	{
 	}
 
 	/// Will be called whenever a contact stops touching a trigger.
-	virtual void onTriggerExit(PhysicsTrigger& trigger, PhysicsFilteredObject& obj)
+	virtual void onTriggerExit([[maybe_unused]] PhysicsTrigger& trigger, [[maybe_unused]] PhysicsFilteredObject& obj)
 	{
 	}
 };

+ 1 - 3
AnKi/Physics/PhysicsWorld.cpp

@@ -222,7 +222,7 @@ void PhysicsWorld::destroyMarkedForDeletion()
 	}
 }
 
-Error PhysicsWorld::update(Second dt)
+void PhysicsWorld::update(Second dt)
 {
 	// First destroy
 	destroyMarkedForDeletion();
@@ -260,8 +260,6 @@ Error PhysicsWorld::update(Second dt)
 
 	// Reset the pool
 	m_tmpAlloc.getMemoryPool().reset();
-
-	return Error::NONE;
 }
 
 void PhysicsWorld::destroyObject(PhysicsObject* obj)

+ 2 - 2
AnKi/Physics/PhysicsWorld.h

@@ -43,7 +43,7 @@ public:
 	PhysicsWorld();
 	~PhysicsWorld();
 
-	ANKI_USE_RESULT Error init(AllocAlignedCallback allocCb, void* allocCbData);
+	Error init(AllocAlignedCallback allocCb, void* allocCbData);
 
 	template<typename T, typename... TArgs>
 	PhysicsPtr<T> newInstance(TArgs&&... args)
@@ -62,7 +62,7 @@ public:
 	}
 
 	/// Do the update.
-	Error update(Second dt);
+	void update(Second dt);
 
 	HeapAllocator<U8> getAllocator() const
 	{

+ 1 - 1
AnKi/Renderer/AccelerationStructureBuilder.h

@@ -25,7 +25,7 @@ public:
 	{
 	}
 
-	ANKI_USE_RESULT Error init()
+	Error init()
 	{
 		return Error::NONE;
 	}

+ 4 - 4
AnKi/Renderer/Bloom.h

@@ -22,7 +22,7 @@ public:
 
 	~Bloom();
 
-	ANKI_USE_RESULT Error init()
+	Error init()
 	{
 		const Error err = initInternal();
 		if(err)
@@ -79,10 +79,10 @@ private:
 		RenderTargetHandle m_upscaleRt;
 	} m_runCtx;
 
-	ANKI_USE_RESULT Error initExposure();
-	ANKI_USE_RESULT Error initUpscale();
+	Error initExposure();
+	Error initUpscale();
 
-	ANKI_USE_RESULT Error initInternal();
+	Error initInternal();
 };
 
 /// @}

+ 2 - 1
AnKi/Renderer/ClusterBinning.cpp

@@ -223,7 +223,8 @@ void ClusterBinning::writeClustererBuffers(RenderingContext& ctx)
 void ClusterBinning::writeClusterBuffersAsync()
 {
 	m_r->getThreadHive().submitTask(
-		[](void* userData, U32 threadId, ThreadHive& hive, ThreadHiveSemaphore* signalSemaphore) {
+		[](void* userData, [[maybe_unused]] U32 threadId, [[maybe_unused]] ThreadHive& hive,
+		   [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
 			static_cast<ClusterBinning*>(userData)->writeClustererBuffersTask();
 		},
 		this);

+ 1 - 1
AnKi/Renderer/ClusterBinning.h

@@ -20,7 +20,7 @@ public:
 
 	~ClusterBinning();
 
-	ANKI_USE_RESULT Error init();
+	Error init();
 
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);

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