Browse Source

Move Vulkan to the new binding model

Panagiotis Christopoulos Charitos 1 year ago
parent
commit
97734abaae
100 changed files with 2230 additions and 2366 deletions
  1. 2 2
      AnKi/Core/CVarSet.cpp
  2. 3 3
      AnKi/Core/GpuMemory/GpuSceneBuffer.cpp
  3. 12 0
      AnKi/Gr/BackendCommon/Common.cpp
  4. 3 0
      AnKi/Gr/BackendCommon/Common.h
  5. 0 79
      AnKi/Gr/BackendCommon/Functions.cpp
  6. 0 3
      AnKi/Gr/BackendCommon/Functions.h
  7. 1 0
      AnKi/Gr/CMakeLists.txt
  8. 10 27
      AnKi/Gr/CommandBuffer.h
  9. 43 20
      AnKi/Gr/Common.cpp
  10. 73 44
      AnKi/Gr/Common.h
  11. 1 36
      AnKi/Gr/D3D/D3DCommandBuffer.cpp
  12. 1 1
      AnKi/Gr/D3D/D3DShaderProgram.cpp
  13. 9 30
      AnKi/Gr/RenderGraph.h
  14. 2 2
      AnKi/Gr/RenderGraph.inl.h
  15. 7 3
      AnKi/Gr/Shader.h
  16. 70 123
      AnKi/Gr/Vulkan/VkCommandBuffer.cpp
  17. 1 3
      AnKi/Gr/Vulkan/VkCommandBuffer.h
  18. 3 3
      AnKi/Gr/Vulkan/VkCommandBufferFactory.h
  19. 618 0
      AnKi/Gr/Vulkan/VkDescriptor.cpp
  20. 362 0
      AnKi/Gr/Vulkan/VkDescriptor.h
  21. 0 667
      AnKi/Gr/Vulkan/VkDescriptorSetFactory.cpp
  22. 0 348
      AnKi/Gr/Vulkan/VkDescriptorSetFactory.h
  23. 2 2
      AnKi/Gr/Vulkan/VkFrameGarbageCollector.cpp
  24. 61 63
      AnKi/Gr/Vulkan/VkGrManager.cpp
  25. 0 1
      AnKi/Gr/Vulkan/VkPipelineFactory.h
  26. 0 76
      AnKi/Gr/Vulkan/VkPipelineLayoutFactory.cpp
  27. 0 53
      AnKi/Gr/Vulkan/VkPipelineLayoutFactory.h
  28. 5 11
      AnKi/Gr/Vulkan/VkShader.cpp
  29. 2 2
      AnKi/Gr/Vulkan/VkShader.h
  30. 240 44
      AnKi/Gr/Vulkan/VkShaderProgram.cpp
  31. 7 12
      AnKi/Gr/Vulkan/VkShaderProgram.h
  32. 2 2
      AnKi/Gr/Vulkan/VkTexture.cpp
  33. 8 8
      AnKi/Renderer/Bloom.cpp
  34. 8 8
      AnKi/Renderer/ClusterBinning.cpp
  35. 11 11
      AnKi/Renderer/Dbg.cpp
  36. 7 7
      AnKi/Renderer/DepthDownscale.cpp
  37. 5 5
      AnKi/Renderer/DownscaleBlur.cpp
  38. 11 11
      AnKi/Renderer/FinalComposite.cpp
  39. 10 9
      AnKi/Renderer/ForwardShading.cpp
  40. 6 8
      AnKi/Renderer/GBufferPost.cpp
  41. 4 4
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  42. 7 7
      AnKi/Renderer/LensFlare.cpp
  43. 27 27
      AnKi/Renderer/LightShading.cpp
  44. 2 2
      AnKi/Renderer/MainRenderer.cpp
  45. 5 5
      AnKi/Renderer/MotionVectors.cpp
  46. 7 7
      AnKi/Renderer/ProbeReflections.cpp
  47. 1 1
      AnKi/Renderer/Renderer.cpp
  48. 4 4
      AnKi/Renderer/RendererObject.h
  49. 54 59
      AnKi/Renderer/RtShadows.cpp
  50. 10 10
      AnKi/Renderer/Scale.cpp
  51. 6 6
      AnKi/Renderer/ShadowMapping.cpp
  52. 13 12
      AnKi/Renderer/ShadowmapsResolve.cpp
  53. 11 11
      AnKi/Renderer/Sky.cpp
  54. 15 15
      AnKi/Renderer/Ssao.cpp
  55. 7 7
      AnKi/Renderer/Ssr.cpp
  56. 7 7
      AnKi/Renderer/TemporalAA.cpp
  57. 2 2
      AnKi/Renderer/Tonemapping.cpp
  58. 14 17
      AnKi/Renderer/Utils/Drawer.cpp
  59. 40 39
      AnKi/Renderer/Utils/GpuVisibility.cpp
  60. 10 8
      AnKi/Renderer/Utils/HzbGenerator.cpp
  61. 21 20
      AnKi/Renderer/Utils/TraditionalDeferredShading.cpp
  62. 3 3
      AnKi/Renderer/VolumetricFog.cpp
  63. 14 14
      AnKi/Renderer/VolumetricLightingAccumulation.cpp
  64. 6 6
      AnKi/Renderer/VrsSriGeneration.cpp
  65. 1 1
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp
  66. 20 0
      AnKi/ShaderCompiler/Dxc.cpp
  67. 6 0
      AnKi/ShaderCompiler/Dxc.h
  68. 95 67
      AnKi/ShaderCompiler/ShaderCompiler.cpp
  69. 1 0
      AnKi/ShaderCompiler/ShaderProgramBinary.xml
  70. 1 0
      AnKi/ShaderCompiler/ShaderProgramBinaryExtra.h
  71. 1 0
      AnKi/ShaderCompiler/ShaderProgramCompiler.cpp
  72. 1 0
      AnKi/ShaderCompiler/ShaderProgramCompiler.h
  73. 1 0
      AnKi/ShaderCompiler/ShaderProgramParser.cpp
  74. 1 0
      AnKi/ShaderCompiler/ShaderProgramParser.h
  75. 4 4
      AnKi/Shaders/ApplyIrradianceToReflection.ankiprog
  76. 5 6
      AnKi/Shaders/Blit.ankiprog
  77. 8 8
      AnKi/Shaders/Bloom.ankiprog
  78. 5 5
      AnKi/Shaders/BloomUpscale.ankiprog
  79. 5 5
      AnKi/Shaders/ClearTextureCompute.ankiprog
  80. 4 5
      AnKi/Shaders/ClusterBinning.ankiprog
  81. 3 3
      AnKi/Shaders/ClusterBinningPackVisibles.ankiprog
  82. 3 3
      AnKi/Shaders/ClusterBinningSetup.ankiprog
  83. 58 0
      AnKi/Shaders/Common.hlsl
  84. 8 8
      AnKi/Shaders/DbgBillboard.ankiprog
  85. 6 6
      AnKi/Shaders/DbgRenderables.ankiprog
  86. 5 5
      AnKi/Shaders/DepthAwareBlur.ankiprog
  87. 8 8
      AnKi/Shaders/DepthDownscale.ankiprog
  88. 6 6
      AnKi/Shaders/DownscaleBlur.ankiprog
  89. 0 123
      AnKi/Shaders/DrawerStats.ankiprog
  90. 11 12
      AnKi/Shaders/FinalComposite.ankiprog
  91. 1 1
      AnKi/Shaders/ForwardShadingGenericTransparent.ankiprog
  92. 3 3
      AnKi/Shaders/ForwardShadingParticles.ankiprog
  93. 4 4
      AnKi/Shaders/Fsr.ankiprog
  94. 12 14
      AnKi/Shaders/GBufferGeneric.ankiprog
  95. 9 11
      AnKi/Shaders/GBufferPost.ankiprog
  96. 6 6
      AnKi/Shaders/GpuParticlesSimulation.ankiprog
  97. 3 3
      AnKi/Shaders/GpuSceneMicroPatching.ankiprog
  98. 18 18
      AnKi/Shaders/GpuVisibility.ankiprog
  99. 9 9
      AnKi/Shaders/GpuVisibilityAccelerationStructures.ankiprog
  100. 2 2
      AnKi/Shaders/GpuVisibilityAccelerationStructuresZeroRemainingInstances.ankiprog

+ 2 - 2
AnKi/Core/CVarSet.cpp

@@ -62,7 +62,7 @@ Error CVarSet::setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineAr
 			{
 			{
 				if(foundCVar)
 				if(foundCVar)
 				{
 				{
-					ANKI_CORE_LOGW("Command line arg %s has ambiguous name", varName.cstr());
+					ANKI_CORE_LOGE("Command line arg %s has ambiguous name. Skipping", varName.cstr());
 				}
 				}
 				else
 				else
 				{
 				{
@@ -118,7 +118,7 @@ Error CVarSet::setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineAr
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_CORE_LOGW("Can't recognize command line argument: %s. Skipping", varName.cstr());
+			ANKI_CORE_LOGE("Can't recognize command line argument: %s. Skipping", varName.cstr());
 		}
 		}
 	}
 	}
 
 

+ 3 - 3
AnKi/Core/GpuMemory/GpuSceneBuffer.cpp

@@ -137,9 +137,9 @@ void GpuSceneMicroPatcher::patchGpuScene(CommandBuffer& cmdb)
 	const RebarAllocation dataToken = RebarTransientMemoryPool::getSingleton().allocateFrame(m_crntFramePatchData.getSizeInBytes(), mapped);
 	const RebarAllocation dataToken = RebarTransientMemoryPool::getSingleton().allocateFrame(m_crntFramePatchData.getSizeInBytes(), mapped);
 	memcpy(mapped, &m_crntFramePatchData[0], m_crntFramePatchData.getSizeInBytes());
 	memcpy(mapped, &m_crntFramePatchData[0], m_crntFramePatchData.getSizeInBytes());
 
 
-	cmdb.bindStorageBuffer(0, 0, headersToken);
-	cmdb.bindStorageBuffer(0, 1, dataToken);
-	cmdb.bindStorageBuffer(0, 2, BufferView(&GpuSceneBuffer::getSingleton().getBuffer()));
+	cmdb.bindStorageBuffer(ANKI_REG(t0), headersToken);
+	cmdb.bindStorageBuffer(ANKI_REG(t1), dataToken);
+	cmdb.bindStorageBuffer(ANKI_REG(u0), BufferView(&GpuSceneBuffer::getSingleton().getBuffer()));
 
 
 	cmdb.bindShaderProgram(m_grProgram.get());
 	cmdb.bindShaderProgram(m_grProgram.get());
 
 

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

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

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

@@ -6,10 +6,13 @@
 #pragma once
 #pragma once
 
 
 #include <AnKi/Gr/Common.h>
 #include <AnKi/Gr/Common.h>
+#include <AnKi/Core/CVarSet.h>
 
 
 namespace anki {
 namespace anki {
 
 
 /// There is no need to ask for a fence or a semaphore to be waited for more than 10 seconds. The GPU will timeout anyway.
 /// There is no need to ask for a fence or a semaphore to be waited for more than 10 seconds. The GPU will timeout anyway.
 constexpr Second kMaxFenceOrSemaphoreWaitTime = 10.0;
 constexpr Second kMaxFenceOrSemaphoreWaitTime = 10.0;
 
 
+extern NumericCVar<U32> g_maxBindlessSampledTextureCountCVar;
+
 } // end namespace anki
 } // end namespace anki

+ 0 - 79
AnKi/Gr/BackendCommon/Functions.cpp

@@ -137,83 +137,4 @@ void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlo
 	}
 	}
 }
 }
 
 
-Error linkShaderReflection(const ShaderReflection& a, const ShaderReflection& b, ShaderReflection& c_)
-{
-	ShaderReflection c;
-
-#if ANKI_GR_BACKEND_VULKAN
-	c.m_descriptorSetMask = a.m_descriptorSetMask | b.m_descriptorSetMask;
-
-	for(U32 set = 0; set < kMaxDescriptorSets; ++set)
-	{
-		if(!c.m_descriptorSetMask.get(set))
-		{
-			continue;
-		}
-
-		for(U32 binding = 0; binding < kMaxBindingsPerDescriptorSet; ++binding)
-		{
-			const Bool bindingExists = a.m_descriptorArraySizes[set][binding] > 0 || b.m_descriptorArraySizes[set][binding] > 0;
-			if(!bindingExists)
-			{
-				continue;
-			}
-
-			const Bool sizeCorrect = a.m_descriptorArraySizes[set][binding] == 0 || b.m_descriptorArraySizes[set][binding] == 0
-									 || a.m_descriptorArraySizes[set][binding] == b.m_descriptorArraySizes[set][binding];
-
-			if(!sizeCorrect)
-			{
-				ANKI_GR_LOGE("Can't link shader reflection because of different array size. Set %u binding %u", set, binding);
-				return Error::kFunctionFailed;
-			}
-
-			const Bool typeCorrect = a.m_descriptorTypes[set][binding] == DescriptorType::kCount
-									 || b.m_descriptorTypes[set][binding] == DescriptorType::kCount
-									 || a.m_descriptorTypes[set][binding] == b.m_descriptorTypes[set][binding];
-
-			if(!typeCorrect)
-			{
-				ANKI_GR_LOGE("Can't link shader reflection because of different array size. Set %u binding %u", set, binding);
-				return Error::kFunctionFailed;
-			}
-
-			const Bool flagsCorrect = a.m_descriptorFlags[set][binding] == DescriptorFlag::kNone
-									  || b.m_descriptorFlags[set][binding] == DescriptorFlag::kNone
-									  || a.m_descriptorFlags[set][binding] == b.m_descriptorFlags[set][binding];
-			if(!flagsCorrect)
-			{
-				ANKI_GR_LOGE("Can't link shader reflection because of different discriptor flags. Set %u binding %u", set, binding);
-				return Error::kFunctionFailed;
-			}
-
-			c.m_descriptorArraySizes[set][binding] = max(a.m_descriptorArraySizes[set][binding], b.m_descriptorArraySizes[set][binding]);
-			c.m_descriptorTypes[set][binding] = min(a.m_descriptorTypes[set][binding], b.m_descriptorTypes[set][binding]);
-			c.m_descriptorFlags[set][binding] = max(a.m_descriptorFlags[set][binding], b.m_descriptorFlags[set][binding]);
-		}
-	}
-#endif
-
-	c.m_vertex.m_vertexAttributeLocations =
-		(a.m_vertex.m_vertexAttributeMask.getAnySet()) ? a.m_vertex.m_vertexAttributeLocations : b.m_vertex.m_vertexAttributeLocations;
-	c.m_vertex.m_vertexAttributeMask = a.m_vertex.m_vertexAttributeMask | b.m_vertex.m_vertexAttributeMask;
-
-	c.m_fragment.m_colorAttachmentWritemask = a.m_fragment.m_colorAttachmentWritemask | b.m_fragment.m_colorAttachmentWritemask;
-
-	const Bool pushConstantsCorrect = a.m_descriptor.m_pushConstantsSize == 0 || b.m_descriptor.m_pushConstantsSize == 0
-									  || a.m_descriptor.m_pushConstantsSize == b.m_descriptor.m_pushConstantsSize;
-	if(!pushConstantsCorrect)
-	{
-		ANKI_GR_LOGE("Can't link shader reflection because of different push constants size");
-		return Error::kFunctionFailed;
-	}
-
-	c.m_descriptor.m_pushConstantsSize = max(a.m_descriptor.m_pushConstantsSize, b.m_descriptor.m_pushConstantsSize);
-
-	c.m_fragment.m_discards = a.m_fragment.m_discards || b.m_fragment.m_discards;
-
-	c_ = c;
-	return Error::kNone;
-}
-
 } // end namespace anki
 } // end namespace anki

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

@@ -44,7 +44,4 @@ ShaderVariableDataType getShaderVariableTypeFromTypename();
 void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo, const void* elements, U32 elementsCount,
 void writeShaderBlockMemory(ShaderVariableDataType type, const ShaderVariableBlockInfo& varBlkInfo, const void* elements, U32 elementsCount,
 							void* buffBegin, const void* buffEnd);
 							void* buffBegin, const void* buffEnd);
 
 
-/// Combine shader reflection.
-Error linkShaderReflection(const ShaderReflection& a, const ShaderReflection& b, ShaderReflection& c);
-
 } // end namespace anki
 } // end namespace anki

+ 1 - 0
AnKi/Gr/CMakeLists.txt

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

+ 10 - 27
AnKi/Gr/CommandBuffer.h

@@ -101,6 +101,14 @@ public:
 	HlslResourceType m_resourceType = HlslResourceType::kCount;
 	HlslResourceType m_resourceType = HlslResourceType::kCount;
 	U8 m_space = kMaxU8;
 	U8 m_space = kMaxU8;
 
 
+	Register(HlslResourceType type, U32 bindingPoint, U8 space = 0)
+		: m_bindPoint(bindingPoint)
+		, m_resourceType(type)
+		, m_space(space)
+	{
+		validate();
+	}
+
 	/// Construct using a couple of strings like ("t0", "space10")
 	/// Construct using a couple of strings like ("t0", "space10")
 	Register(const Char* reg, const Char* space = "space0")
 	Register(const Char* reg, const Char* space = "space0")
 	{
 	{
@@ -254,48 +262,23 @@ public:
 	/// Set the line width. By default it's undefined.
 	/// Set the line width. By default it's undefined.
 	void setLineWidth(F32 lineWidth);
 	void setLineWidth(F32 lineWidth);
 
 
-	/// Bind sampler.
-	void bindSampler(U32 set, U32 binding, Sampler* sampler, U32 arrayIdx = 0);
-
 	/// Bind sampler.
 	/// Bind sampler.
 	void bindSampler(Register reg, Sampler* sampler);
 	void bindSampler(Register reg, Sampler* sampler);
 
 
-	/// Bind a texture.
-	void bindTexture(U32 set, U32 binding, const TextureView& texView, U32 arrayIdx = 0);
-
 	/// Bind a texture.
 	/// Bind a texture.
 	void bindTexture(Register reg, const TextureView& texView);
 	void bindTexture(Register reg, const TextureView& texView);
 
 
-	/// Bind uniform buffer.
-	void bindUniformBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx = 0);
-
 	/// Bind uniform buffer.
 	/// Bind uniform buffer.
 	void bindUniformBuffer(Register reg, const BufferView& buff);
 	void bindUniformBuffer(Register reg, const BufferView& buff);
 
 
-	/// Bind storage buffer.
-	void bindStorageBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx = 0);
-
 	/// Bind storage buffer.
 	/// Bind storage buffer.
 	void bindStorageBuffer(Register reg, const BufferView& buff);
 	void bindStorageBuffer(Register reg, const BufferView& buff);
 
 
-	/// Bind load/store image.
-	void bindStorageTexture(U32 set, U32 binding, const TextureView& texView, U32 arrayIdx = 0);
-
-	/// Bind texture buffer.
-	void bindReadOnlyTexelBuffer(U32 set, U32 binding, const BufferView& buff, Format fmt, U32 arrayIdx = 0);
-
 	/// Bind texel buffer.
 	/// Bind texel buffer.
 	void bindTexelBuffer(Register reg, const BufferView& buff, Format fmt);
 	void bindTexelBuffer(Register reg, const BufferView& buff, Format fmt);
 
 
-	/// Bind an acceleration structure.
-	/// @param set The set to bind to.
-	/// @param binding The binding to bind to.
-	/// @param[in,out] as The AS to bind.
-	/// @param arrayIdx The array index if the binding is an array.
-	void bindAccelerationStructure(U32 set, U32 binding, AccelerationStructure* as, U32 arrayIdx = 0);
-
-	/// Bind the bindless descriptor set into a slot.
-	void bindAllBindless(U32 set);
+	/// Bind AS.
+	void bindAccelerationStructure(Register reg, AccelerationStructure* as);
 
 
 	/// Set push constants.
 	/// Set push constants.
 	void setPushConstants(const void* data, U32 dataSize);
 	void setPushConstants(const void* data, U32 dataSize);

+ 43 - 20
AnKi/Gr/Common.cpp

@@ -123,39 +123,62 @@ U32 computeMaxMipmapCount3d(U32 w, U32 h, U32 d, U32 minSizeOfLastMip)
 	return count;
 	return count;
 }
 }
 
 
-#if ANKI_ASSERTIONS_ENABLED
-void ShaderReflection::validate() const
+Error ShaderReflection::linkShaderReflection(const ShaderReflection& a, const ShaderReflection& b, ShaderReflection& c_)
 {
 {
-#	if ANKI_GR_BACKEND_VULKAN
+	ShaderReflection c;
+
+	memcpy(&c.m_descriptor, &a.m_descriptor, sizeof(a.m_descriptor));
 	for(U32 set = 0; set < kMaxDescriptorSets; ++set)
 	for(U32 set = 0; set < kMaxDescriptorSets; ++set)
 	{
 	{
-		const Bool setExists = m_descriptorSetMask.get(set);
-		for(U32 binding = 0; binding < kMaxBindingsPerDescriptorSet; ++binding)
+		for(U32 binding = 0; binding < b.m_descriptor.m_bindingCounts[set]; ++binding)
 		{
 		{
-			const U32 arraySize = m_descriptorArraySizes[set][binding];
-			const DescriptorType type = m_descriptorTypes[set][binding];
-
-			if(!setExists)
+			// Search for the binding in a
+			const ShaderReflectionBinding& bbinding = b.m_descriptor.m_bindings[set][binding];
+			Bool bindingFoundOnA = false;
+			for(U32 binding2 = 0; binding2 < a.m_descriptor.m_bindingCounts[set]; ++binding2)
 			{
 			{
-				ANKI_ASSERT(arraySize == 0 && type == DescriptorType::kCount);
+				const ShaderReflectionBinding& abinding = a.m_descriptor.m_bindings[set][binding2];
+
+				if(abinding.m_registerBindingPoint == bbinding.m_registerBindingPoint
+				   && descriptorTypeToHlslResourceType(abinding.m_type, abinding.m_flags)
+						  == descriptorTypeToHlslResourceType(bbinding.m_type, bbinding.m_flags))
+				{
+					if(abinding != bbinding)
+					{
+						ANKI_GR_LOGE("Can't link shader reflection because of different bindings. Set %u binding %u", set, binding);
+						return Error::kFunctionFailed;
+					}
+					bindingFoundOnA = true;
+					break;
+				}
 			}
 			}
-			else if(arraySize != 0)
-			{
-				ANKI_ASSERT(type != DescriptorType::kCount);
-			}
-			else if(type != DescriptorType::kCount)
+
+			if(!bindingFoundOnA)
 			{
 			{
-				ANKI_ASSERT(arraySize > 0);
+				c.m_descriptor.m_bindings[set][c.m_descriptor.m_bindingCounts[set]++] = bbinding;
 			}
 			}
 		}
 		}
 	}
 	}
-#	endif
 
 
-	for(VertexAttributeSemantic semantic : EnumIterable<VertexAttributeSemantic>())
+	if(a.m_descriptor.m_pushConstantsSize != 0 && b.m_descriptor.m_pushConstantsSize != 0
+	   && a.m_descriptor.m_pushConstantsSize != b.m_descriptor.m_pushConstantsSize)
 	{
 	{
-		ANKI_ASSERT(!m_vertex.m_vertexAttributeMask.get(semantic) || m_vertex.m_vertexAttributeLocations[semantic] != kMaxU8);
+		ANKI_GR_LOGE("Can't link shader reflection because push constant size doesn't match");
+		return Error::kFunctionFailed;
 	}
 	}
+	c.m_descriptor.m_pushConstantsSize = max(a.m_descriptor.m_pushConstantsSize, b.m_descriptor.m_pushConstantsSize);
+
+	c.m_descriptor.m_hasVkBindlessDescriptorSet = a.m_descriptor.m_hasVkBindlessDescriptorSet || b.m_descriptor.m_hasVkBindlessDescriptorSet;
+
+	c.m_vertex.m_vertexAttributeLocations =
+		(a.m_vertex.m_vertexAttributeMask.getAnySet()) ? a.m_vertex.m_vertexAttributeLocations : b.m_vertex.m_vertexAttributeLocations;
+	c.m_vertex.m_vertexAttributeMask = a.m_vertex.m_vertexAttributeMask | b.m_vertex.m_vertexAttributeMask;
+
+	c.m_fragment.m_colorAttachmentWritemask = a.m_fragment.m_colorAttachmentWritemask | b.m_fragment.m_colorAttachmentWritemask;
+	c.m_fragment.m_discards = a.m_fragment.m_discards || b.m_fragment.m_discards;
+
+	c_ = c;
+	return Error::kNone;
 }
 }
-#endif
 
 
 } // end namespace anki
 } // end namespace anki

+ 73 - 44
AnKi/Gr/Common.h

@@ -931,11 +931,13 @@ class ShaderReflectionBinding
 public:
 public:
 	U32 m_registerBindingPoint = kMaxU32;
 	U32 m_registerBindingPoint = kMaxU32;
 	U16 m_arraySize = 0;
 	U16 m_arraySize = 0;
+
 	union
 	union
 	{
 	{
-		U16 m_vkBinding = kMaxU16;
+		U16 m_vkBinding = kMaxU16; ///< Filled by the VK backend.
 		U16 m_d3dStructuredBufferStride;
 		U16 m_d3dStructuredBufferStride;
 	};
 	};
+
 	DescriptorType m_type = DescriptorType::kCount;
 	DescriptorType m_type = DescriptorType::kCount;
 	DescriptorFlag m_flags = DescriptorFlag::kNone;
 	DescriptorFlag m_flags = DescriptorFlag::kNone;
 
 
@@ -955,48 +957,66 @@ public:
 
 
 		ANKI_LESS(m_registerBindingPoint)
 		ANKI_LESS(m_registerBindingPoint)
 		ANKI_LESS(m_arraySize)
 		ANKI_LESS(m_arraySize)
-		ANKI_LESS(m_vkBinding)
+		ANKI_LESS(m_d3dStructuredBufferStride)
 #undef ANKI_LESS
 #undef ANKI_LESS
 		return false;
 		return false;
 	}
 	}
 
 
+	Bool operator==(const ShaderReflectionBinding& b) const
+	{
+		return memcmp(this, &b, sizeof(*this)) == 0;
+	}
+
 	void validate() const
 	void validate() const
 	{
 	{
 		ANKI_ASSERT(m_registerBindingPoint < kMaxU32);
 		ANKI_ASSERT(m_registerBindingPoint < kMaxU32);
 		ANKI_ASSERT(m_type < DescriptorType::kCount);
 		ANKI_ASSERT(m_type < DescriptorType::kCount);
 		ANKI_ASSERT(m_flags != DescriptorFlag::kNone);
 		ANKI_ASSERT(m_flags != DescriptorFlag::kNone);
 		ANKI_ASSERT(m_arraySize > 0);
 		ANKI_ASSERT(m_arraySize > 0);
-		ANKI_ASSERT(ANKI_GR_BACKEND_DIRECT3D || m_vkBinding != kMaxU16);
+		ANKI_ASSERT(ANKI_GR_BACKEND_VULKAN || m_type != DescriptorType::kStorageBuffer || m_d3dStructuredBufferStride != 0);
 	}
 	}
 };
 };
 ANKI_END_PACKED_STRUCT
 ANKI_END_PACKED_STRUCT
 
 
-class ShaderReflection
+ANKI_BEGIN_PACKED_STRUCT
+class ShaderReflectionDescriptorRelated
 {
 {
 public:
 public:
-#if ANKI_GR_BACKEND_VULKAN
-	// !!OLD!!
-	Array2d<U16, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> m_descriptorArraySizes;
-	Array2d<DescriptorType, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> m_descriptorTypes;
-	Array2d<DescriptorFlag, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> m_descriptorFlags;
-	BitSet<kMaxDescriptorSets, U8> m_descriptorSetMask = {false};
-#endif
+	Array2d<ShaderReflectionBinding, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> m_bindings;
+	Array<U8, kMaxDescriptorSets> m_bindingCounts = {};
 
 
-	// !!NEW!!
-	ANKI_BEGIN_PACKED_STRUCT
-	class DescriptorRelated
-	{
-	public:
-		Array2d<ShaderReflectionBinding, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> m_bindings;
-		Array<U8, kMaxDescriptorSets> m_bindingCounts = {};
+	U32 m_pushConstantsSize = 0;
 
 
-		U32 m_pushConstantsSize = 0;
+	Bool m_hasVkBindlessDescriptorSet = false; ///< Filled by the shader compiler.
+	U8 m_vkBindlessDescriptorSet = kMaxU8; ///< Filled by the VK backend.
 
 
-		U8 m_vkBindlessDescriptorSet = kMaxDescriptorSets;
-	};
-	ANKI_END_PACKED_STRUCT
+	void validate() const
+	{
+		for(U32 set = 0; set < kMaxDescriptorSets; ++set)
+		{
+			for(U32 ibinding = 0; ibinding < kMaxBindingsPerDescriptorSet; ++ibinding)
+			{
+				const ShaderReflectionBinding& binding = m_bindings[set][ibinding];
+
+				if(binding.m_type != DescriptorType::kCount)
+				{
+					ANKI_ASSERT(ibinding < m_bindingCounts[set]);
+					binding.validate();
+				}
+				else
+				{
+					ANKI_ASSERT(ibinding >= m_bindingCounts[set]);
+				}
+			}
+		}
+	}
+};
+ANKI_END_PACKED_STRUCT
 
 
-	DescriptorRelated m_descriptor;
+class ShaderReflection
+{
+public:
+	ShaderReflectionDescriptorRelated m_descriptor;
 
 
 	class
 	class
 	{
 	{
@@ -1015,33 +1035,20 @@ public:
 
 
 	ShaderReflection()
 	ShaderReflection()
 	{
 	{
-#if ANKI_GR_BACKEND_VULKAN
-		for(auto& it : m_descriptorArraySizes)
-		{
-			it.fill(0);
-		}
-
-		for(auto& it : m_descriptorTypes)
-		{
-			it.fill(DescriptorType::kCount);
-		}
-
-		for(auto& it : m_descriptorFlags)
-		{
-			it.fill(DescriptorFlag::kNone);
-		}
-#endif
-
 		m_vertex.m_vertexAttributeLocations.fill(kMaxU8);
 		m_vertex.m_vertexAttributeLocations.fill(kMaxU8);
 	}
 	}
 
 
-#if ANKI_ASSERTIONS_ENABLED
-	void validate() const;
-#else
 	void validate() const
 	void validate() const
 	{
 	{
+		m_descriptor.validate();
+		for(VertexAttributeSemantic semantic : EnumIterable<VertexAttributeSemantic>())
+		{
+			ANKI_ASSERT(!m_vertex.m_vertexAttributeMask.get(semantic) || m_vertex.m_vertexAttributeLocations[semantic] != kMaxU8);
+		}
 	}
 	}
-#endif
+
+	/// Combine shader reflection.
+	static Error linkShaderReflection(const ShaderReflection& a, const ShaderReflection& b, ShaderReflection& c);
 };
 };
 
 
 /// Clear values for textures or attachments.
 /// Clear values for textures or attachments.
@@ -1086,6 +1093,28 @@ U32 computeMaxMipmapCount2d(U32 w, U32 h, U32 minSizeOfLastMip = 1);
 
 
 /// Compute max number of mipmaps for a 3D texture.
 /// Compute max number of mipmaps for a 3D texture.
 U32 computeMaxMipmapCount3d(U32 w, U32 h, U32 d, U32 minSizeOfLastMip = 1);
 U32 computeMaxMipmapCount3d(U32 w, U32 h, U32 d, U32 minSizeOfLastMip = 1);
+
+/// Visit a SPIR-V binary.
+template<template<typename> typename TArray, typename TFunc>
+static void visitSpirv(TArray<U32> spv, TFunc func)
+{
+	ANKI_ASSERT(spv.getSize() > 5);
+
+	auto it = &spv[5];
+	do
+	{
+		const U32 instructionCount = *it >> 16u;
+		const U32 opcode = *it & 0xFFFFu;
+
+		TArray<U32> instructions(it + 1, instructionCount - 1);
+
+		func(opcode, instructions);
+
+		it += instructionCount;
+	} while(it < spv.getEnd());
+
+	ANKI_ASSERT(it == spv.getEnd());
+}
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

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

@@ -132,11 +132,6 @@ void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, Bl
 	ANKI_ASSERT(!"TODO");
 	ANKI_ASSERT(!"TODO");
 }
 }
 
 
-void CommandBuffer::bindTexture(U32 set, U32 binding, const TextureView& texView, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
 void CommandBuffer::bindTexture(Register reg, const TextureView& texView)
 void CommandBuffer::bindTexture(Register reg, const TextureView& texView)
 {
 {
 	reg.validate();
 	reg.validate();
@@ -156,11 +151,6 @@ void CommandBuffer::bindTexture(Register reg, const TextureView& texView)
 	}
 	}
 }
 }
 
 
-void CommandBuffer::bindSampler(U32 set, U32 binding, Sampler* sampler, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
 void CommandBuffer::bindSampler(Register reg, Sampler* sampler)
 void CommandBuffer::bindSampler(Register reg, Sampler* sampler)
 {
 {
 	reg.validate();
 	reg.validate();
@@ -173,11 +163,6 @@ void CommandBuffer::bindSampler(Register reg, Sampler* sampler)
 	self.m_mcmdb->pushObjectRef(sampler);
 	self.m_mcmdb->pushObjectRef(sampler);
 }
 }
 
 
-void CommandBuffer::bindUniformBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
 void CommandBuffer::bindUniformBuffer(Register reg, const BufferView& buff)
 void CommandBuffer::bindUniformBuffer(Register reg, const BufferView& buff)
 {
 {
 	reg.validate();
 	reg.validate();
@@ -187,11 +172,6 @@ void CommandBuffer::bindUniformBuffer(Register reg, const BufferView& buff)
 	self.m_descriptors.bindCbv(reg.m_space, reg.m_bindPoint, &impl.getD3DResource(), buff.getOffset(), buff.getRange());
 	self.m_descriptors.bindCbv(reg.m_space, reg.m_bindPoint, &impl.getD3DResource(), buff.getOffset(), buff.getRange());
 }
 }
 
 
-void CommandBuffer::bindStorageBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
 void CommandBuffer::bindStorageBuffer(Register reg, const BufferView& buff)
 void CommandBuffer::bindStorageBuffer(Register reg, const BufferView& buff)
 {
 {
 	reg.validate();
 	reg.validate();
@@ -209,21 +189,6 @@ void CommandBuffer::bindStorageBuffer(Register reg, const BufferView& buff)
 	}
 	}
 }
 }
 
 
-void CommandBuffer::bindStorageTexture(U32 set, U32 binding, const TextureView& tex, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
-void CommandBuffer::bindAccelerationStructure(U32 set, U32 binding, AccelerationStructure* as, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
-void CommandBuffer::bindReadOnlyTexelBuffer(U32 set, U32 binding, const BufferView& buff, Format fmt, U32 arrayIdx)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
 void CommandBuffer::bindTexelBuffer(Register reg, const BufferView& buff, Format fmt)
 void CommandBuffer::bindTexelBuffer(Register reg, const BufferView& buff, Format fmt)
 {
 {
 	reg.validate();
 	reg.validate();
@@ -241,7 +206,7 @@ void CommandBuffer::bindTexelBuffer(Register reg, const BufferView& buff, Format
 	}
 	}
 }
 }
 
 
-void CommandBuffer::bindAllBindless(U32 set)
+void CommandBuffer::bindAccelerationStructure(Register reg, AccelerationStructure* as)
 {
 {
 	ANKI_ASSERT(!"TODO");
 	ANKI_ASSERT(!"TODO");
 }
 }

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

@@ -73,7 +73,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_CHECK(linkShaderReflection(refl, simpl.m_reflection, refl));
+			ANKI_CHECK(ShaderReflection::linkShaderReflection(refl, simpl.m_reflection, refl));
 		}
 		}
 
 
 		refl.validate();
 		refl.validate();

+ 9 - 30
AnKi/Gr/RenderGraph.h

@@ -133,63 +133,42 @@ public:
 	}
 	}
 
 
 	/// Convenience method.
 	/// Convenience method.
-	void bindTexture(U32 set, U32 binding, RenderTargetHandle handle, const TextureSubresourceDescriptor& subresource)
+	void bindTexture(Register reg, RenderTargetHandle handle, const TextureSubresourceDescriptor& subresource)
 	{
 	{
 		Texture* tex;
 		Texture* tex;
 		getRenderTargetState(handle, subresource, tex);
 		getRenderTargetState(handle, subresource, tex);
-		m_commandBuffer->bindTexture(set, binding, TextureView(tex, subresource));
+		m_commandBuffer->bindTexture(reg, TextureView(tex, subresource));
 	}
 	}
 
 
 	/// Convenience method to bind the whole texture.
 	/// Convenience method to bind the whole texture.
-	void bindTexture(U32 set, U32 binding, RenderTargetHandle handle, U32 arrayIdx = 0)
+	void bindTexture(Register reg, RenderTargetHandle handle)
 	{
 	{
 		const TextureSubresourceDescriptor subresource = TextureSubresourceDescriptor::all();
 		const TextureSubresourceDescriptor subresource = TextureSubresourceDescriptor::all();
 		Texture* tex;
 		Texture* tex;
 		getRenderTargetState(handle, subresource, tex); // Doesn't care about the aspect so it's OK
 		getRenderTargetState(handle, subresource, tex); // Doesn't care about the aspect so it's OK
-		m_commandBuffer->bindTexture(set, binding, TextureView(tex, subresource), arrayIdx);
+		m_commandBuffer->bindTexture(reg, TextureView(tex, subresource));
 	}
 	}
 
 
 	/// Convenience method.
 	/// Convenience method.
-	void bindStorageTexture(U32 set, U32 binding, RenderTargetHandle handle, const TextureSubresourceDescriptor& subresource, U32 arrayIdx = 0)
-	{
-		Texture* tex;
-		getRenderTargetState(handle, subresource, tex);
-		m_commandBuffer->bindStorageTexture(set, binding, TextureView(tex, subresource), arrayIdx);
-	}
-
-	/// Convenience method to bind the whole image.
-	void bindStorageTexture(U32 set, U32 binding, RenderTargetHandle handle, U32 arrayIdx = 0)
-	{
-		Texture* tex;
-#if ANKI_ASSERTIONS_ENABLED
-		tex = &getTexture(handle);
-		ANKI_ASSERT(tex->getLayerCount() == 1 && tex->getMipmapCount() == 1 && tex->getDepthStencilAspect() == DepthStencilAspectBit::kNone);
-#endif
-		const TextureSubresourceDescriptor subresource = TextureSubresourceDescriptor::all();
-		getRenderTargetState(handle, subresource, tex);
-		m_commandBuffer->bindStorageTexture(set, binding, TextureView(tex, subresource), arrayIdx);
-	}
-
-	/// Convenience method.
-	void bindStorageBuffer(U32 set, U32 binding, BufferHandle handle)
+	void bindStorageBuffer(Register reg, BufferHandle handle)
 	{
 	{
 		Buffer* buff;
 		Buffer* buff;
 		PtrSize offset, range;
 		PtrSize offset, range;
 		getBufferState(handle, buff, offset, range);
 		getBufferState(handle, buff, offset, range);
-		m_commandBuffer->bindStorageBuffer(set, binding, BufferView(buff, offset, range));
+		m_commandBuffer->bindStorageBuffer(reg, BufferView(buff, offset, range));
 	}
 	}
 
 
 	/// Convenience method.
 	/// Convenience method.
-	void bindUniformBuffer(U32 set, U32 binding, BufferHandle handle)
+	void bindUniformBuffer(Register reg, BufferHandle handle)
 	{
 	{
 		Buffer* buff;
 		Buffer* buff;
 		PtrSize offset, range;
 		PtrSize offset, range;
 		getBufferState(handle, buff, offset, range);
 		getBufferState(handle, buff, offset, range);
-		m_commandBuffer->bindUniformBuffer(set, binding, BufferView(buff, offset, range));
+		m_commandBuffer->bindUniformBuffer(reg, BufferView(buff, offset, range));
 	}
 	}
 
 
 	/// Convenience method.
 	/// Convenience method.
-	void bindAccelerationStructure(U32 set, U32 binding, AccelerationStructureHandle handle);
+	void bindAccelerationStructure(Register reg, AccelerationStructureHandle handle);
 
 
 private:
 private:
 	const RenderGraph* m_rgraph ANKI_DEBUG_CODE(= nullptr);
 	const RenderGraph* m_rgraph ANKI_DEBUG_CODE(= nullptr);

+ 2 - 2
AnKi/Gr/RenderGraph.inl.h

@@ -7,9 +7,9 @@
 
 
 namespace anki {
 namespace anki {
 
 
-inline void RenderPassWorkContext::bindAccelerationStructure(U32 set, U32 binding, AccelerationStructureHandle handle)
+inline void RenderPassWorkContext::bindAccelerationStructure(Register reg, AccelerationStructureHandle handle)
 {
 {
-	m_commandBuffer->bindAccelerationStructure(set, binding, m_rgraph->getAs(handle));
+	m_commandBuffer->bindAccelerationStructure(reg, m_rgraph->getAs(handle));
 }
 }
 
 
 inline void RenderPassWorkContext::getBufferState(BufferHandle handle, Buffer*& buff, PtrSize& offset, PtrSize& range) const
 inline void RenderPassWorkContext::getBufferState(BufferHandle handle, Buffer*& buff, PtrSize& offset, PtrSize& range) const

+ 7 - 3
AnKi/Gr/Shader.h

@@ -65,9 +65,6 @@ public:
 
 
 	ShaderReflection m_reflection;
 	ShaderReflection m_reflection;
 
 
-	/// @note It's OK to have entries in that array with consts that do not appear in the shader.
-	ConstWeakArray<ShaderSpecializationConstValue> m_constValues;
-
 	ShaderInitInfo()
 	ShaderInitInfo()
 	{
 	{
 	}
 	}
@@ -83,6 +80,13 @@ public:
 		, m_binary(bin)
 		, m_binary(bin)
 	{
 	{
 	}
 	}
+
+	void validate() const
+	{
+		ANKI_ASSERT(m_shaderType != ShaderType::kCount);
+		ANKI_ASSERT(m_binary.getSize() > 0);
+		m_reflection.validate();
+	}
 };
 };
 
 
 /// GPU shader.
 /// GPU shader.

+ 70 - 123
AnKi/Gr/Vulkan/VkCommandBuffer.cpp

@@ -10,6 +10,8 @@
 #include <AnKi/Gr/Vulkan/VkGrUpscaler.h>
 #include <AnKi/Gr/Vulkan/VkGrUpscaler.h>
 #include <AnKi/Gr/Vulkan/VkOcclusionQuery.h>
 #include <AnKi/Gr/Vulkan/VkOcclusionQuery.h>
 #include <AnKi/Gr/Vulkan/VkTimestampQuery.h>
 #include <AnKi/Gr/Vulkan/VkTimestampQuery.h>
+#include <AnKi/Gr/Vulkan/VkSampler.h>
+#include <AnKi/Gr/Vulkan/VkAccelerationStructure.h>
 
 
 #if ANKI_DLSS
 #if ANKI_DLSS
 #	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx.h>
 #	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx.h>
@@ -263,108 +265,106 @@ void CommandBuffer::setBlendOperation(U32 attachment, BlendOperation funcRgb, Bl
 	self.m_state.setBlendOperation(attachment, funcRgb, funcA);
 	self.m_state.setBlendOperation(attachment, funcRgb, funcA);
 }
 }
 
 
-void CommandBuffer::bindTexture(U32 set, U32 binding, const TextureView& texView, U32 arrayIdx)
+void CommandBuffer::bindTexture(Register reg, const TextureView& texView)
 {
 {
-	ANKI_ASSERT(texView.isGoodForSampling());
-
+	reg.validate();
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
 
 
 	const TextureImpl& tex = static_cast<const TextureImpl&>(texView.getTexture());
 	const TextureImpl& tex = static_cast<const TextureImpl&>(texView.getTexture());
-	const VkImageLayout lay = tex.computeLayout(TextureUsageBit::kAllSampled & tex.getTextureUsage(), 0);
 
 
-	self.m_dsetState[set].bindTexture(binding, arrayIdx, tex.getImageView(texView.getSubresource()), lay);
-}
+	if(reg.m_resourceType == HlslResourceType::kSrv)
+	{
+		ANKI_ASSERT(texView.isGoodForSampling());
+		const VkImageLayout lay = tex.computeLayout(TextureUsageBit::kAllSampled & tex.getTextureUsage(), 0);
+		self.m_descriptorState.bindSampledTexture(reg.m_space, reg.m_bindPoint, tex.getImageView(texView.getSubresource()), lay);
+	}
+	else
+	{
+		ANKI_ASSERT(texView.isGoodForStorage());
+		self.m_descriptorState.bindStorageTexture(reg.m_space, reg.m_bindPoint, tex.getImageView(texView.getSubresource()));
 
 
-void CommandBuffer::bindTexture([[maybe_unused]] Register reg, [[maybe_unused]] const TextureView& texView)
-{
-	ANKI_ASSERT(!"TODO");
+		const Bool isPresentable = !!(tex.getTextureUsage() & TextureUsageBit::kPresent);
+		if(isPresentable)
+		{
+			self.m_renderedToDefaultFb = true;
+		}
+	}
 }
 }
 
 
-void CommandBuffer::bindSampler(U32 set, U32 binding, Sampler* sampler, U32 arrayIdx)
+void CommandBuffer::bindSampler(Register reg, Sampler* sampler)
 {
 {
+	reg.validate();
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
-	self.m_dsetState[set].bindSampler(binding, arrayIdx, sampler);
-	self.m_microCmdb->pushObjectRef(sampler);
-}
 
 
-void CommandBuffer::bindSampler([[maybe_unused]] Register reg, [[maybe_unused]] Sampler* sampler)
-{
-	ANKI_ASSERT(!"TODO");
+	const VkSampler handle = static_cast<const SamplerImpl&>(*sampler).m_sampler->getHandle();
+	self.m_descriptorState.bindSampler(reg.m_space, reg.m_bindPoint, handle);
+	self.m_microCmdb->pushObjectRef(sampler);
 }
 }
 
 
-void CommandBuffer::bindUniformBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx)
+void CommandBuffer::bindUniformBuffer(Register reg, const BufferView& buff)
 {
 {
+	reg.validate();
 	ANKI_ASSERT(buff.isValid());
 	ANKI_ASSERT(buff.isValid());
 
 
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
-	self.m_dsetState[set].bindUniformBuffer(binding, arrayIdx, &buff.getBuffer(), buff.getOffset(), buff.getRange());
-}
 
 
-void CommandBuffer::bindUniformBuffer([[maybe_unused]] Register reg, [[maybe_unused]] const BufferView& buff)
-{
-	ANKI_ASSERT(!"TODO");
+	const VkBuffer handle = static_cast<const BufferImpl&>(buff.getBuffer()).getHandle();
+	self.m_descriptorState.bindUniformBuffer(reg.m_space, reg.m_bindPoint, handle, buff.getOffset(), buff.getRange());
 }
 }
 
 
-void CommandBuffer::bindStorageBuffer(U32 set, U32 binding, const BufferView& buff, U32 arrayIdx)
+void CommandBuffer::bindStorageBuffer(Register reg, const BufferView& buff)
 {
 {
+	reg.validate();
 	ANKI_ASSERT(buff.isValid());
 	ANKI_ASSERT(buff.isValid());
 
 
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
-	self.m_dsetState[set].bindStorageBuffer(binding, arrayIdx, &buff.getBuffer(), buff.getOffset(), buff.getRange());
-}
-
-void CommandBuffer::bindStorageBuffer([[maybe_unused]] Register reg, [[maybe_unused]] const BufferView& buff)
-{
-	ANKI_ASSERT(!"TODO");
-}
-
-void CommandBuffer::bindStorageTexture(U32 set, U32 binding, const TextureView& view, U32 arrayIdx)
-{
-	ANKI_ASSERT(view.isGoodForStorage());
-	ANKI_VK_SELF(CommandBufferImpl);
-	self.commandCommon();
-
-	const TextureImpl& tex = static_cast<const TextureImpl&>(view.getTexture());
-	self.m_dsetState[set].bindStorageTexture(binding, arrayIdx, tex.getImageView(view.getSubresource()));
 
 
-	const Bool isPresentable = !!(tex.getTextureUsage() & TextureUsageBit::kPresent);
-	if(isPresentable)
+	const VkBuffer handle = static_cast<const BufferImpl&>(buff.getBuffer()).getHandle();
+	if(reg.m_resourceType == HlslResourceType::kSrv)
 	{
 	{
-		self.m_renderedToDefaultFb = true;
+		self.m_descriptorState.bindReadStorageBuffer(reg.m_space, reg.m_bindPoint, handle, buff.getOffset(), buff.getRange());
+	}
+	else
+	{
+		self.m_descriptorState.bindReadWriteStorageBuffer(reg.m_space, reg.m_bindPoint, handle, buff.getOffset(), buff.getRange());
 	}
 	}
 }
 }
 
 
-void CommandBuffer::bindAccelerationStructure(U32 set, U32 binding, AccelerationStructure* as, U32 arrayIdx)
+void CommandBuffer::bindAccelerationStructure(Register reg, AccelerationStructure* as)
 {
 {
+	reg.validate();
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
-	self.m_dsetState[set].bindAccelerationStructure(binding, arrayIdx, as);
+
+	const VkAccelerationStructureKHR& handle = static_cast<const AccelerationStructureImpl&>(*as).getHandle();
+	self.m_descriptorState.bindAccelerationStructure(reg.m_space, reg.m_bindPoint, &handle);
 	self.m_microCmdb->pushObjectRef(as);
 	self.m_microCmdb->pushObjectRef(as);
 }
 }
 
 
-void CommandBuffer::bindReadOnlyTexelBuffer(U32 set, U32 binding, const BufferView& buff, Format fmt, U32 arrayIdx)
+void CommandBuffer::bindTexelBuffer(Register reg, const BufferView& buff, Format fmt)
 {
 {
-	ANKI_ASSERT(buff.isValid());
+	reg.validate();
+	ANKI_ASSERT(fmt != Format::kNone);
+	reg.validate();
 
 
 	ANKI_VK_SELF(CommandBufferImpl);
 	ANKI_VK_SELF(CommandBufferImpl);
 	self.commandCommon();
 	self.commandCommon();
-	self.m_dsetState[set].bindReadOnlyTexelBuffer(binding, arrayIdx, &buff.getBuffer(), buff.getOffset(), buff.getRange(), fmt);
-}
 
 
-void CommandBuffer::bindTexelBuffer([[maybe_unused]] Register reg, [[maybe_unused]] const BufferView& buff, [[maybe_unused]] Format fmt)
-{
-	ANKI_ASSERT(!"TODO");
-}
+	const VkBufferView view = static_cast<const BufferImpl&>(buff.getBuffer()).getOrCreateBufferView(fmt, buff.getOffset(), buff.getRange());
 
 
-void CommandBuffer::bindAllBindless(U32 set)
-{
-	ANKI_VK_SELF(CommandBufferImpl);
-	self.commandCommon();
-	self.m_dsetState[set].bindBindlessDescriptorSet();
+	if(reg.m_resourceType == HlslResourceType::kSrv)
+	{
+		self.m_descriptorState.bindReadTexelBuffer(reg.m_space, reg.m_bindPoint, view);
+	}
+	else
+	{
+		ANKI_ASSERT(reg.m_resourceType == HlslResourceType::kUav);
+		self.m_descriptorState.bindReadWriteTexelBuffer(reg.m_space, reg.m_bindPoint, view);
+	}
 }
 }
 
 
 void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
@@ -373,6 +373,7 @@ void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 	self.commandCommon();
 	self.commandCommon();
 
 
 	ShaderProgramImpl& impl = static_cast<ShaderProgramImpl&>(*prog);
 	ShaderProgramImpl& impl = static_cast<ShaderProgramImpl&>(*prog);
+	VkPipelineBindPoint bindPoint;
 
 
 	if(impl.isGraphics())
 	if(impl.isGraphics())
 	{
 	{
@@ -380,6 +381,8 @@ void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 		self.m_computeProg = nullptr; // Unbind the compute prog. Doesn't work like vulkan
 		self.m_computeProg = nullptr; // Unbind the compute prog. Doesn't work like vulkan
 		self.m_rtProg = nullptr; // See above
 		self.m_rtProg = nullptr; // See above
 		self.m_state.bindShaderProgram(&impl);
 		self.m_state.bindShaderProgram(&impl);
+
+		bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
 	}
 	}
 	else if(!!(impl.getStages() & ShaderTypeBit::kCompute))
 	else if(!!(impl.getStages() & ShaderTypeBit::kCompute))
 	{
 	{
@@ -389,6 +392,8 @@ void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 
 
 		// Bind the pipeline now
 		// Bind the pipeline now
 		vkCmdBindPipeline(self.m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, impl.getComputePipelineHandle());
 		vkCmdBindPipeline(self.m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, impl.getComputePipelineHandle());
+
+		bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
 	}
 	}
 	else
 	else
 	{
 	{
@@ -399,27 +404,13 @@ void CommandBuffer::bindShaderProgram(ShaderProgram* prog)
 
 
 		// Bind now
 		// Bind now
 		vkCmdBindPipeline(self.m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, impl.getRayTracingPipelineHandle());
 		vkCmdBindPipeline(self.m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, impl.getRayTracingPipelineHandle());
-	}
 
 
-	for(U32 i = 0; i < kMaxDescriptorSets; ++i)
-	{
-		if(impl.getReflectionInfo().m_descriptorSetMask.get(i))
-		{
-			self.m_dsetState[i].setLayout(&impl.getDescriptorSetLayout(i));
-		}
-		else
-		{
-			// According to the spec the bound DS may be disturbed if the ppline layout is not compatible. Play it safe and dirty the slot. That will
-			// force rebind of the DS at drawcall time.
-			self.m_dsetState[i].setLayoutDirty();
-		}
+		bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
 	}
 	}
 
 
-	self.m_microCmdb->pushObjectRef(prog);
+	self.m_descriptorState.setPipelineLayout(&impl.getPipelineLayout(), bindPoint);
 
 
-#if ANKI_EXTRA_CHECKS
-	self.m_setPushConstantsSize = 0;
-#endif
+	self.m_microCmdb->pushObjectRef(prog);
 }
 }
 
 
 void CommandBuffer::beginRenderPass(ConstWeakArray<RenderTarget> colorRts, RenderTarget* depthStencilRt, U32 minx, U32 miny, U32 width, U32 height,
 void CommandBuffer::beginRenderPass(ConstWeakArray<RenderTarget> colorRts, RenderTarget* depthStencilRt, U32 minx, U32 miny, U32 width, U32 height,
@@ -778,7 +769,6 @@ void CommandBuffer::traceRays(const BufferView& sbtBuffer, U32 sbtRecordSize32,
 	ANKI_ASSERT(width > 0 && height > 0 && depth > 0);
 	ANKI_ASSERT(width > 0 && height > 0 && depth > 0);
 	ANKI_ASSERT(self.m_rtProg);
 	ANKI_ASSERT(self.m_rtProg);
 	const ShaderProgramImpl& sprog = static_cast<const ShaderProgramImpl&>(*self.m_rtProg);
 	const ShaderProgramImpl& sprog = static_cast<const ShaderProgramImpl&>(*self.m_rtProg);
-	ANKI_ASSERT(sprog.getReflectionInfo().m_descriptor.m_pushConstantsSize == self.m_setPushConstantsSize && "Forgot to set pushConstants");
 
 
 	ANKI_ASSERT(rayTypeCount == sprog.getMissShaderCount() && "All the miss shaders should be in use");
 	ANKI_ASSERT(rayTypeCount == sprog.getMissShaderCount() && "All the miss shaders should be in use");
 	ANKI_ASSERT((hitGroupSbtRecordCount % rayTypeCount) == 0);
 	ANKI_ASSERT((hitGroupSbtRecordCount % rayTypeCount) == 0);
@@ -790,18 +780,7 @@ void CommandBuffer::traceRays(const BufferView& sbtBuffer, U32 sbtRecordSize32,
 	self.commandCommon();
 	self.commandCommon();
 
 
 	// Bind descriptors
 	// Bind descriptors
-	for(U32 i = 0; i < kMaxDescriptorSets; ++i)
-	{
-		if(sprog.getReflectionInfo().m_descriptorSetMask.get(i))
-		{
-			VkDescriptorSet dset;
-			if(self.m_dsetState[i].flush(self.m_microCmdb->getDSAllocator(), dset))
-			{
-				vkCmdBindDescriptorSets(self.m_handle, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, sprog.getPipelineLayout().getHandle(), i, 1, &dset, 0,
-										nullptr);
-			}
-		}
-	}
+	self.m_descriptorState.flush(self.m_handle, self.m_microCmdb->getDSAllocator());
 
 
 	Array<VkStridedDeviceAddressRegionKHR, 4> regions;
 	Array<VkStridedDeviceAddressRegionKHR, 4> regions;
 	const U64 stbBufferAddress = sbtBuffer.getBuffer().getGpuAddress() + sbtBuffer.getOffset();
 	const U64 stbBufferAddress = sbtBuffer.getBuffer().getGpuAddress() + sbtBuffer.getOffset();
@@ -1386,12 +1365,7 @@ void CommandBuffer::setPushConstants(const void* data, U32 dataSize)
 				&& "The bound program should have push constants equal to the \"dataSize\" parameter");
 				&& "The bound program should have push constants equal to the \"dataSize\" parameter");
 
 
 	self.commandCommon();
 	self.commandCommon();
-
-	vkCmdPushConstants(self.m_handle, prog.getPipelineLayout().getHandle(), VK_SHADER_STAGE_ALL, 0, dataSize, data);
-
-#if ANKI_EXTRA_CHECKS
-	self.m_setPushConstantsSize = dataSize;
-#endif
+	self.m_descriptorState.setPushConstants(data, dataSize);
 }
 }
 
 
 void CommandBuffer::setRasterizationOrder(RasterizationOrder order)
 void CommandBuffer::setRasterizationOrder(RasterizationOrder order)
@@ -1485,10 +1459,7 @@ Error CommandBufferImpl::init(const CommandBufferInitInfo& init)
 
 
 	m_pool = &m_microCmdb->getFastMemoryPool();
 	m_pool = &m_microCmdb->getFastMemoryPool();
 
 
-	for(DSStateTracker& state : m_dsetState)
-	{
-		state.init(m_pool);
-	}
+	m_descriptorState.init(m_pool);
 
 
 	m_state.setVrsCapable(getGrManagerImpl().getDeviceCapabilities().m_vrs);
 	m_state.setVrsCapable(getGrManagerImpl().getDeviceCapabilities().m_vrs);
 
 
@@ -1590,7 +1561,6 @@ void CommandBufferImpl::drawcallCommon()
 	commandCommon();
 	commandCommon();
 	ANKI_ASSERT(m_graphicsProg);
 	ANKI_ASSERT(m_graphicsProg);
 	ANKI_ASSERT(m_insideRenderpass);
 	ANKI_ASSERT(m_insideRenderpass);
-	ANKI_ASSERT(m_graphicsProg->getReflectionInfo().m_descriptor.m_pushConstantsSize == m_setPushConstantsSize && "Forgot to set pushConstants");
 
 
 	// Get or create ppline
 	// Get or create ppline
 	Pipeline ppline;
 	Pipeline ppline;
@@ -1603,18 +1573,7 @@ void CommandBufferImpl::drawcallCommon()
 	}
 	}
 
 
 	// Bind dsets
 	// Bind dsets
-	for(U32 i = 0; i < kMaxDescriptorSets; ++i)
-	{
-		if(m_graphicsProg->getReflectionInfo().m_descriptorSetMask.get(i))
-		{
-			VkDescriptorSet dset;
-			if(m_dsetState[i].flush(m_microCmdb->getDSAllocator(), dset))
-			{
-				vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsProg->getPipelineLayout().getHandle(), i, 1, &dset, 0,
-										nullptr);
-			}
-		}
-	}
+	m_descriptorState.flush(m_handle, m_microCmdb->getDSAllocator());
 
 
 	// Flush viewport
 	// Flush viewport
 	if(m_viewportDirty) [[unlikely]]
 	if(m_viewportDirty) [[unlikely]]
@@ -1674,23 +1633,11 @@ void CommandBufferImpl::drawcallCommon()
 ANKI_FORCE_INLINE void CommandBufferImpl::dispatchCommon()
 ANKI_FORCE_INLINE void CommandBufferImpl::dispatchCommon()
 {
 {
 	ANKI_ASSERT(m_computeProg);
 	ANKI_ASSERT(m_computeProg);
-	ANKI_ASSERT(m_computeProg->getReflectionInfo().m_descriptor.m_pushConstantsSize == m_setPushConstantsSize && "Forgot to set pushConstants");
 
 
 	commandCommon();
 	commandCommon();
 
 
 	// Bind descriptors
 	// Bind descriptors
-	for(U32 i = 0; i < kMaxDescriptorSets; ++i)
-	{
-		if(m_computeProg->getReflectionInfo().m_descriptorSetMask.get(i))
-		{
-			VkDescriptorSet dset;
-			if(m_dsetState[i].flush(m_microCmdb->getDSAllocator(), dset))
-			{
-				vkCmdBindDescriptorSets(m_handle, VK_PIPELINE_BIND_POINT_COMPUTE, m_computeProg->getPipelineLayout().getHandle(), i, 1, &dset, 0,
-										nullptr);
-			}
-		}
-	}
+	m_descriptorState.flush(m_handle, m_microCmdb->getDSAllocator());
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 1 - 3
AnKi/Gr/Vulkan/VkCommandBuffer.h

@@ -109,15 +109,13 @@ private:
 	U32 m_renderpassHeight = 0;
 	U32 m_renderpassHeight = 0;
 #if ANKI_ASSERTIONS_ENABLED
 #if ANKI_ASSERTIONS_ENABLED
 	U32 m_commandCount = 0;
 	U32 m_commandCount = 0;
-	U32 m_setPushConstantsSize = 0;
 	U32 m_debugMarkersPushed = 0;
 	U32 m_debugMarkersPushed = 0;
 	Bool m_submitted = false;
 	Bool m_submitted = false;
 	Bool m_insideRenderpass = false;
 	Bool m_insideRenderpass = false;
 #endif
 #endif
 
 
 	PipelineStateTracker m_state;
 	PipelineStateTracker m_state;
-
-	Array<DSStateTracker, kMaxDescriptorSets> m_dsetState;
+	DescriptorState m_descriptorState;
 
 
 	ShaderProgramImpl* m_graphicsProg ANKI_DEBUG_CODE(= nullptr); ///< Last bound graphics program
 	ShaderProgramImpl* m_graphicsProg ANKI_DEBUG_CODE(= nullptr); ///< Last bound graphics program
 	ShaderProgramImpl* m_computeProg ANKI_DEBUG_CODE(= nullptr);
 	ShaderProgramImpl* m_computeProg ANKI_DEBUG_CODE(= nullptr);

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

@@ -8,7 +8,7 @@
 #include <AnKi/Gr/Vulkan/VkFenceFactory.h>
 #include <AnKi/Gr/Vulkan/VkFenceFactory.h>
 #include <AnKi/Gr/CommandBuffer.h>
 #include <AnKi/Gr/CommandBuffer.h>
 #include <AnKi/Gr/BackendCommon/MicroObjectRecycler.h>
 #include <AnKi/Gr/BackendCommon/MicroObjectRecycler.h>
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
 #include <AnKi/Util/List.h>
 #include <AnKi/Util/List.h>
 
 
 namespace anki {
 namespace anki {
@@ -98,7 +98,7 @@ public:
 		return m_queue;
 		return m_queue;
 	}
 	}
 
 
-	DSAllocator& getDSAllocator()
+	DescriptorAllocator& getDSAllocator()
 	{
 	{
 		return m_dsAllocator;
 		return m_dsAllocator;
 	}
 	}
@@ -112,7 +112,7 @@ private:
 	MicroFencePtr m_fence;
 	MicroFencePtr m_fence;
 	Array<DynamicArray<GrObjectPtr, MemoryPoolPtrWrapper<StackMemoryPool>>, U(GrObjectType::kCount)> m_objectRefs;
 	Array<DynamicArray<GrObjectPtr, MemoryPoolPtrWrapper<StackMemoryPool>>, U(GrObjectType::kCount)> m_objectRefs;
 
 
-	DSAllocator m_dsAllocator;
+	DescriptorAllocator m_dsAllocator;
 
 
 	CommandBufferThreadAllocator* m_threadAlloc;
 	CommandBufferThreadAllocator* m_threadAlloc;
 	mutable Atomic<I32> m_refcount = {0};
 	mutable Atomic<I32> m_refcount = {0};

+ 618 - 0
AnKi/Gr/Vulkan/VkDescriptor.cpp

@@ -0,0 +1,618 @@
+// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
+#include <AnKi/Gr/Vulkan/VkGrManager.h>
+#include <AnKi/Core/StatsSet.h>
+#include <AnKi/Util/Tracer.h>
+
+namespace anki {
+
+static StatCounter g_descriptorSetsAllocatedStatVar(StatCategory::kMisc, "DescriptorSets allocated this frame", StatFlag::kZeroEveryFrame);
+static StatCounter g_descriptorSetsWrittenStatVar(StatCategory::kMisc, "DescriptorSets written this frame", StatFlag::kZeroEveryFrame);
+
+/// Contains some constants. It's a class to avoid bugs initializing arrays (m_descriptorCount).
+class DSAllocatorConstants
+{
+public:
+	Array<std::pair<VkDescriptorType, U32>, 8> m_descriptorCount;
+
+	U32 m_maxSets;
+
+	DSAllocatorConstants()
+	{
+		m_descriptorCount[0] = {VK_DESCRIPTOR_TYPE_SAMPLER, 8};
+		m_descriptorCount[1] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 64};
+		m_descriptorCount[2] = {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 8};
+		m_descriptorCount[3] = {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 32};
+		m_descriptorCount[4] = {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 8};
+		m_descriptorCount[5] = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8};
+		m_descriptorCount[6] = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 64};
+		m_descriptorCount[7] = {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 4};
+
+		m_maxSets = 64;
+	}
+};
+
+static const DSAllocatorConstants g_dsAllocatorConsts;
+
+static U32 powu(U32 base, U32 exponent)
+{
+	U32 out = 1;
+	for(U32 i = 1; i <= exponent; i++)
+	{
+		out *= base;
+	}
+	return out;
+}
+
+DescriptorAllocator::~DescriptorAllocator()
+{
+	destroy();
+}
+
+void DescriptorAllocator::createNewBlock()
+{
+	ANKI_TRACE_SCOPED_EVENT(GrDescriptorSetCreate);
+
+	const Bool rtEnabled = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled;
+
+	Array<VkDescriptorPoolSize, g_dsAllocatorConsts.m_descriptorCount.getSize()> poolSizes;
+
+	for(U32 i = 0; i < g_dsAllocatorConsts.m_descriptorCount.getSize(); ++i)
+	{
+		VkDescriptorPoolSize& size = poolSizes[i];
+
+		size.descriptorCount = g_dsAllocatorConsts.m_descriptorCount[i].second * powu(kDescriptorSetGrowScale, m_blocks.getSize());
+		size.type = g_dsAllocatorConsts.m_descriptorCount[i].first;
+	}
+
+	VkDescriptorPoolCreateInfo inf = {};
+	inf.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+	inf.flags = 0;
+	inf.maxSets = g_dsAllocatorConsts.m_maxSets * powu(kDescriptorSetGrowScale, m_blocks.getSize());
+	static_assert(DescriptorType::kAccelerationStructure == DescriptorType::kCount - 1, "Needs to be the last for the bellow to work");
+	inf.poolSizeCount = rtEnabled ? U32(DescriptorType::kCount) : U32(DescriptorType::kCount) - 1;
+	inf.pPoolSizes = poolSizes.getBegin();
+
+	VkDescriptorPool handle;
+	ANKI_VK_CHECKF(vkCreateDescriptorPool(getVkDevice(), &inf, nullptr, &handle));
+
+	Block& block = *m_blocks.emplaceBack();
+	block.m_pool = handle;
+
+	g_descriptorSetsAllocatedStatVar.increment(1);
+}
+
+void DescriptorAllocator::allocate(VkDescriptorSetLayout layout, VkDescriptorSet& set)
+{
+	ANKI_TRACE_SCOPED_EVENT(GrAllocateDescriptorSet);
+
+	// Lazy init
+	if(m_blocks.getSize() == 0)
+	{
+		createNewBlock();
+		ANKI_ASSERT(m_activeBlock == 0);
+	}
+
+	U32 iterationCount = 0;
+	do
+	{
+		VkResult res;
+		if(m_blocks[m_activeBlock].m_dsetsAllocatedCount > g_dsAllocatorConsts.m_maxSets * powu(kDescriptorSetGrowScale, m_activeBlock) * 2)
+		{
+			// The driver doesn't respect VkDescriptorPoolCreateInfo::maxSets. It should have thrown OoM already. To avoid growing the same DS forever
+			// force OoM
+			res = VK_ERROR_OUT_OF_POOL_MEMORY;
+		}
+		else
+		{
+
+			VkDescriptorSetAllocateInfo ci = {};
+			ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+			ci.descriptorPool = m_blocks[m_activeBlock].m_pool;
+			ci.descriptorSetCount = 1;
+			ci.pSetLayouts = &layout;
+
+			res = vkAllocateDescriptorSets(getVkDevice(), &ci, &set);
+		}
+
+		if(res == VK_SUCCESS)
+		{
+			++m_blocks[m_activeBlock].m_dsetsAllocatedCount;
+			break;
+		}
+		else if(res == VK_ERROR_OUT_OF_POOL_MEMORY)
+		{
+			++m_activeBlock;
+			if(m_activeBlock >= m_blocks.getSize())
+			{
+				createNewBlock();
+			}
+		}
+		else
+		{
+			ANKI_VK_CHECKF(res);
+		}
+
+		++iterationCount;
+	} while(iterationCount < 10);
+
+	if(iterationCount == 10)
+	{
+		ANKI_VK_LOGF("Failed to allocate descriptor set");
+	}
+}
+
+void DescriptorAllocator::reset()
+{
+	// Trim blocks that were not used last time
+	const U32 blocksInUse = m_activeBlock + 1;
+	if(blocksInUse < m_blocks.getSize())
+	{
+		for(U32 i = blocksInUse; i < m_blocks.getSize(); ++i)
+		{
+			vkDestroyDescriptorPool(getVkDevice(), m_blocks[i].m_pool, nullptr);
+		}
+
+		m_blocks.resize(blocksInUse);
+	}
+
+	// Reset the remaining pools
+	for(Block& b : m_blocks)
+	{
+		vkResetDescriptorPool(getVkDevice(), b.m_pool, 0);
+		b.m_dsetsAllocatedCount = 0;
+	}
+
+	m_activeBlock = 0;
+}
+
+BindlessDescriptorSet::~BindlessDescriptorSet()
+{
+	ANKI_ASSERT(m_freeTexIndexCount == m_freeTexIndices.getSize() && "Forgot to unbind some textures");
+
+	if(m_dsPool)
+	{
+		vkDestroyDescriptorPool(getVkDevice(), m_dsPool, nullptr);
+		m_dsPool = VK_NULL_HANDLE;
+		m_dset = VK_NULL_HANDLE;
+	}
+
+	if(m_layout)
+	{
+		vkDestroyDescriptorSetLayout(getVkDevice(), m_layout, nullptr);
+		m_layout = VK_NULL_HANDLE;
+	}
+}
+
+Error BindlessDescriptorSet::init()
+{
+	const U32 bindlessTextureCount = g_maxBindlessSampledTextureCountCVar.get();
+
+	// Create the layout
+	{
+		Array<VkDescriptorSetLayoutBinding, 1> bindings = {};
+		bindings[0].binding = 0;
+		bindings[0].stageFlags = VK_SHADER_STAGE_ALL;
+		bindings[0].descriptorCount = bindlessTextureCount;
+		bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+
+		Array<VkDescriptorBindingFlagsEXT, 1> bindingFlags = {};
+		bindingFlags[0] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT
+						  | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT;
+
+		VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extraInfos = {};
+		extraInfos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
+		extraInfos.bindingCount = bindingFlags.getSize();
+		extraInfos.pBindingFlags = &bindingFlags[0];
+
+		VkDescriptorSetLayoutCreateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+		ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
+		ci.bindingCount = bindings.getSize();
+		ci.pBindings = &bindings[0];
+		ci.pNext = &extraInfos;
+
+		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &m_layout));
+	}
+
+	// Create the pool
+	{
+		Array<VkDescriptorPoolSize, 1> sizes = {};
+		sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+		sizes[0].descriptorCount = bindlessTextureCount;
+
+		VkDescriptorPoolCreateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+		ci.maxSets = 1;
+		ci.poolSizeCount = sizes.getSize();
+		ci.pPoolSizes = &sizes[0];
+		ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
+
+		ANKI_VK_CHECK(vkCreateDescriptorPool(getVkDevice(), &ci, nullptr, &m_dsPool));
+	}
+
+	// Create the descriptor set
+	{
+		VkDescriptorSetAllocateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+		ci.descriptorPool = m_dsPool;
+		ci.descriptorSetCount = 1;
+		ci.pSetLayouts = &m_layout;
+
+		ANKI_VK_CHECK(vkAllocateDescriptorSets(getVkDevice(), &ci, &m_dset));
+	}
+
+	// Init the free arrays
+	{
+		m_freeTexIndices.resize(bindlessTextureCount);
+		m_freeTexIndexCount = U16(m_freeTexIndices.getSize());
+
+		for(U32 i = 0; i < m_freeTexIndices.getSize(); ++i)
+		{
+			m_freeTexIndices[i] = U16(m_freeTexIndices.getSize() - i - 1);
+		}
+	}
+
+	return Error::kNone;
+}
+
+U32 BindlessDescriptorSet::bindTexture(const VkImageView view, const VkImageLayout layout)
+{
+	ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL || layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+	ANKI_ASSERT(view);
+	LockGuard<Mutex> lock(m_mtx);
+	ANKI_ASSERT(m_freeTexIndexCount > 0 && "Out of indices");
+
+	// Pop the index
+	--m_freeTexIndexCount;
+	const U16 idx = m_freeTexIndices[m_freeTexIndexCount];
+	ANKI_ASSERT(idx < m_freeTexIndices.getSize());
+
+	// Update the set
+	VkDescriptorImageInfo imageInf = {};
+	imageInf.imageView = view;
+	imageInf.imageLayout = layout;
+
+	VkWriteDescriptorSet write = {};
+	write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+	write.pNext = nullptr;
+	write.dstSet = m_dset;
+	write.dstBinding = 0;
+	write.descriptorCount = 1;
+	write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+	write.dstArrayElement = idx;
+	write.pImageInfo = &imageInf;
+
+	vkUpdateDescriptorSets(getVkDevice(), 1, &write, 0, nullptr);
+
+	return idx;
+}
+
+void BindlessDescriptorSet::unbindTexture(U32 idx)
+{
+	LockGuard<Mutex> lock(m_mtx);
+
+	ANKI_ASSERT(idx < m_freeTexIndices.getSize());
+	ANKI_ASSERT(m_freeTexIndexCount < m_freeTexIndices.getSize());
+
+	m_freeTexIndices[m_freeTexIndexCount] = U16(idx);
+	++m_freeTexIndexCount;
+
+	// Sort the free indices to minimize fragmentation
+	std::sort(&m_freeTexIndices[0], &m_freeTexIndices[0] + m_freeTexIndexCount, std::greater<U16>());
+
+	// Make sure there are no duplicates
+	for(U32 i = 1; i < m_freeTexIndexCount; ++i)
+	{
+		ANKI_ASSERT(m_freeTexIndices[i] != m_freeTexIndices[i - 1]);
+	}
+}
+
+PipelineLayoutFactory2::~PipelineLayoutFactory2()
+{
+	for(auto it : m_pplLayouts)
+	{
+		vkDestroyPipelineLayout(getVkDevice(), it->m_handle, nullptr);
+		deleteInstance(GrMemoryPool::getSingleton(), it);
+	}
+
+	for(auto it : m_dsLayouts)
+	{
+		vkDestroyDescriptorSetLayout(getVkDevice(), it->m_handle, nullptr);
+		deleteInstance(GrMemoryPool::getSingleton(), it);
+	}
+}
+
+Error PipelineLayoutFactory2::getOrCreateDescriptorSetLayout(ConstWeakArray<ShaderReflectionBinding> reflBindings, DescriptorSetLayout*& layout)
+{
+	ANKI_BEGIN_PACKED_STRUCT
+	class DSBinding
+	{
+	public:
+		VkDescriptorType m_type = VK_DESCRIPTOR_TYPE_MAX_ENUM;
+		U16 m_arraySize = 0;
+		U16 m_binding = kMaxU8;
+	};
+	ANKI_END_PACKED_STRUCT
+
+	// Compute the hash for the layout
+	Array<DSBinding, kMaxBindingsPerDescriptorSet> bindings;
+	U64 hash;
+
+	if(reflBindings.getSize())
+	{
+		// Copy to a new place because we want to sort
+		U32 count = 0;
+		for(const ShaderReflectionBinding& reflBinding : reflBindings)
+		{
+			bindings[count].m_type = convertDescriptorType(reflBinding.m_type, reflBinding.m_flags);
+			bindings[count].m_arraySize = reflBinding.m_arraySize;
+			bindings[count].m_binding = reflBinding.m_vkBinding;
+			++count;
+		}
+
+		std::sort(bindings.getBegin(), bindings.getBegin() + count, [](const DSBinding& a, const DSBinding& b) {
+			return a.m_binding < b.m_binding;
+		});
+
+		hash = computeHash(&bindings[0], sizeof(bindings[0]) * count);
+		ANKI_ASSERT(hash != 1);
+	}
+	else
+	{
+		hash = 1;
+	}
+
+	// Search the cache or create it
+	auto it = m_dsLayouts.find(hash);
+	if(it != m_dsLayouts.getEnd())
+	{
+		layout = *it;
+	}
+	else
+	{
+		const U32 bindingCount = reflBindings.getSize();
+
+		layout = newInstance<DescriptorSetLayout>(GrMemoryPool::getSingleton());
+		m_dsLayouts.emplace(hash, layout);
+
+		Array<VkDescriptorSetLayoutBinding, kMaxBindingsPerDescriptorSet> vkBindings;
+		VkDescriptorSetLayoutCreateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+
+		for(U i = 0; i < bindingCount; ++i)
+		{
+			VkDescriptorSetLayoutBinding& vk = vkBindings[i];
+			const DSBinding& ak = bindings[i];
+
+			vk.binding = ak.m_binding;
+			vk.descriptorCount = ak.m_arraySize;
+			vk.descriptorType = ak.m_type;
+			vk.pImmutableSamplers = nullptr;
+			vk.stageFlags = VK_SHADER_STAGE_ALL;
+		}
+
+		ci.bindingCount = bindingCount;
+		ci.pBindings = &vkBindings[0];
+
+		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &layout->m_handle));
+	}
+
+	return Error::kNone;
+}
+
+Error PipelineLayoutFactory2::getOrCreatePipelineLayout(const ShaderReflectionDescriptorRelated& refl, PipelineLayout2*& layout)
+{
+	// Compute the hash
+	const U64 hash = computeHash(&refl, sizeof(refl));
+
+	LockGuard lock(m_mtx);
+
+	auto it = m_pplLayouts.find(hash);
+	if(it != m_pplLayouts.getEnd())
+	{
+		layout = *it;
+	}
+	else
+	{
+		// Create new
+
+		layout = newInstance<PipelineLayout2>(GrMemoryPool::getSingleton());
+		m_pplLayouts.emplace(hash, layout);
+		layout->m_refl = refl;
+
+		// Find dset count
+		layout->m_dsetCount = 0;
+		for(U8 iset = 0; iset < kMaxDescriptorSets; ++iset)
+		{
+			if(refl.m_bindingCounts[iset])
+			{
+				layout->m_dsetCount = max<U8>(iset + 1u, layout->m_dsetCount);
+
+				for(U32 i = 0; i < refl.m_bindingCounts[iset]; ++i)
+				{
+					layout->m_descriptorCounts[iset] += refl.m_bindings[iset][i].m_arraySize;
+				}
+			}
+		}
+
+		if(refl.m_vkBindlessDescriptorSet != kMaxU8)
+		{
+			layout->m_dsetCount = max<U8>(refl.m_vkBindlessDescriptorSet + 1, layout->m_dsetCount);
+		}
+
+		// Create the DS layouts
+		for(U32 iset = 0; iset < layout->m_dsetCount; ++iset)
+		{
+			if(refl.m_vkBindlessDescriptorSet == iset)
+			{
+				layout->m_dsetLayouts[iset] = BindlessDescriptorSet::getSingleton().m_layout;
+			}
+			else
+			{
+				DescriptorSetLayout* dlayout;
+				ANKI_CHECK(getOrCreateDescriptorSetLayout({refl.m_bindings[iset].getBegin(), refl.m_bindingCounts[iset]}, dlayout));
+
+				layout->m_dsetLayouts[iset] = dlayout->m_handle;
+			}
+		}
+
+		VkPipelineLayoutCreateInfo ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+		ci.pSetLayouts = &layout->m_dsetLayouts[0];
+		ci.setLayoutCount = layout->m_dsetCount;
+
+		VkPushConstantRange pushConstantRange;
+		if(refl.m_pushConstantsSize > 0)
+		{
+			pushConstantRange.offset = 0;
+			pushConstantRange.size = refl.m_pushConstantsSize;
+			pushConstantRange.stageFlags = VK_SHADER_STAGE_ALL;
+			ci.pushConstantRangeCount = 1;
+			ci.pPushConstantRanges = &pushConstantRange;
+		}
+
+		ANKI_VK_CHECK(vkCreatePipelineLayout(getVkDevice(), &ci, nullptr, &layout->m_handle));
+	}
+
+	return Error::kNone;
+}
+
+void DescriptorState::flush(VkCommandBuffer cmdb, DescriptorAllocator& dalloc)
+{
+	ANKI_ASSERT(m_pipelineLayout);
+
+	const ShaderReflectionDescriptorRelated& refl = m_pipelineLayout->getReflection();
+
+	// Small opt to bind the high frequency sets as little as possible
+	BitSet<kMaxDescriptorSets> dirtySets(false);
+
+	for(U32 iset = 0; iset < m_pipelineLayout->m_dsetCount; ++iset)
+	{
+		DescriptorSet& set = m_sets[iset];
+
+		if(iset == refl.m_vkBindlessDescriptorSet)
+		{
+			if(m_vkDsets[iset] != BindlessDescriptorSet::getSingleton().m_dset)
+			{
+				dirtySets.set(iset);
+
+				m_vkDsets[iset] = BindlessDescriptorSet::getSingleton().m_dset;
+			}
+		}
+		else if(m_sets[iset].m_dirty)
+		{
+			// Need to allocate and populate a new DS
+
+			dirtySets.set(iset);
+
+			set.m_dirty = false;
+
+			if(set.m_writeInfos.getSize() < m_pipelineLayout->m_descriptorCounts[iset])
+			{
+				set.m_writeInfos.resize(m_pipelineLayout->m_descriptorCounts[iset]);
+			}
+
+			dalloc.allocate(m_pipelineLayout->m_dsetLayouts[iset], m_vkDsets[iset]);
+
+			// Write the DS
+			VkWriteDescriptorSet writeTemplate = {};
+			writeTemplate.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+			writeTemplate.pNext = nullptr;
+			writeTemplate.dstSet = m_vkDsets[iset];
+			writeTemplate.descriptorCount = 1;
+
+			U32 writeInfoCount = 0;
+
+			for(U32 ibinding = 0; ibinding < refl.m_bindingCounts[iset]; ++ibinding)
+			{
+				const ShaderReflectionBinding& binding = refl.m_bindings[iset][ibinding];
+				for(U32 arrayIdx = 0; arrayIdx < binding.m_arraySize; ++arrayIdx)
+				{
+					VkWriteDescriptorSet& writeInfo = set.m_writeInfos[writeInfoCount++];
+					const HlslResourceType hlslType = descriptorTypeToHlslResourceType(binding.m_type, binding.m_flags);
+					ANKI_ASSERT(binding.m_registerBindingPoint + arrayIdx < set.m_descriptors[hlslType].getSize() && "Forgot to bind something");
+					const Descriptor& desc = set.m_descriptors[hlslType][binding.m_registerBindingPoint + arrayIdx];
+
+					ANKI_ASSERT(desc.m_type == binding.m_type && desc.m_flags == binding.m_flags && "Have bound the wrong type");
+
+					writeInfo = writeTemplate;
+					writeInfo.descriptorType = convertDescriptorType(binding.m_type, binding.m_flags);
+					writeInfo.dstArrayElement = arrayIdx;
+					writeInfo.dstBinding = binding.m_vkBinding;
+
+					switch(writeInfo.descriptorType)
+					{
+					case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+					case VK_DESCRIPTOR_TYPE_SAMPLER:
+					case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+					{
+						writeInfo.pImageInfo = &desc.m_image;
+						break;
+					}
+					case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+					case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+					{
+						writeInfo.pBufferInfo = &desc.m_buffer;
+						break;
+					}
+					case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+					case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+					{
+						writeInfo.pTexelBufferView = &desc.m_bufferView;
+						break;
+					}
+					case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
+					{
+						writeInfo.pNext = &desc.m_as;
+						break;
+					}
+					default:
+						ANKI_ASSERT(0);
+					}
+				}
+			}
+
+			if(writeInfoCount > 0)
+			{
+				vkUpdateDescriptorSets(getVkDevice(), writeInfoCount, set.m_writeInfos.getBegin(), 0, nullptr);
+				g_descriptorSetsWrittenStatVar.increment(1);
+			}
+		}
+		else
+		{
+			// Do nothing
+		}
+
+		ANKI_ASSERT(m_vkDsets[iset] != VK_NULL_HANDLE);
+	}
+
+	// Bind the descriptor sets
+	if(dirtySets.getAnySet())
+	{
+		const U32 minSetThatNeedsRebind = dirtySets.getLeastSignificantBit();
+		const U32 dsetCount = m_pipelineLayout->m_dsetCount - minSetThatNeedsRebind;
+		ANKI_ASSERT(dsetCount <= m_pipelineLayout->m_dsetCount);
+		vkCmdBindDescriptorSets(cmdb, m_pipelineBindPoint, m_pipelineLayout->m_handle, minSetThatNeedsRebind, dsetCount,
+								&m_vkDsets[minSetThatNeedsRebind], 0, nullptr);
+	}
+
+	// Set push consts
+	if(refl.m_pushConstantsSize)
+	{
+		ANKI_ASSERT(refl.m_pushConstantsSize == m_pushConstSize && "Possibly forgot to set push constants");
+
+		if(m_pushConstantsDirty)
+		{
+			vkCmdPushConstants(cmdb, m_pipelineLayout->m_handle, VK_SHADER_STAGE_ALL, 0, m_pushConstSize, m_pushConsts.getBegin());
+			m_pushConstantsDirty = false;
+		}
+	}
+}
+
+} // end namespace anki

+ 362 - 0
AnKi/Gr/Vulkan/VkDescriptor.h

@@ -0,0 +1,362 @@
+// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/Gr/Vulkan/VkCommon.h>
+#include <AnKi/Util/HashMap.h>
+#include <AnKi/Util/WeakArray.h>
+
+namespace anki {
+
+/// @addtogroup vulkan
+/// @{
+
+/// Allocates descriptor sets.
+class DescriptorAllocator
+{
+public:
+	DescriptorAllocator() = default;
+
+	~DescriptorAllocator();
+
+	void destroy()
+	{
+		for(Block& b : m_blocks)
+		{
+			ANKI_ASSERT(b.m_pool != VK_NULL_HANDLE);
+			vkDestroyDescriptorPool(getVkDevice(), b.m_pool, nullptr);
+		}
+
+		m_blocks.destroy();
+		m_activeBlock = 0;
+	}
+
+	void allocate(VkDescriptorSetLayout layout, VkDescriptorSet& set);
+
+	/// Reset for reuse.
+	void reset();
+
+private:
+	class Block
+	{
+	public:
+		VkDescriptorPool m_pool = VK_NULL_HANDLE;
+		U32 m_dsetsAllocatedCount = 0;
+	};
+
+	static constexpr U32 kDescriptorSetGrowScale = 2;
+
+	GrDynamicArray<Block> m_blocks;
+
+	U32 m_activeBlock = 0;
+
+	void createNewBlock();
+};
+
+/// The bindless descriptor set.
+class BindlessDescriptorSet : public MakeSingleton<BindlessDescriptorSet>
+{
+	friend class PipelineLayoutFactory2;
+	friend class DescriptorState;
+
+public:
+	~BindlessDescriptorSet();
+
+	Error init();
+
+	/// Bind a sampled image.
+	/// @note It's thread-safe.
+	U32 bindTexture(const VkImageView view, const VkImageLayout layout);
+
+	/// @note It's thread-safe.
+	void unbindTexture(U32 idx);
+
+	U32 getMaxTextureCount() const
+	{
+		return m_freeTexIndices.getSize();
+	}
+
+private:
+	VkDescriptorSetLayout m_layout = VK_NULL_HANDLE;
+	VkDescriptorPool m_dsPool = VK_NULL_HANDLE;
+	VkDescriptorSet m_dset = VK_NULL_HANDLE;
+	Mutex m_mtx;
+
+	GrDynamicArray<U16> m_freeTexIndices;
+
+	U16 m_freeTexIndexCount = kMaxU16;
+};
+
+/// Wrapper over VkPipelineLayout
+class PipelineLayout2
+{
+	friend class PipelineLayoutFactory2;
+	friend class DescriptorState;
+
+public:
+	VkPipelineLayout getHandle() const
+	{
+		ANKI_ASSERT(m_handle);
+		return m_handle;
+	}
+
+	const ShaderReflectionDescriptorRelated& getReflection() const
+	{
+		return m_refl;
+	}
+
+private:
+	VkPipelineLayout m_handle = VK_NULL_HANDLE;
+	ShaderReflectionDescriptorRelated m_refl;
+	Array<VkDescriptorSetLayout, kMaxDescriptorSets> m_dsetLayouts = {};
+	Array<U32, kMaxDescriptorSets> m_descriptorCounts = {};
+	U8 m_dsetCount = 0;
+};
+
+/// Creator of pipeline layouts.
+class PipelineLayoutFactory2 : public MakeSingleton<PipelineLayoutFactory2>
+{
+public:
+	PipelineLayoutFactory2() = default;
+
+	~PipelineLayoutFactory2();
+
+	/// @note It's thread-safe.
+	Error getOrCreatePipelineLayout(const ShaderReflectionDescriptorRelated& refl, PipelineLayout2*& layout);
+
+private:
+	class DescriptorSetLayout
+	{
+	public:
+		VkDescriptorSetLayout m_handle = {};
+	};
+
+	GrHashMap<U64, PipelineLayout2*> m_pplLayouts;
+	GrHashMap<U64, DescriptorSetLayout*> m_dsLayouts;
+
+	Mutex m_mtx;
+
+	Error getOrCreateDescriptorSetLayout(ConstWeakArray<ShaderReflectionBinding> bindings, DescriptorSetLayout*& layout);
+};
+
+/// Part of the command buffer that deals with descriptors.
+class DescriptorState
+{
+public:
+	void init(StackMemoryPool* tempPool)
+	{
+		for(auto& set : m_sets)
+		{
+			set.init(tempPool);
+		}
+	}
+
+	void setPipelineLayout(const PipelineLayout2* layout, VkPipelineBindPoint bindPoint)
+	{
+		ANKI_ASSERT(layout);
+		if(layout != m_pipelineLayout || bindPoint != m_pipelineBindPoint)
+		{
+			m_pipelineLayout = layout;
+			m_pipelineBindPoint = bindPoint;
+			m_pushConstantsDirty = m_pushConstantsDirty || (m_pushConstSize != m_pipelineLayout->m_refl.m_pushConstantsSize);
+
+			for(U32 iset = 0; iset < m_pipelineLayout->m_dsetCount; ++iset)
+			{
+				if(m_sets[iset].m_dsLayout != m_pipelineLayout->m_dsetLayouts[iset])
+				{
+					m_sets[iset].m_dirty = true;
+					m_sets[iset].m_dsLayout = m_pipelineLayout->m_dsetLayouts[iset];
+				}
+			}
+		}
+	}
+
+	void bindSampledTexture(U32 space, U32 registerBinding, VkImageView view, VkImageLayout layout)
+	{
+		ANKI_ASSERT(view != 0 && layout != VK_IMAGE_LAYOUT_UNDEFINED);
+		Descriptor& desc = getDescriptor(HlslResourceType::kSrv, space, registerBinding);
+		desc.m_image.imageView = view;
+		desc.m_image.imageLayout = layout;
+		desc.m_image.sampler = 0;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kTexture;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void bindStorageTexture(U32 space, U32 registerBinding, VkImageView view)
+	{
+		ANKI_ASSERT(view);
+		Descriptor& desc = getDescriptor(HlslResourceType::kUav, space, registerBinding);
+		desc.m_image.imageView = view;
+		desc.m_image.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+		desc.m_image.sampler = 0;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kTexture;
+		desc.m_flags = DescriptorFlag::kReadWrite;
+#endif
+	}
+
+	void bindSampler(U32 space, U32 registerBinding, VkSampler sampler)
+	{
+		ANKI_ASSERT(sampler);
+		Descriptor& desc = getDescriptor(HlslResourceType::kSampler, space, registerBinding);
+		desc.m_image.imageView = 0;
+		desc.m_image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+		desc.m_image.sampler = sampler;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kSampler;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void bindUniformBuffer(U32 space, U32 registerBinding, VkBuffer buffer, PtrSize offset, PtrSize range)
+	{
+		ANKI_ASSERT(buffer && range > 0);
+		Descriptor& desc = getDescriptor(HlslResourceType::kCbv, space, registerBinding);
+		desc.m_buffer.buffer = buffer;
+		desc.m_buffer.offset = offset;
+		desc.m_buffer.range = range;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kUniformBuffer;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void bindReadStorageBuffer(U32 space, U32 registerBinding, VkBuffer buffer, PtrSize offset, PtrSize range)
+	{
+		ANKI_ASSERT(buffer && range > 0);
+		Descriptor& desc = getDescriptor(HlslResourceType::kSrv, space, registerBinding);
+		desc.m_buffer.buffer = buffer;
+		desc.m_buffer.offset = offset;
+		desc.m_buffer.range = range;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kStorageBuffer;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void bindReadWriteStorageBuffer(U32 space, U32 registerBinding, VkBuffer buffer, PtrSize offset, PtrSize range)
+	{
+		ANKI_ASSERT(buffer && range > 0);
+		Descriptor& desc = getDescriptor(HlslResourceType::kUav, space, registerBinding);
+		desc.m_buffer.buffer = buffer;
+		desc.m_buffer.offset = offset;
+		desc.m_buffer.range = range;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kStorageBuffer;
+		desc.m_flags = DescriptorFlag::kReadWrite;
+#endif
+	}
+
+	void bindReadTexelBuffer(U32 space, U32 registerBinding, VkBufferView bufferView)
+	{
+		ANKI_ASSERT(bufferView);
+		Descriptor& desc = getDescriptor(HlslResourceType::kSrv, space, registerBinding);
+		desc.m_bufferView = bufferView;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kTexelBuffer;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void bindReadWriteTexelBuffer(U32 space, U32 registerBinding, VkBufferView bufferView)
+	{
+		ANKI_ASSERT(bufferView);
+		Descriptor& desc = getDescriptor(HlslResourceType::kUav, space, registerBinding);
+		desc.m_bufferView = bufferView;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kTexelBuffer;
+		desc.m_flags = DescriptorFlag::kReadWrite;
+#endif
+	}
+
+	void bindAccelerationStructure(U32 space, U32 registerBinding, const VkAccelerationStructureKHR* handle)
+	{
+		ANKI_ASSERT(handle);
+		Descriptor& desc = getDescriptor(HlslResourceType::kSrv, space, registerBinding);
+		desc.m_as.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
+		desc.m_as.pNext = nullptr;
+		desc.m_as.accelerationStructureCount = 1;
+		desc.m_as.pAccelerationStructures = handle;
+#if ANKI_ASSERTIONS_ENABLED
+		desc.m_type = DescriptorType::kAccelerationStructure;
+		desc.m_flags = DescriptorFlag::kRead;
+#endif
+	}
+
+	void setPushConstants(const void* data, U32 dataSize)
+	{
+		ANKI_ASSERT(data && dataSize && dataSize <= kMaxPushConstantSize);
+		memcpy(m_pushConsts.getBegin(), data, dataSize);
+		m_pushConstSize = dataSize;
+		m_pushConstantsDirty = true;
+	}
+
+	void flush(VkCommandBuffer cmdb, DescriptorAllocator& dalloc);
+
+private:
+	class Descriptor
+	{
+	public:
+		union
+		{
+			VkDescriptorImageInfo m_image;
+			VkDescriptorBufferInfo m_buffer;
+			VkWriteDescriptorSetAccelerationStructureKHR m_as;
+			VkBufferView m_bufferView;
+		};
+
+#if ANKI_ASSERTIONS_ENABLED
+		DescriptorType m_type = DescriptorType::kCount;
+		DescriptorFlag m_flags = DescriptorFlag::kNone;
+#endif
+	};
+
+	class DescriptorSet
+	{
+	public:
+		Array<DynamicArray<Descriptor, MemoryPoolPtrWrapper<StackMemoryPool>>, U32(HlslResourceType::kCount)> m_descriptors;
+
+		DynamicArray<VkWriteDescriptorSet, MemoryPoolPtrWrapper<StackMemoryPool>> m_writeInfos;
+
+		VkDescriptorSetLayout m_dsLayout = VK_NULL_HANDLE;
+
+		Bool m_dirty = true; ///< Needs rebuild and rebind
+
+		void init(StackMemoryPool* pool)
+		{
+			for(auto& dynArr : m_descriptors)
+			{
+				dynArr = {pool};
+			}
+
+			m_writeInfos = {pool};
+		}
+	};
+
+	const PipelineLayout2* m_pipelineLayout = nullptr;
+	VkPipelineBindPoint m_pipelineBindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM;
+	Array<DescriptorSet, kMaxDescriptorSets> m_sets;
+	Array<VkDescriptorSet, kMaxDescriptorSets> m_vkDsets = {};
+
+	Array<U8, kMaxPushConstantSize> m_pushConsts;
+	U32 m_pushConstSize = 0;
+	Bool m_pushConstantsDirty = true;
+
+	Descriptor& getDescriptor(HlslResourceType svv, U32 space, U32 registerBinding)
+	{
+		if(registerBinding >= m_sets[space].m_descriptors[svv].getSize())
+		{
+			m_sets[space].m_descriptors[svv].resize(registerBinding + 1);
+		}
+		m_sets[space].m_dirty = true;
+		return m_sets[space].m_descriptors[svv][registerBinding];
+	}
+};
+/// @}
+
+} // end namespace anki

+ 0 - 667
AnKi/Gr/Vulkan/VkDescriptorSetFactory.cpp

@@ -1,667 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
-#include <AnKi/Gr/Vulkan/VkGrManager.h>
-#include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/StatsSet.h>
-
-namespace anki {
-
-static StatCounter g_descriptorSetsAllocated(StatCategory::kMisc, "DescriptorSets allocated this frame", StatFlag::kZeroEveryFrame);
-
-/// Contains some constants. It's a class to avoid bugs initializing arrays (m_descriptorCount).
-class DSAllocatorConstants
-{
-public:
-	Array<std::pair<VkDescriptorType, U32>, 8> m_descriptorCount;
-
-	U32 m_maxSets;
-
-	DSAllocatorConstants()
-	{
-		m_descriptorCount[0] = {VK_DESCRIPTOR_TYPE_SAMPLER, 8};
-		m_descriptorCount[1] = {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 64};
-		m_descriptorCount[2] = {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 8};
-		m_descriptorCount[3] = {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 32};
-		m_descriptorCount[4] = {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 8};
-		m_descriptorCount[5] = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 8};
-		m_descriptorCount[6] = {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 64};
-		m_descriptorCount[7] = {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 4};
-
-		m_maxSets = 64;
-	}
-};
-
-static const DSAllocatorConstants g_dsAllocatorConsts;
-
-static U32 powu(U32 base, U32 exponent)
-{
-	U32 out = 1;
-	for(U32 i = 1; i <= exponent; i++)
-	{
-		out *= base;
-	}
-	return out;
-}
-
-DSAllocator::~DSAllocator()
-{
-	destroy();
-}
-
-void DSAllocator::createNewBlock()
-{
-	ANKI_TRACE_SCOPED_EVENT(GrDescriptorSetCreate);
-
-	const Bool rtEnabled = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled;
-
-	Array<VkDescriptorPoolSize, g_dsAllocatorConsts.m_descriptorCount.getSize()> poolSizes;
-
-	for(U32 i = 0; i < g_dsAllocatorConsts.m_descriptorCount.getSize(); ++i)
-	{
-		VkDescriptorPoolSize& size = poolSizes[i];
-
-		size.descriptorCount = g_dsAllocatorConsts.m_descriptorCount[i].second * powu(kDescriptorSetGrowScale, m_blocks.getSize());
-		size.type = g_dsAllocatorConsts.m_descriptorCount[i].first;
-	}
-
-	VkDescriptorPoolCreateInfo inf = {};
-	inf.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
-	inf.flags = 0;
-	inf.maxSets = g_dsAllocatorConsts.m_maxSets * powu(kDescriptorSetGrowScale, m_blocks.getSize());
-	static_assert(DescriptorType::kAccelerationStructure == DescriptorType::kCount - 1, "Needs to be the last for the bellow to work");
-	inf.poolSizeCount = rtEnabled ? U32(DescriptorType::kCount) : U32(DescriptorType::kCount) - 1;
-	inf.pPoolSizes = poolSizes.getBegin();
-
-	VkDescriptorPool handle;
-	ANKI_VK_CHECKF(vkCreateDescriptorPool(getVkDevice(), &inf, nullptr, &handle));
-
-	Block& block = *m_blocks.emplaceBack();
-	block.m_pool = handle;
-
-	g_descriptorSetsAllocated.increment(1);
-}
-
-void DSAllocator::allocate(const DSLayout& layout, VkDescriptorSet& set)
-{
-	ANKI_TRACE_SCOPED_EVENT(GrAllocateDescriptorSet);
-
-	ANKI_ASSERT(layout.m_hash != 0 && "Can't allocate using the bindless DS layout");
-
-	// Lazy init
-	if(m_blocks.getSize() == 0)
-	{
-		createNewBlock();
-		ANKI_ASSERT(m_activeBlock == 0);
-	}
-
-	U32 iterationCount = 0;
-	do
-	{
-		VkResult res;
-		if(m_blocks[m_activeBlock].m_dsetsAllocatedCount > g_dsAllocatorConsts.m_maxSets * powu(kDescriptorSetGrowScale, m_activeBlock) * 2)
-		{
-			// The driver doesn't respect VkDescriptorPoolCreateInfo::maxSets. It should have thrown OoM already. To avoid growing the same DS forever
-			// force OoM
-			res = VK_ERROR_OUT_OF_POOL_MEMORY;
-		}
-		else
-		{
-
-			VkDescriptorSetAllocateInfo ci = {};
-			ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-			ci.descriptorPool = m_blocks[m_activeBlock].m_pool;
-			ci.descriptorSetCount = 1;
-			ci.pSetLayouts = &layout.getHandle();
-
-			res = vkAllocateDescriptorSets(getVkDevice(), &ci, &set);
-		}
-
-		if(res == VK_SUCCESS)
-		{
-			++m_blocks[m_activeBlock].m_dsetsAllocatedCount;
-			break;
-		}
-		else if(res == VK_ERROR_OUT_OF_POOL_MEMORY)
-		{
-			++m_activeBlock;
-			if(m_activeBlock >= m_blocks.getSize())
-			{
-				createNewBlock();
-			}
-		}
-		else
-		{
-			ANKI_VK_CHECKF(res);
-		}
-
-		++iterationCount;
-	} while(iterationCount < 10);
-
-	if(iterationCount == 10)
-	{
-		ANKI_VK_LOGF("Failed to allocate descriptor set");
-	}
-}
-
-void DSAllocator::reset()
-{
-	// Trim blocks that were not used last time
-	const U32 blocksInUse = m_activeBlock + 1;
-	if(blocksInUse < m_blocks.getSize())
-	{
-		for(U32 i = blocksInUse; i < m_blocks.getSize(); ++i)
-		{
-			vkDestroyDescriptorPool(getVkDevice(), m_blocks[i].m_pool, nullptr);
-		}
-
-		m_blocks.resize(blocksInUse);
-	}
-
-	// Reset the remaining pools
-	for(Block& b : m_blocks)
-	{
-		vkResetDescriptorPool(getVkDevice(), b.m_pool, 0);
-		b.m_dsetsAllocatedCount = 0;
-	}
-
-	m_activeBlock = 0;
-}
-
-DSBindless::~DSBindless()
-{
-	ANKI_ASSERT(m_freeTexIndexCount == m_freeTexIndices.getSize() && "Forgot to unbind some textures");
-	ANKI_ASSERT(m_freeTexelBufferIndexCount == m_freeTexelBufferIndices.getSize() && "Forgot to unbind some texel buffers");
-
-	if(m_dsPool)
-	{
-		vkDestroyDescriptorPool(getVkDevice(), m_dsPool, nullptr);
-		m_dsPool = VK_NULL_HANDLE;
-		m_dset = VK_NULL_HANDLE;
-	}
-
-	if(m_layout)
-	{
-		vkDestroyDescriptorSetLayout(getVkDevice(), m_layout, nullptr);
-		m_layout = VK_NULL_HANDLE;
-	}
-}
-
-Error DSBindless::init(U32 bindlessTextureCount, U32 bindlessTextureBuffers)
-{
-	// Create the layout
-	{
-		Array<VkDescriptorSetLayoutBinding, 2> bindings = {};
-		bindings[0].binding = 0;
-		bindings[0].stageFlags = VK_SHADER_STAGE_ALL;
-		bindings[0].descriptorCount = bindlessTextureCount;
-		bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
-		bindings[1].binding = 1;
-		bindings[1].stageFlags = VK_SHADER_STAGE_ALL;
-		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 | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT
-						  | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT;
-		bindingFlags[1] = bindingFlags[0];
-
-		VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extraInfos = {};
-		extraInfos.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
-		extraInfos.bindingCount = bindingFlags.getSize();
-		extraInfos.pBindingFlags = &bindingFlags[0];
-
-		VkDescriptorSetLayoutCreateInfo ci = {};
-		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
-		ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
-		ci.bindingCount = bindings.getSize();
-		ci.pBindings = &bindings[0];
-		ci.pNext = &extraInfos;
-
-		ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &m_layout));
-	}
-
-	// Create the pool
-	{
-		Array<VkDescriptorPoolSize, 2> sizes = {};
-		sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
-		sizes[0].descriptorCount = bindlessTextureCount;
-		sizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
-		sizes[1].descriptorCount = bindlessTextureBuffers;
-
-		VkDescriptorPoolCreateInfo ci = {};
-		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
-		ci.maxSets = 1;
-		ci.poolSizeCount = sizes.getSize();
-		ci.pPoolSizes = &sizes[0];
-		ci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
-
-		ANKI_VK_CHECK(vkCreateDescriptorPool(getVkDevice(), &ci, nullptr, &m_dsPool));
-	}
-
-	// Create the descriptor set
-	{
-		VkDescriptorSetAllocateInfo ci = {};
-		ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-		ci.descriptorPool = m_dsPool;
-		ci.descriptorSetCount = 1;
-		ci.pSetLayouts = &m_layout;
-
-		ANKI_VK_CHECK(vkAllocateDescriptorSets(getVkDevice(), &ci, &m_dset));
-	}
-
-	// Init the free arrays
-	{
-		m_freeTexIndices.resize(bindlessTextureCount);
-		m_freeTexIndexCount = U16(m_freeTexIndices.getSize());
-
-		for(U32 i = 0; i < m_freeTexIndices.getSize(); ++i)
-		{
-			m_freeTexIndices[i] = U16(m_freeTexIndices.getSize() - i - 1);
-		}
-
-		m_freeTexelBufferIndices.resize(bindlessTextureBuffers);
-		m_freeTexelBufferIndexCount = U16(m_freeTexelBufferIndices.getSize());
-
-		for(U32 i = 0; i < m_freeTexelBufferIndices.getSize(); ++i)
-		{
-			m_freeTexelBufferIndices[i] = U16(m_freeTexelBufferIndices.getSize() - i - 1);
-		}
-	}
-
-	return Error::kNone;
-}
-
-U32 DSBindless::bindTexture(const VkImageView view, const VkImageLayout layout)
-{
-	ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL || layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
-
-	ANKI_ASSERT(view);
-	LockGuard<Mutex> lock(m_mtx);
-	ANKI_ASSERT(m_freeTexIndexCount > 0 && "Out of indices");
-
-	// Pop the index
-	--m_freeTexIndexCount;
-	const U16 idx = m_freeTexIndices[m_freeTexIndexCount];
-	ANKI_ASSERT(idx < m_freeTexIndices.getSize());
-
-	// Update the set
-	VkDescriptorImageInfo imageInf = {};
-	imageInf.imageView = view;
-	imageInf.imageLayout = layout;
-
-	VkWriteDescriptorSet write = {};
-	write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-	write.pNext = nullptr;
-	write.dstSet = m_dset;
-	write.dstBinding = 0;
-	write.descriptorCount = 1;
-	write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
-	write.dstArrayElement = idx;
-	write.pImageInfo = &imageInf;
-
-	vkUpdateDescriptorSets(getVkDevice(), 1, &write, 0, nullptr);
-
-	return idx;
-}
-
-U32 DSBindless::bindUniformTexelBuffer(VkBufferView view)
-{
-	ANKI_ASSERT(view);
-	LockGuard<Mutex> lock(m_mtx);
-	ANKI_ASSERT(m_freeTexelBufferIndexCount > 0 && "Out of indices");
-
-	// Pop the index
-	--m_freeTexelBufferIndexCount;
-	const U16 idx = m_freeTexelBufferIndices[m_freeTexelBufferIndexCount];
-	ANKI_ASSERT(idx < m_freeTexelBufferIndices.getSize());
-
-	// Update the set
-	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_UNIFORM_TEXEL_BUFFER;
-	write.dstArrayElement = idx;
-	write.pTexelBufferView = &view;
-
-	vkUpdateDescriptorSets(getVkDevice(), 1, &write, 0, nullptr);
-
-	return idx;
-}
-
-void DSBindless::unbindCommon(U32 idx, GrDynamicArray<U16>& freeIndices, U16& freeIndexCount)
-{
-	LockGuard<Mutex> lock(m_mtx);
-
-	ANKI_ASSERT(idx < freeIndices.getSize());
-	ANKI_ASSERT(freeIndexCount < freeIndices.getSize());
-
-	freeIndices[freeIndexCount] = U16(idx);
-	++freeIndexCount;
-
-	// Sort the free indices to minimize fragmentation
-	std::sort(&freeIndices[0], &freeIndices[0] + freeIndexCount, std::greater<U16>());
-
-	// Make sure there are no duplicates
-	for(U32 i = 1; i < freeIndexCount; ++i)
-	{
-		ANKI_ASSERT(freeIndices[i] != freeIndices[i - 1]);
-	}
-}
-
-void DSStateTracker::setBinding(U32 bindingIdx, U32 arrayIdx, const Binding& b)
-{
-	ANKI_ASSERT(bindingIdx < kMaxBindingsPerDescriptorSet);
-
-	BindingExtended& extended = m_bindings[bindingIdx];
-	Binding* out;
-
-	const Bool extendedInitializedBefore = m_bindingIsSetMask.get(bindingIdx);
-
-	if(!extendedInitializedBefore)
-	{
-		m_bindingIsSetMask.set(bindingIdx);
-		zeroMemory(extended.m_single);
-		extended.m_count = 1;
-	}
-
-	if(arrayIdx == 0) [[likely]]
-	{
-		// Array idx is zero, most common case
-		out = (extended.m_count == 1) ? &extended.m_single : &extended.m_array[0];
-	}
-	else if(arrayIdx < extended.m_count)
-	{
-		// It's (or was) an array and there enough space in thar array
-		ANKI_ASSERT(arrayIdx > 0);
-		out = &extended.m_array[arrayIdx];
-	}
-	else
-	{
-		// Need to grow
-		ANKI_ASSERT(arrayIdx > 0);
-		const U32 newSize = max(extended.m_count * 2, arrayIdx + 1);
-		Binding* newArr = newArray<Binding>(m_writeInfos.getMemoryPool(), newSize);
-
-		if(!extendedInitializedBefore)
-		{
-			memset(newArr, 0, newSize * sizeof(Binding));
-		}
-		else if(extended.m_count == 1)
-		{
-			newArr[0] = extended.m_single;
-		}
-		else
-		{
-			// Copy old to new
-			memcpy(newArr, extended.m_array, sizeof(Binding) * extended.m_count);
-
-			// Zero the rest
-			memset(newArr + extended.m_count, 0, sizeof(Binding) * (newSize - extended.m_count));
-		}
-
-		extended.m_count = newSize;
-		extended.m_array = newArr;
-
-		out = &extended.m_array[arrayIdx];
-	}
-
-	unbindBindlessDSet();
-	m_bindingDirtyMask.set(bindingIdx);
-	*out = b;
-}
-
-Bool DSStateTracker::flush(DSAllocator& allocator, VkDescriptorSet& dsHandle)
-{
-	ANKI_TRACE_SCOPED_EVENT(GrFlushDescrStateTracker);
-	ANKI_ASSERT(m_layout);
-
-	dsHandle = VK_NULL_HANDLE;
-
-	if(m_bindlessDSBound)
-	{
-		ANKI_ASSERT((m_layout->m_hash == 0 || m_layout->m_descriptorCount == 0)
-					&& "Need to have bound the bindless layout or a layout with no descriptors");
-	}
-
-	const Bool reallyBindless = m_bindlessDSBound && m_layout->m_hash == 0;
-	if(reallyBindless)
-	{
-		if(m_bindlessDSDirty || m_layoutDirty)
-		{
-			dsHandle = DSBindless::getSingleton().m_dset;
-			m_bindlessDSDirty = false;
-			m_layoutDirty = false;
-		}
-		return dsHandle != VK_NULL_HANDLE;
-	}
-
-	const Bool dirty = m_layoutDirty || (m_layout->m_activeBindings & m_bindingDirtyMask);
-	if(!dirty)
-	{
-		return false;
-	}
-
-	m_layoutDirty = false;
-	m_bindingDirtyMask = m_bindingDirtyMask & ~m_layout->m_activeBindings;
-
-	if(m_writeInfos.getSize() < m_layout->m_descriptorCount)
-	{
-		m_writeInfos.resize(m_layout->m_descriptorCount);
-	}
-
-	// Allocate the DS
-	allocator.allocate(*m_layout, dsHandle);
-
-	// Write the DS
-	VkWriteDescriptorSet writeTemplate = {};
-	writeTemplate.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-	writeTemplate.pNext = nullptr;
-	writeTemplate.dstSet = dsHandle;
-	writeTemplate.descriptorCount = 1;
-
-	U32 writeInfoIdx = 0;
-	for(U32 bindingIdx = m_layout->m_minBinding; bindingIdx <= m_layout->m_maxBinding; ++bindingIdx)
-	{
-		if(m_layout->m_activeBindings.get(bindingIdx))
-		{
-			for(U32 arrIdx = 0; arrIdx < m_layout->m_bindingArraySize[bindingIdx]; ++arrIdx)
-			{
-				VkWriteDescriptorSet& writeInfo = m_writeInfos[writeInfoIdx++];
-				ANKI_ASSERT(m_bindings[bindingIdx].m_count < kMaxU32);
-				const Binding& b = (m_bindings[bindingIdx].m_count == 1) ? m_bindings[bindingIdx].m_single : m_bindings[bindingIdx].m_array[arrIdx];
-
-				ANKI_ASSERT(b.m_type == m_layout->m_bindingDsType[bindingIdx] && "Bound the wrong type");
-
-				writeInfo = writeTemplate;
-				writeInfo.descriptorType = b.m_type;
-				writeInfo.dstArrayElement = arrIdx;
-				writeInfo.dstBinding = bindingIdx;
-
-				switch(b.m_type)
-				{
-				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
-				case VK_DESCRIPTOR_TYPE_SAMPLER:
-				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
-				{
-					writeInfo.pImageInfo = &b.m_image;
-					break;
-				}
-				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
-				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
-				{
-					writeInfo.pBufferInfo = &b.m_buffer;
-					break;
-				}
-				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
-				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
-				{
-					writeInfo.pTexelBufferView = &b.m_bufferView;
-					break;
-				}
-				case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
-				{
-					writeInfo.pNext = &b.m_as;
-					break;
-				}
-				default:
-					ANKI_ASSERT(0);
-				}
-			}
-		}
-	}
-
-	if(writeInfoIdx > 0)
-	{
-		vkUpdateDescriptorSets(getVkDevice(), writeInfoIdx, m_writeInfos.getBegin(), 0, nullptr);
-	}
-
-	return true;
-}
-
-DSLayoutFactory::DSLayoutFactory()
-{
-	DSLayout* pLayout = newInstance<DSLayout>(GrMemoryPool::getSingleton());
-	pLayout->m_handle = DSBindless::getSingleton().m_layout;
-	pLayout->m_hash = 0;
-	// The rest we don't care
-
-	m_layouts.emplaceBack(pLayout);
-}
-
-DSLayoutFactory::~DSLayoutFactory()
-{
-	for(DSLayout* l : m_layouts)
-	{
-		if(l->m_hash != 0)
-		{
-			vkDestroyDescriptorSetLayout(getVkDevice(), l->m_handle, nullptr);
-		}
-
-		deleteInstance(GrMemoryPool::getSingleton(), l);
-	}
-}
-
-Error DSLayoutFactory::getOrCreateDescriptorSetLayout(const WeakArray<DSBinding>& bindings_, const DSLayout*& layout_)
-{
-	DSLayout* layout = nullptr;
-
-	// Compute the hash for the layout
-	Array<DSBinding, kMaxBindingsPerDescriptorSet> bindings;
-	const U32 bindingCount = bindings_.getSize();
-	U64 hash;
-
-	if(bindingCount > 0)
-	{
-		// Copy to a new place because we want to sort
-		memcpy(bindings.getBegin(), bindings_.getBegin(), bindings_.getSizeInBytes());
-		std::sort(bindings.getBegin(), bindings.getBegin() + bindingCount, [](const DSBinding& a, const DSBinding& b) {
-			return a.m_binding < b.m_binding;
-		});
-
-		hash = computeHash(&bindings[0], bindings_.getSizeInBytes());
-		ANKI_ASSERT(hash != 1);
-	}
-	else
-	{
-		hash = 1;
-	}
-
-	ANKI_ASSERT(hash != 0);
-
-	// Identify if the DS is the bindless one. It is if there is at least one binding that matches the criteria
-	Bool isBindless = false;
-	if(bindingCount > 0)
-	{
-		isBindless = true;
-		for(U32 i = 0; i < bindingCount; ++i)
-		{
-			const DSBinding& binding = bindings[i];
-			if(binding.m_binding == 0 && binding.m_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
-			   && binding.m_arraySize == DSBindless::getSingleton().getMaxTextureCount())
-			{
-				// All good
-			}
-			else if(binding.m_binding == 1 && binding.m_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
-					&& binding.m_arraySize == DSBindless::getSingleton().getMaxTexelBufferCount())
-			{
-				// All good
-			}
-			else
-			{
-				isBindless = false;
-				break;
-			}
-		}
-	}
-
-	LockGuard lock(m_mtx);
-
-	if(isBindless)
-	{
-		layout = *m_layouts.getBegin();
-	}
-	else
-	{
-		// Search the cache or create it
-
-		for(DSLayout* it : m_layouts)
-		{
-			if(it->m_hash == hash)
-			{
-				layout = it;
-				break;
-			}
-		}
-
-		if(layout == nullptr)
-		{
-			// Create it
-
-			layout = newInstance<DSLayout>(GrMemoryPool::getSingleton());
-			m_layouts.emplaceBack(layout);
-			layout->m_hash = hash;
-
-			Array<VkDescriptorSetLayoutBinding, kMaxBindingsPerDescriptorSet> vkBindings;
-			VkDescriptorSetLayoutCreateInfo ci = {};
-			ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
-
-			for(U i = 0; i < bindingCount; ++i)
-			{
-				VkDescriptorSetLayoutBinding& vk = vkBindings[i];
-				const DSBinding& ak = bindings[i];
-
-				vk.binding = ak.m_binding;
-				vk.descriptorCount = ak.m_arraySize;
-				vk.descriptorType = ak.m_type;
-				vk.pImmutableSamplers = nullptr;
-				vk.stageFlags = VK_SHADER_STAGE_ALL;
-
-				ANKI_ASSERT(layout->m_activeBindings.get(ak.m_binding) == false);
-				layout->m_activeBindings.set(ak.m_binding);
-				layout->m_bindingDsType[ak.m_binding] = ak.m_type;
-				layout->m_bindingArraySize[ak.m_binding] = ak.m_arraySize;
-				layout->m_minBinding = min<U32>(layout->m_minBinding, ak.m_binding);
-				layout->m_maxBinding = max<U32>(layout->m_maxBinding, ak.m_binding);
-				layout->m_descriptorCount += ak.m_arraySize;
-			}
-
-			ci.bindingCount = bindingCount;
-			ci.pBindings = &vkBindings[0];
-
-			ANKI_VK_CHECK(vkCreateDescriptorSetLayout(getVkDevice(), &ci, nullptr, &layout->m_handle));
-		}
-	}
-
-	layout_ = layout;
-
-	return Error::kNone;
-}
-
-} // end namespace anki

+ 0 - 348
AnKi/Gr/Vulkan/VkDescriptorSetFactory.h

@@ -1,348 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Gr/Vulkan/VkCommon.h>
-#include <AnKi/Gr/Vulkan/VkBuffer.h>
-#include <AnKi/Gr/Vulkan/VkTexture.h>
-#include <AnKi/Gr/Vulkan/VkSampler.h>
-#include <AnKi/Gr/Vulkan/VkAccelerationStructure.h>
-#include <AnKi/Util/WeakArray.h>
-#include <AnKi/Util/BitSet.h>
-
-namespace anki {
-
-class DSLayout
-{
-	friend class DSStateTracker;
-	friend class DSLayoutFactory;
-	friend class DSAllocator;
-
-public:
-	const VkDescriptorSetLayout& getHandle() const
-	{
-		ANKI_ASSERT(m_handle);
-		return m_handle;
-	}
-
-private:
-	VkDescriptorSetLayout m_handle = VK_NULL_HANDLE;
-
-	U64 m_hash = 0;
-	BitSet<kMaxBindingsPerDescriptorSet, U32> m_activeBindings = {false};
-	Array<U32, kMaxBindingsPerDescriptorSet> m_bindingArraySize = {};
-	Array<VkDescriptorType, kMaxBindingsPerDescriptorSet> m_bindingDsType = {};
-	U32 m_minBinding = kMaxU32;
-	U32 m_maxBinding = 0;
-	U32 m_descriptorCount = 0;
-};
-
-/// Allocates descriptor sets.
-class DSAllocator
-{
-	friend class DSStateTracker;
-
-public:
-	DSAllocator() = default;
-
-	~DSAllocator();
-
-	void destroy()
-	{
-		for(Block& b : m_blocks)
-		{
-			ANKI_ASSERT(b.m_pool != VK_NULL_HANDLE);
-			vkDestroyDescriptorPool(getVkDevice(), b.m_pool, nullptr);
-		}
-
-		m_blocks.destroy();
-		m_activeBlock = 0;
-	}
-
-	/// Reset for reuse.
-	void reset();
-
-private:
-	class Block
-	{
-	public:
-		VkDescriptorPool m_pool = VK_NULL_HANDLE;
-		U32 m_dsetsAllocatedCount = 0;
-	};
-
-	static constexpr U32 kDescriptorSetGrowScale = 2;
-
-	GrDynamicArray<Block> m_blocks;
-
-	U32 m_activeBlock = 0;
-
-	void allocate(const DSLayout& layout, VkDescriptorSet& set);
-
-	void createNewBlock();
-};
-
-/// The bindless descriptor set.
-class DSBindless : public MakeSingleton<DSBindless>
-{
-	friend class DSStateTracker;
-	friend class DSLayoutFactory;
-
-public:
-	~DSBindless();
-
-	Error init(U32 bindlessTextureCount, U32 bindlessTextureBuffers);
-
-	/// Bind a sampled image.
-	/// @note It's thread-safe.
-	U32 bindTexture(const VkImageView view, const VkImageLayout layout);
-
-	/// Bind a uniform texel buffer.
-	/// @note It's thread-safe.
-	U32 bindUniformTexelBuffer(VkBufferView view);
-
-	/// @note It's thread-safe.
-	void unbindTexture(U32 idx)
-	{
-		unbindCommon(idx, m_freeTexIndices, m_freeTexIndexCount);
-	}
-
-	/// @note It's thread-safe.
-	void unbindUniformTexelBuffer(U32 idx)
-	{
-		unbindCommon(idx, m_freeTexelBufferIndices, m_freeTexelBufferIndexCount);
-	}
-
-	U32 getMaxTextureCount() const
-	{
-		return m_freeTexIndices.getSize();
-	}
-
-	U32 getMaxTexelBufferCount() const
-	{
-		return m_freeTexelBufferIndices.getSize();
-	}
-
-private:
-	VkDescriptorSetLayout m_layout = VK_NULL_HANDLE;
-	VkDescriptorPool m_dsPool = VK_NULL_HANDLE;
-	VkDescriptorSet m_dset = VK_NULL_HANDLE;
-	Mutex m_mtx;
-
-	GrDynamicArray<U16> m_freeTexIndices;
-	GrDynamicArray<U16> m_freeTexelBufferIndices;
-
-	U16 m_freeTexIndexCount = kMaxU16;
-	U16 m_freeTexelBufferIndexCount = kMaxU16;
-
-	void unbindCommon(U32 idx, GrDynamicArray<U16>& freeIndices, U16& freeIndexCount);
-};
-
-/// A state tracker that creates descriptors at will.
-class DSStateTracker
-{
-public:
-	void init(StackMemoryPool* pool)
-	{
-		m_writeInfos = {pool};
-	}
-
-	Bool setLayout(const DSLayout* layout)
-	{
-		ANKI_ASSERT(layout);
-		if(layout != m_layout)
-		{
-			m_layoutDirty = true;
-			m_layout = layout;
-			return true;
-		}
-
-		return false;
-	}
-
-	void setLayoutDirty()
-	{
-		m_layoutDirty = true;
-	}
-
-	void bindTexture(U32 binding, U32 arrayIdx, VkImageView handle, VkImageLayout layout)
-	{
-		ANKI_ASSERT(handle);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
-		b.m_image.imageView = handle;
-		b.m_image.imageLayout = layout;
-		b.m_image.sampler = VK_NULL_HANDLE;
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindSampler(U32 binding, U32 arrayIdx, const Sampler* sampler)
-	{
-		ANKI_ASSERT(sampler);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_SAMPLER;
-		b.m_image.sampler = static_cast<const SamplerImpl*>(sampler)->m_sampler->getHandle();
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindUniformBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range)
-	{
-		ANKI_ASSERT(buff && range > 0);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-		b.m_buffer.buffer = static_cast<const BufferImpl*>(buff)->getHandle();
-		b.m_buffer.offset = offset;
-		b.m_buffer.range = (range == kMaxPtrSize) ? VK_WHOLE_SIZE : range;
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindStorageBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range)
-	{
-		ANKI_ASSERT(buff && range > 0);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-		b.m_buffer.buffer = static_cast<const BufferImpl*>(buff)->getHandle();
-		b.m_buffer.offset = offset;
-		b.m_buffer.range = (range == kMaxPtrSize) ? VK_WHOLE_SIZE : range;
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindReadOnlyTexelBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range, Format fmt)
-	{
-		ANKI_ASSERT(buff && range > 0);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
-		b.m_bufferView = static_cast<const BufferImpl*>(buff)->getOrCreateBufferView(fmt, offset, range);
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindStorageTexture(U32 binding, U32 arrayIdx, VkImageView handle)
-	{
-		ANKI_ASSERT(handle);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
-		b.m_image.imageView = handle;
-		b.m_image.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
-		setBinding(binding, arrayIdx, b);
-	}
-
-	void bindAccelerationStructure(U32 binding, U32 arrayIdx, const AccelerationStructure* as)
-	{
-		ANKI_ASSERT(as);
-		Binding b;
-		zeroMemory(b);
-		b.m_type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
-		b.m_as.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
-		b.m_as.accelerationStructureCount = 1;
-		b.m_as.pAccelerationStructures = &static_cast<const AccelerationStructureImpl*>(as)->getHandle();
-		setBinding(binding, arrayIdx, b);
-	}
-
-	/// Forget all the rest of the bindings and bind the whole bindless descriptor set.
-	void bindBindlessDescriptorSet()
-	{
-		if(!m_bindlessDSBound)
-		{
-			m_bindlessDSBound = true;
-			m_bindlessDSDirty = true;
-		}
-	}
-
-	/// Get all the state and create a descriptor set.
-	/// @param[out] dsHandle It can be VK_NULL_HANDLE if there is no need to re-bind the descriptor set.
-	Bool flush(DSAllocator& allocator, VkDescriptorSet& dsHandle);
-
-private:
-	class Binding
-	{
-	public:
-		union
-		{
-			VkDescriptorImageInfo m_image;
-			VkDescriptorBufferInfo m_buffer;
-			VkWriteDescriptorSetAccelerationStructureKHR m_as;
-			VkBufferView m_bufferView;
-		};
-
-		VkDescriptorType m_type;
-
-		Binding()
-		{
-			// No init for perf reasons
-		}
-	};
-
-	class BindingExtended
-	{
-	public:
-		union
-		{
-			Binding m_single;
-			Binding* m_array;
-		};
-
-		U32 m_count;
-
-		BindingExtended()
-		{
-			// No init for perf reasons
-#if ANKI_ASSERTIONS_ENABLED
-			m_count = kMaxU32;
-#endif
-		}
-	};
-
-	const DSLayout* m_layout = nullptr;
-
-	Array<BindingExtended, kMaxBindingsPerDescriptorSet> m_bindings;
-
-	BitSet<kMaxBindingsPerDescriptorSet, U32> m_bindingIsSetMask = {false};
-	BitSet<kMaxBindingsPerDescriptorSet, U32> m_bindingDirtyMask = {true};
-	Bool m_bindlessDSDirty = true;
-	Bool m_bindlessDSBound = false;
-	Bool m_layoutDirty = true;
-
-	DynamicArray<VkWriteDescriptorSet, MemoryPoolPtrWrapper<StackMemoryPool>> m_writeInfos;
-
-	void unbindBindlessDSet()
-	{
-		m_bindlessDSBound = false;
-	}
-
-	void setBinding(U32 bindingIdx, U32 arrayIdx, const Binding& b);
-};
-
-class DSBinding
-{
-public:
-	VkDescriptorType m_type = VK_DESCRIPTOR_TYPE_MAX_ENUM;
-	U16 m_arraySize = 0;
-	U8 m_binding = kMaxU8;
-	U8 m_padding = 0;
-};
-static_assert(sizeof(DSBinding) == 8, "Should be packed because it will be hashed");
-
-class DSLayoutFactory : public MakeSingleton<DSLayoutFactory>
-{
-public:
-	DSLayoutFactory();
-
-	~DSLayoutFactory();
-
-	/// @note It's thread-safe.
-	Error getOrCreateDescriptorSetLayout(const WeakArray<DSBinding>& bindings, const DSLayout*& layout);
-
-private:
-	GrDynamicArray<DSLayout*> m_layouts;
-	Mutex m_mtx;
-};
-
-} // end namespace anki

+ 2 - 2
AnKi/Gr/Vulkan/VkFrameGarbageCollector.cpp

@@ -5,7 +5,7 @@
 
 
 #include <AnKi/Gr/Vulkan/VkFrameGarbageCollector.h>
 #include <AnKi/Gr/Vulkan/VkFrameGarbageCollector.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
 #include <AnKi/Gr/Fence.h>
 #include <AnKi/Gr/Fence.h>
 
 
 namespace anki {
 namespace anki {
@@ -50,7 +50,7 @@ void FrameGarbageCollector::collectGarbage()
 
 
 			for(U32 bindlessIndex : textureGarbage->m_bindlessIndices)
 			for(U32 bindlessIndex : textureGarbage->m_bindlessIndices)
 			{
 			{
-				DSBindless::getSingleton().unbindTexture(bindlessIndex);
+				BindlessDescriptorSet::getSingleton().unbindTexture(bindlessIndex);
 			}
 			}
 
 
 			if(textureGarbage->m_imageHandle)
 			if(textureGarbage->m_imageHandle)

+ 61 - 63
AnKi/Gr/Vulkan/VkGrManager.cpp

@@ -21,6 +21,7 @@
 #include <AnKi/Gr/Vulkan/VkGrUpscaler.h>
 #include <AnKi/Gr/Vulkan/VkGrUpscaler.h>
 #include <AnKi/Gr/Vulkan/VkFence.h>
 #include <AnKi/Gr/Vulkan/VkFence.h>
 #include <AnKi/Gr/Vulkan/VkGpuMemoryManager.h>
 #include <AnKi/Gr/Vulkan/VkGpuMemoryManager.h>
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
 
 
 #include <AnKi/Window/NativeWindow.h>
 #include <AnKi/Window/NativeWindow.h>
 #if ANKI_WINDOWING_SYSTEM_SDL
 #if ANKI_WINDOWING_SYSTEM_SDL
@@ -337,9 +338,8 @@ GrManagerImpl::~GrManagerImpl()
 	m_frameGarbageCollector.destroy();
 	m_frameGarbageCollector.destroy();
 
 
 	GpuMemoryManager::freeSingleton();
 	GpuMemoryManager::freeSingleton();
-	PipelineLayoutFactory::freeSingleton();
-	DSLayoutFactory::freeSingleton();
-	DSBindless::freeSingleton();
+	PipelineLayoutFactory2::freeSingleton();
+	BindlessDescriptorSet::freeSingleton();
 	PipelineCache::freeSingleton();
 	PipelineCache::freeSingleton();
 	FenceFactory::freeSingleton();
 	FenceFactory::freeSingleton();
 
 
@@ -463,12 +463,10 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 		}
 	}
 	}
 
 
-	DSBindless::allocateSingleton();
-	ANKI_CHECK(DSBindless::getSingleton().init(kMaxBindlessTextures, kMaxBindlessReadonlyTextureBuffers));
+	BindlessDescriptorSet::allocateSingleton();
+	ANKI_CHECK(BindlessDescriptorSet::getSingleton().init());
 
 
-	DSLayoutFactory::allocateSingleton();
-
-	PipelineLayoutFactory::allocateSingleton();
+	PipelineLayoutFactory2::allocateSingleton();
 
 
 	m_frameGarbageCollector.init();
 	m_frameGarbageCollector.init();
 
 
@@ -1707,61 +1705,6 @@ void GrManagerImpl::trySetVulkanHandleName(CString name, VkObjectType type, U64
 	}
 	}
 }
 }
 
 
-VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
-											   [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
-											   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)
-{
-#if ANKI_PLATFORM_MOBILE
-	if(pCallbackData->messageIdNumber == 101294395)
-	{
-		// Interface mismatch error. Eg vert shader is writing to varying that is not consumed by frag. Ignore this
-		// stupid error because I'm not going to create more shader variants to fix it. Especially when mobile drivers
-		// do linking anyway. On desktop just enable the maintenance4 extension
-		return false;
-	}
-#endif
-
-	if(pCallbackData->messageIdNumber == 1944932341 || pCallbackData->messageIdNumber == 1303270965)
-	{
-		// Not sure why I'm getting that
-		return false;
-	}
-
-	// Get all names of affected objects
-	GrString objectNames;
-	if(pCallbackData->objectCount)
-	{
-		for(U32 i = 0; i < pCallbackData->objectCount; ++i)
-		{
-			const Char* name = pCallbackData->pObjects[i].pObjectName;
-			objectNames += (name) ? name : "?";
-			if(i < pCallbackData->objectCount - 1)
-			{
-				objectNames += ", ";
-			}
-		}
-	}
-	else
-	{
-		objectNames = "N/A";
-	}
-
-	if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
-	{
-		ANKI_VK_LOGE("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
-	}
-	else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
-	{
-		ANKI_VK_LOGW("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
-	}
-	else
-	{
-		ANKI_VK_LOGI("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
-	}
-
-	return false;
-}
-
 void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, U64 hash) const
 void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, U64 hash) const
 {
 {
 	if(printPipelineShaderInfoInternal(ppline, name, hash))
 	if(printPipelineShaderInfoInternal(ppline, name, hash))
@@ -1880,4 +1823,59 @@ Error GrManagerImpl::initSurface()
 	return Error::kNone;
 	return Error::kNone;
 }
 }
 
 
+VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+											   [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+											   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)
+{
+#if ANKI_PLATFORM_MOBILE
+	if(pCallbackData->messageIdNumber == 101294395)
+	{
+		// Interface mismatch error. Eg vert shader is writing to varying that is not consumed by frag. Ignore this
+		// stupid error because I'm not going to create more shader variants to fix it. Especially when mobile drivers
+		// do linking anyway. On desktop just enable the maintenance4 extension
+		return false;
+	}
+#endif
+
+	if(pCallbackData->messageIdNumber == 1944932341 || pCallbackData->messageIdNumber == 1303270965)
+	{
+		// Not sure why I'm getting that
+		return false;
+	}
+
+	// Get all names of affected objects
+	GrString objectNames;
+	if(pCallbackData->objectCount)
+	{
+		for(U32 i = 0; i < pCallbackData->objectCount; ++i)
+		{
+			const Char* name = pCallbackData->pObjects[i].pObjectName;
+			objectNames += (name) ? name : "?";
+			if(i < pCallbackData->objectCount - 1)
+			{
+				objectNames += ", ";
+			}
+		}
+	}
+	else
+	{
+		objectNames = "N/A";
+	}
+
+	if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
+	{
+		ANKI_VK_LOGE("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
+	}
+	else if(messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
+	{
+		ANKI_VK_LOGW("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
+	}
+	else
+	{
+		ANKI_VK_LOGI("VK debug report: %s. Affected objects: %s", pCallbackData->pMessage, objectNames.cstr());
+	}
+
+	return false;
+}
+
 } // end namespace anki
 } // end namespace anki

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

@@ -5,7 +5,6 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
 #include <AnKi/Gr/ShaderProgram.h>
 #include <AnKi/Gr/ShaderProgram.h>
 #include <AnKi/Gr/Vulkan/VkShaderProgram.h>
 #include <AnKi/Gr/Vulkan/VkShaderProgram.h>
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Util/HashMap.h>

+ 0 - 76
AnKi/Gr/Vulkan/VkPipelineLayoutFactory.cpp

@@ -1,76 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Gr/Vulkan/VkPipelineLayoutFactory.h>
-
-namespace anki {
-
-void PipelineLayoutFactory::destroy()
-{
-	while(!m_layouts.isEmpty())
-	{
-		auto it = m_layouts.getBegin();
-		VkPipelineLayout handle = *it;
-		m_layouts.erase(it);
-
-		vkDestroyPipelineLayout(getVkDevice(), handle, nullptr);
-	}
-}
-
-Error PipelineLayoutFactory::newPipelineLayout(const WeakArray<const DSLayout*>& dsetLayouts, U32 pushConstantsSize, PipelineLayout& layout)
-{
-	U64 hash = computeHash(&pushConstantsSize, sizeof(pushConstantsSize));
-	Array<VkDescriptorSetLayout, kMaxDescriptorSets> vkDsetLayouts;
-	U32 dsetLayoutCount = 0;
-	for(const DSLayout* dl : dsetLayouts)
-	{
-		vkDsetLayouts[dsetLayoutCount++] = dl->getHandle();
-	}
-
-	if(dsetLayoutCount > 0)
-	{
-		hash = appendHash(&vkDsetLayouts[0], sizeof(vkDsetLayouts[0]) * dsetLayoutCount, hash);
-	}
-
-	LockGuard<Mutex> lock(m_layoutsMtx);
-
-	auto it = m_layouts.find(hash);
-	if(it != m_layouts.getEnd())
-	{
-		// Found it
-
-		layout.m_handle = *it;
-	}
-	else
-	{
-		// Not found, create new
-
-		VkPipelineLayoutCreateInfo ci = {};
-		ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
-		ci.pSetLayouts = &vkDsetLayouts[0];
-		ci.setLayoutCount = dsetLayoutCount;
-
-		VkPushConstantRange pushConstantRange;
-		if(pushConstantsSize > 0)
-		{
-			pushConstantRange.offset = 0;
-			pushConstantRange.size = pushConstantsSize;
-			pushConstantRange.stageFlags = VK_SHADER_STAGE_ALL;
-			ci.pushConstantRangeCount = 1;
-			ci.pPushConstantRanges = &pushConstantRange;
-		}
-
-		VkPipelineLayout pplineLayHandle;
-		ANKI_VK_CHECK(vkCreatePipelineLayout(getVkDevice(), &ci, nullptr, &pplineLayHandle));
-
-		m_layouts.emplace(hash, pplineLayHandle);
-
-		layout.m_handle = pplineLayHandle;
-	}
-
-	return Error::kNone;
-}
-
-} // end namespace anki

+ 0 - 53
AnKi/Gr/Vulkan/VkPipelineLayoutFactory.h

@@ -1,53 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
-#include <AnKi/Util/HashMap.h>
-
-namespace anki {
-
-/// @addtogroup vulkan
-/// @{
-
-class PipelineLayout
-{
-	friend class PipelineLayoutFactory;
-
-public:
-	VkPipelineLayout getHandle() const
-	{
-		ANKI_ASSERT(m_handle);
-		return m_handle;
-	}
-
-private:
-	VkPipelineLayout m_handle = VK_NULL_HANDLE;
-};
-
-/// Creator of pipeline layouts.
-class PipelineLayoutFactory : public MakeSingleton<PipelineLayoutFactory>
-{
-public:
-	PipelineLayoutFactory() = default;
-
-	~PipelineLayoutFactory()
-	{
-		destroy();
-	}
-
-	/// @note It's thread-safe.
-	Error newPipelineLayout(const WeakArray<const DSLayout*>& dsetLayouts, U32 pushConstantsSize, PipelineLayout& layout);
-
-private:
-	GrHashMap<U64, VkPipelineLayout> m_layouts;
-	Mutex m_layoutsMtx;
-
-	void destroy();
-};
-/// @}
-
-} // end namespace anki

+ 5 - 11
AnKi/Gr/Vulkan/VkShader.cpp

@@ -29,22 +29,21 @@ Shader* Shader::newInstance(const ShaderInitInfo& init)
 
 
 ShaderImpl::~ShaderImpl()
 ShaderImpl::~ShaderImpl()
 {
 {
-	if(m_handle)
-	{
-		vkDestroyShaderModule(getVkDevice(), m_handle, nullptr);
-	}
 }
 }
 
 
 Error ShaderImpl::init(const ShaderInitInfo& inf)
 Error ShaderImpl::init(const ShaderInitInfo& inf)
 {
 {
-	ANKI_ASSERT(inf.m_binary.getSize() > 0);
-	ANKI_ASSERT(m_handle == VK_NULL_HANDLE);
+	inf.validate();
+	ANKI_ASSERT((inf.m_binary.getSize() % sizeof(U32)) == 0);
 	m_shaderType = inf.m_shaderType;
 	m_shaderType = inf.m_shaderType;
 	m_hasDiscard = inf.m_reflection.m_fragment.m_discards;
 	m_hasDiscard = inf.m_reflection.m_fragment.m_discards;
 	m_shaderBinarySize = U32(inf.m_binary.getSizeInBytes());
 	m_shaderBinarySize = U32(inf.m_binary.getSizeInBytes());
 	m_reflection = inf.m_reflection;
 	m_reflection = inf.m_reflection;
 	m_reflection.validate();
 	m_reflection.validate();
 
 
+	m_spirvBin.resize(inf.m_binary.getSize() / sizeof(U32));
+	memcpy(m_spirvBin.getBegin(), inf.m_binary.getBegin(), inf.m_binary.getSizeInBytes());
+
 #if ANKI_DUMP_SHADERS
 #if ANKI_DUMP_SHADERS
 	{
 	{
 		StringRaii fnameSpirv(getAllocator());
 		StringRaii fnameSpirv(getAllocator());
@@ -56,11 +55,6 @@ Error ShaderImpl::init(const ShaderInitInfo& inf)
 	}
 	}
 #endif
 #endif
 
 
-	VkShaderModuleCreateInfo ci = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, nullptr, 0, inf.m_binary.getSize(),
-								   reinterpret_cast<const uint32_t*>(&inf.m_binary[0])};
-
-	ANKI_VK_CHECK(vkCreateShaderModule(getVkDevice(), &ci, nullptr, &m_handle));
-
 	return Error::kNone;
 	return Error::kNone;
 }
 }
 
 

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

@@ -6,7 +6,7 @@
 #pragma once
 #pragma once
 
 
 #include <AnKi/Gr/Shader.h>
 #include <AnKi/Gr/Shader.h>
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
+#include <AnKi/Gr/Vulkan/VkCommon.h>
 #include <AnKi/Util/BitSet.h>
 #include <AnKi/Util/BitSet.h>
 
 
 namespace anki {
 namespace anki {
@@ -18,8 +18,8 @@ namespace anki {
 class ShaderImpl final : public Shader
 class ShaderImpl final : public Shader
 {
 {
 public:
 public:
-	VkShaderModule m_handle = VK_NULL_HANDLE;
 	ShaderReflection m_reflection;
 	ShaderReflection m_reflection;
+	GrDynamicArray<U32> m_spirvBin;
 
 
 	ShaderImpl(CString name)
 	ShaderImpl(CString name)
 		: Shader(name)
 		: Shader(name)

+ 240 - 44
AnKi/Gr/Vulkan/VkShaderProgram.cpp

@@ -8,9 +8,100 @@
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
 #include <AnKi/Gr/Vulkan/VkPipelineFactory.h>
 #include <AnKi/Gr/Vulkan/VkPipelineFactory.h>
 #include <AnKi/Gr/BackendCommon/Functions.h>
 #include <AnKi/Gr/BackendCommon/Functions.h>
+#include <AnKi/Gr/Vulkan/VkBuffer.h>
+
+#include <AnKi/ShaderCompiler/Dxc.h>
+#include <ThirdParty/SpirvCross/spirv.hpp>
 
 
 namespace anki {
 namespace anki {
 
 
+/// Used to avoid keeping alive many shader modules that are essentially the same code. Mainly used to save memory because graphics ShaderPrograms
+/// need to keep alive the shader modules for later when the pipeline is created.
+class ShaderModuleFactory : public MakeSingletonSimple<ShaderModuleFactory>
+{
+public:
+	~ShaderModuleFactory()
+	{
+		ANKI_ASSERT(m_entries.getSize() == 0 && "Forgot to release shader modules");
+	}
+
+	/// @note Thread-safe
+	VkShaderModule getOrCreateShaderModule(ConstWeakArray<U32> spirv)
+	{
+		const U64 hash = computeHash(spirv.getBegin(), spirv.getSizeInBytes());
+
+		LockGuard lock(m_mtx);
+
+		Entry* entry = nullptr;
+		for(Entry& e : m_entries)
+		{
+			if(e.m_hash == hash)
+			{
+				entry = &e;
+				break;
+			}
+		}
+
+		if(entry)
+		{
+			++entry->m_refcount;
+			return entry->m_module;
+		}
+		else
+		{
+			VkShaderModuleCreateInfo ci = {};
+			ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+			ci.codeSize = spirv.getSizeInBytes();
+			ci.pCode = spirv.getBegin();
+
+			Entry entry;
+			ANKI_VK_CHECKF(vkCreateShaderModule(getVkDevice(), &ci, nullptr, &entry.m_module));
+
+			entry.m_hash = hash;
+			m_entries.emplaceBack(entry);
+
+			return entry.m_module;
+		}
+	}
+
+	/// @note Thread-safe
+	void releaseShaderModule(VkShaderModule smodule)
+	{
+		LockGuard lock(m_mtx);
+
+		U32 idx = kMaxU32;
+		for(U32 i = 0; i < m_entries.getSize(); ++i)
+		{
+			if(m_entries[i].m_module == smodule)
+			{
+				idx = i;
+				break;
+			}
+		}
+
+		ANKI_ASSERT(idx != kMaxU32);
+		ANKI_ASSERT(m_entries[idx].m_refcount > 0);
+		--m_entries[idx].m_refcount;
+		if(m_entries[idx].m_refcount == 0)
+		{
+			vkDestroyShaderModule(getVkDevice(), m_entries[idx].m_module, nullptr);
+			m_entries.erase(m_entries.getBegin() + idx);
+		}
+	}
+
+private:
+	class Entry
+	{
+	public:
+		U64 m_hash = 0;
+		VkShaderModule m_module = 0;
+		U32 m_refcount = 1;
+	};
+
+	GrDynamicArray<Entry> m_entries;
+	Mutex m_mtx;
+};
+
 ShaderProgram* ShaderProgram::newInstance(const ShaderProgramInitInfo& init)
 ShaderProgram* ShaderProgram::newInstance(const ShaderProgramInitInfo& init)
 {
 {
 	ShaderProgramImpl* impl = anki::newInstance<ShaderProgramImpl>(GrMemoryPool::getSingleton(), init.getName());
 	ShaderProgramImpl* impl = anki::newInstance<ShaderProgramImpl>(GrMemoryPool::getSingleton(), init.getName());
@@ -35,6 +126,18 @@ Buffer& ShaderProgram::getShaderGroupHandlesGpuBuffer() const
 
 
 ShaderProgramImpl::~ShaderProgramImpl()
 ShaderProgramImpl::~ShaderProgramImpl()
 {
 {
+	const Bool graphicsProg = !!(m_shaderTypes & ShaderTypeBit::kAllGraphics);
+	if(graphicsProg)
+	{
+		for(const VkPipelineShaderStageCreateInfo& ci : m_graphics.m_shaderCreateInfos)
+		{
+			if(ci.module != 0)
+			{
+				ShaderModuleFactory::getSingleton().releaseShaderModule(ci.module);
+			}
+		}
+	}
+
 	if(m_graphics.m_pplineFactory)
 	if(m_graphics.m_pplineFactory)
 	{
 	{
 		m_graphics.m_pplineFactory->destroy();
 		m_graphics.m_pplineFactory->destroy();
@@ -133,58 +236,46 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_CHECK(linkShaderReflection(m_refl, simpl.m_reflection, m_refl));
+			ANKI_CHECK(ShaderReflection::linkShaderReflection(m_refl, simpl.m_reflection, m_refl));
 		}
 		}
 
 
 		m_refl.validate();
 		m_refl.validate();
 	}
 	}
 
 
-	// Get bindings
+	// Rewite SPIR-V to fix the bindings
+	//
+	GrDynamicArray<GrDynamicArray<U32>> rewrittenSpirvs;
+	rewriteSpirv(m_refl.m_descriptor, rewrittenSpirvs);
+
+	// Create the shader modules
 	//
 	//
-	Array2d<DSBinding, kMaxDescriptorSets, kMaxBindingsPerDescriptorSet> bindings;
-	Array<U32, kMaxDescriptorSets> counts = {};
-	U32 descriptorSetCount = 0;
-	for(U32 set = 0; set < kMaxDescriptorSets; ++set)
+	const Bool graphicsProg = !!(m_shaderTypes & ShaderTypeBit::kAllGraphics);
+	GrDynamicArray<VkShaderModule> shaderModules;
+	shaderModules.resize(m_shaders.getSize());
+	for(U32 ishader = 0; ishader < shaderModules.getSize(); ++ishader)
 	{
 	{
-		for(U8 binding = 0; m_refl.m_descriptorSetMask.get(set) && binding < kMaxBindingsPerDescriptorSet; ++binding)
+		if(graphicsProg)
 		{
 		{
-			if(m_refl.m_descriptorArraySizes[set][binding])
-			{
-				DSBinding b;
-				b.m_arraySize = m_refl.m_descriptorArraySizes[set][binding];
-				b.m_binding = binding;
-				b.m_type = convertDescriptorType(m_refl.m_descriptorTypes[set][binding], m_refl.m_descriptorFlags[set][binding]);
-
-				bindings[set][counts[set]++] = b;
-			}
+			// Graphics prog, need to keep the modules alive for later
+			shaderModules[ishader] = ShaderModuleFactory::getSingleton().getOrCreateShaderModule(rewrittenSpirvs[ishader]);
 		}
 		}
-
-		// We may end up with ppline layouts with "empty" dslayouts. That's fine, we want it.
-		if(counts[set])
+		else
 		{
 		{
-			descriptorSetCount = set + 1;
-		}
-	}
+			VkShaderModuleCreateInfo ci = {};
+			ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+			ci.codeSize = rewrittenSpirvs[ishader].getSizeInBytes();
+			ci.pCode = rewrittenSpirvs[ishader].getBegin();
 
 
-	// Create the descriptor set layouts
-	//
-	for(U32 set = 0; set < descriptorSetCount; ++set)
-	{
-		ANKI_CHECK(DSLayoutFactory::getSingleton().getOrCreateDescriptorSetLayout(
-			WeakArray<DSBinding>((counts[set]) ? &bindings[set][0] : nullptr, counts[set]), m_descriptorSetLayouts[set]));
-
-		// Even if the dslayout is empty we will have to list it because we'll have to bind a DS for it.
-		m_refl.m_descriptorSetMask.set(set);
+			ANKI_VK_CHECK(vkCreateShaderModule(getVkDevice(), &ci, nullptr, &shaderModules[ishader]));
+		}
 	}
 	}
 
 
 	// Create the ppline layout
 	// Create the ppline layout
 	//
 	//
-	WeakArray<const DSLayout*> dsetLayouts((descriptorSetCount) ? &m_descriptorSetLayouts[0] : nullptr, descriptorSetCount);
-	ANKI_CHECK(PipelineLayoutFactory::getSingleton().newPipelineLayout(dsetLayouts, m_refl.m_descriptor.m_pushConstantsSize, m_pplineLayout));
+	ANKI_CHECK(PipelineLayoutFactory2::getSingleton().getOrCreatePipelineLayout(m_refl.m_descriptor, m_pplineLayout));
 
 
 	// Get some masks
 	// Get some masks
 	//
 	//
-	const Bool graphicsProg = !!(m_shaderTypes & ShaderTypeBit::kAllGraphics);
 	if(graphicsProg)
 	if(graphicsProg)
 	{
 	{
 		const U32 attachmentCount = m_refl.m_fragment.m_colorAttachmentWritemask.getSetBitCount();
 		const U32 attachmentCount = m_refl.m_fragment.m_colorAttachmentWritemask.getSetBitCount();
@@ -198,16 +289,16 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	//
 	if(graphicsProg)
 	if(graphicsProg)
 	{
 	{
-		for(const ShaderPtr& shader : m_shaders)
+		for(U32 ishader = 0; ishader < m_shaders.getSize(); ++ishader)
 		{
 		{
-			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*shader);
+			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*m_shaders[ishader]);
 
 
 			VkPipelineShaderStageCreateInfo& createInf = m_graphics.m_shaderCreateInfos[m_graphics.m_shaderCreateInfoCount++];
 			VkPipelineShaderStageCreateInfo& createInf = m_graphics.m_shaderCreateInfos[m_graphics.m_shaderCreateInfoCount++];
 			createInf = {};
 			createInf = {};
 			createInf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
 			createInf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
-			createInf.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << shader->getShaderType())));
+			createInf.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << shaderImpl.getShaderType())));
 			createInf.pName = "main";
 			createInf.pName = "main";
-			createInf.module = shaderImpl.m_handle;
+			createInf.module = shaderModules[ishader];
 		}
 		}
 	}
 	}
 
 
@@ -222,8 +313,6 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	//
 	if(!!(m_shaderTypes & ShaderTypeBit::kCompute))
 	if(!!(m_shaderTypes & ShaderTypeBit::kCompute))
 	{
 	{
-		const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*m_shaders[0]);
-
 		VkComputePipelineCreateInfo ci = {};
 		VkComputePipelineCreateInfo ci = {};
 
 
 		if(!!(getGrManagerImpl().getExtensions() & VulkanExtensions::kKHR_pipeline_executable_properties))
 		if(!!(getGrManagerImpl().getExtensions() & VulkanExtensions::kKHR_pipeline_executable_properties))
@@ -232,12 +321,12 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		}
 		}
 
 
 		ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
 		ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
-		ci.layout = m_pplineLayout.getHandle();
+		ci.layout = m_pplineLayout->getHandle();
 
 
 		ci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
 		ci.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
 		ci.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
 		ci.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
 		ci.stage.pName = "main";
 		ci.stage.pName = "main";
-		ci.stage.module = shaderImpl.m_handle;
+		ci.stage.module = shaderModules[0];
 
 
 		ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
 		ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
 		ANKI_VK_CHECK(vkCreateComputePipelines(getVkDevice(), PipelineCache::getSingleton().m_cacheHandle, 1, &ci, nullptr, &m_compute.m_ppline));
 		ANKI_VK_CHECK(vkCreateComputePipelines(getVkDevice(), PipelineCache::getSingleton().m_cacheHandle, 1, &ci, nullptr, &m_compute.m_ppline));
@@ -260,7 +349,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 			stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
 			stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
 			stage.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << impl.getShaderType())));
 			stage.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << impl.getShaderType())));
 			stage.pName = "main";
 			stage.pName = "main";
-			stage.module = impl.m_handle;
+			stage.module = shaderModules[i];
 		}
 		}
 
 
 		// Create groups
 		// Create groups
@@ -320,7 +409,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		ci.groupCount = groups.getSize();
 		ci.groupCount = groups.getSize();
 		ci.pGroups = &groups[0];
 		ci.pGroups = &groups[0];
 		ci.maxPipelineRayRecursionDepth = inf.m_rayTracingShaders.m_maxRecursionDepth;
 		ci.maxPipelineRayRecursionDepth = inf.m_rayTracingShaders.m_maxRecursionDepth;
-		ci.layout = m_pplineLayout.getHandle();
+		ci.layout = m_pplineLayout->getHandle();
 
 
 		{
 		{
 			ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
 			ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
@@ -365,7 +454,114 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		}
 		}
 	}
 	}
 
 
+	// Non graphics programs have created their pipeline, destroy the shader modules
+	//
+	if(!graphicsProg)
+	{
+		for(VkShaderModule smodule : shaderModules)
+		{
+			vkDestroyShaderModule(getVkDevice(), smodule, nullptr);
+		}
+	}
+
 	return Error::kNone;
 	return Error::kNone;
 }
 }
 
 
+void ShaderProgramImpl::rewriteSpirv(ShaderReflectionDescriptorRelated& refl, GrDynamicArray<GrDynamicArray<U32>>& rewrittenSpirvs)
+{
+	// Find a binding for the bindless DS
+	if(refl.m_hasVkBindlessDescriptorSet)
+	{
+		for(U8 iset = 0; iset < kMaxDescriptorSets; ++iset)
+		{
+			if(refl.m_bindingCounts[iset] == 0)
+			{
+				refl.m_vkBindlessDescriptorSet = iset;
+				break;
+			}
+		}
+	}
+
+	// Re-write all SPIRVs and compute the new bindings
+	rewrittenSpirvs.resize(m_shaders.getSize());
+	Bool hasBindless = false;
+	Array<U16, kMaxDescriptorSets> vkBindingCount = {};
+	for(U32 ishader = 0; ishader < m_shaders.getSize(); ++ishader)
+	{
+		ConstWeakArray<U32> inSpirv = static_cast<const ShaderImpl&>(*m_shaders[ishader]).m_spirvBin;
+		GrDynamicArray<U32>& outSpv = rewrittenSpirvs[ishader];
+
+		outSpv.resize(inSpirv.getSize());
+		memcpy(outSpv.getBegin(), inSpirv.getBegin(), inSpirv.getSizeInBytes());
+
+		visitSpirv<WeakArray>(WeakArray<U32>(outSpv), [&](U32 cmd, WeakArray<U32> instructions) {
+			if(cmd == spv::OpDecorate && instructions[1] == spv::DecorationBinding
+			   && instructions[2] >= kDxcVkBindingShifts[0][HlslResourceType::kFirst]
+			   && instructions[2] < kDxcVkBindingShifts[kMaxDescriptorSets - 1][HlslResourceType::kCount - 1])
+			{
+				const U32 binding = instructions[2];
+
+				// Look at the binding and derive a few things. See the DXC compilation on what they mean
+				U32 set = kMaxDescriptorSets;
+				HlslResourceType hlslResourceType = HlslResourceType::kCount;
+				for(set = 0; set < kMaxDescriptorSets; ++set)
+				{
+					for(HlslResourceType hlslResourceType_ : EnumIterable<HlslResourceType>())
+					{
+						if(binding >= kDxcVkBindingShifts[set][hlslResourceType_] && binding < kDxcVkBindingShifts[set][hlslResourceType_] + 1000)
+						{
+							hlslResourceType = hlslResourceType_;
+							break;
+						}
+					}
+
+					if(hlslResourceType != HlslResourceType::kCount)
+					{
+						break;
+					}
+				}
+
+				ANKI_ASSERT(set < kMaxDescriptorSets);
+				ANKI_ASSERT(hlslResourceType < HlslResourceType::kCount);
+				const U32 registerBindingPoint = binding - kDxcVkBindingShifts[set][hlslResourceType];
+
+				// Find the binding
+				U32 foundBindingIdx = kMaxU32;
+				for(U32 i = 0; i < refl.m_bindingCounts[set]; ++i)
+				{
+					const ShaderReflectionBinding& x = refl.m_bindings[set][i];
+					if(x.m_registerBindingPoint == registerBindingPoint && hlslResourceType == descriptorTypeToHlslResourceType(x.m_type, x.m_flags))
+					{
+						ANKI_ASSERT(foundBindingIdx == kMaxU32);
+						foundBindingIdx = i;
+					}
+				}
+
+				// Rewrite it
+				ANKI_ASSERT(foundBindingIdx != kMaxU32);
+				if(refl.m_bindings[set][foundBindingIdx].m_vkBinding != kMaxU16)
+				{
+					// Binding was set in another shader, just rewrite the SPIR-V
+					instructions[2] = refl.m_bindings[set][foundBindingIdx].m_vkBinding;
+				}
+				else
+				{
+					// Binding is new
+					refl.m_bindings[set][foundBindingIdx].m_vkBinding = vkBindingCount[set];
+					instructions[2] = vkBindingCount[set];
+					++vkBindingCount[set];
+				}
+			}
+			else if(cmd == spv::OpDecorate && instructions[1] == spv::DecorationDescriptorSet && instructions[2] == kDxcVkBindlessRegisterSpace)
+			{
+				// Bindless set, rewrite its set
+				instructions[2] = refl.m_vkBindlessDescriptorSet;
+				hasBindless = true;
+			}
+		});
+	}
+
+	ANKI_ASSERT(hasBindless == refl.m_hasVkBindlessDescriptorSet);
+}
+
 } // end namespace anki
 } // end namespace anki

+ 7 - 12
AnKi/Gr/Vulkan/VkShaderProgram.h

@@ -6,8 +6,8 @@
 #pragma once
 #pragma once
 
 
 #include <AnKi/Gr/ShaderProgram.h>
 #include <AnKi/Gr/ShaderProgram.h>
-#include <AnKi/Gr/Vulkan/VkPipelineLayoutFactory.h>
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
+#include <AnKi/Gr/Vulkan/VkBuffer.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -42,15 +42,9 @@ public:
 		return &m_graphics.m_shaderCreateInfos[0];
 		return &m_graphics.m_shaderCreateInfos[0];
 	}
 	}
 
 
-	const PipelineLayout& getPipelineLayout() const
+	const PipelineLayout2& getPipelineLayout() const
 	{
 	{
-		return m_pplineLayout;
-	}
-
-	const DSLayout& getDescriptorSetLayout(U32 set) const
-	{
-		ANKI_ASSERT(m_descriptorSetLayouts[set]);
-		return *m_descriptorSetLayouts[set];
+		return *m_pplineLayout;
 	}
 	}
 
 
 	const ShaderReflection& getReflectionInfo() const
 	const ShaderReflection& getReflectionInfo() const
@@ -103,8 +97,7 @@ public:
 private:
 private:
 	GrDynamicArray<ShaderPtr> m_shaders;
 	GrDynamicArray<ShaderPtr> m_shaders;
 
 
-	PipelineLayout m_pplineLayout = {};
-	Array<const DSLayout*, kMaxDescriptorSets> m_descriptorSetLayouts = {};
+	PipelineLayout2* m_pplineLayout = nullptr;
 
 
 	ShaderReflection m_refl;
 	ShaderReflection m_refl;
 
 
@@ -130,6 +123,8 @@ private:
 		U32 m_missShaderCount = 0;
 		U32 m_missShaderCount = 0;
 		BufferPtr m_allHandlesBuff;
 		BufferPtr m_allHandlesBuff;
 	} m_rt;
 	} m_rt;
+
+	void rewriteSpirv(ShaderReflectionDescriptorRelated& refl, GrDynamicArray<GrDynamicArray<U32>>& rewrittenSpirvs);
 };
 };
 /// @}
 /// @}
 
 

+ 2 - 2
AnKi/Gr/Vulkan/VkTexture.cpp

@@ -5,7 +5,7 @@
 
 
 #include <AnKi/Gr/Vulkan/VkTexture.h>
 #include <AnKi/Gr/Vulkan/VkTexture.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
 #include <AnKi/Gr/Vulkan/VkGrManager.h>
-#include <AnKi/Gr/Vulkan/VkDescriptorSetFactory.h>
+#include <AnKi/Gr/Vulkan/VkDescriptor.h>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -33,7 +33,7 @@ U32 Texture::getOrCreateBindlessTextureIndex(const TextureSubresourceDescriptor&
 
 
 	if(entry.m_bindlessIndex == kMaxU32) [[unlikely]]
 	if(entry.m_bindlessIndex == kMaxU32) [[unlikely]]
 	{
 	{
-		entry.m_bindlessIndex = DSBindless::getSingleton().bindTexture(entry.m_handle, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+		entry.m_bindlessIndex = BindlessDescriptorSet::getSingleton().bindTexture(entry.m_handle, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 	}
 	}
 
 
 	return entry.m_bindlessIndex;
 	return entry.m_bindlessIndex;

+ 8 - 8
AnKi/Renderer/Bloom.cpp

@@ -112,17 +112,17 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 			const TextureSubresourceDescriptor inputTexSubresource =
 			const TextureSubresourceDescriptor inputTexSubresource =
 				TextureSubresourceDescriptor::surface(getRenderer().getDownscaleBlur().getMipmapCount() - 1, 0, 0);
 				TextureSubresourceDescriptor::surface(getRenderer().getDownscaleBlur().getMipmapCount() - 1, 0, 0);
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, getRenderer().getDownscaleBlur().getRt(), inputTexSubresource);
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getDownscaleBlur().getRt(), inputTexSubresource);
 
 
 			const Vec4 consts(g_bloomThresholdCVar.get(), g_bloomScaleCVar.get(), 0.0f, 0.0f);
 			const Vec4 consts(g_bloomThresholdCVar.get(), g_bloomScaleCVar.get(), 0.0f, 0.0f);
 			cmdb.setPushConstants(&consts, sizeof(consts));
 			cmdb.setPushConstants(&consts, sizeof(consts));
 
 
-			rgraphCtx.bindStorageTexture(0, 2, getRenderer().getTonemapping().getRt());
+			rgraphCtx.bindTexture(ANKI_REG(u0), getRenderer().getTonemapping().getRt());
 
 
 			if(g_preferComputeCVar.get())
 			if(g_preferComputeCVar.get())
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 3, m_runCtx.m_exposureRt);
+				rgraphCtx.bindTexture(ANKI_REG(u1), m_runCtx.m_exposureRt);
 
 
 				dispatchPPCompute(cmdb, 8, 8, m_exposure.m_rtDescr.m_width, m_exposure.m_rtDescr.m_height);
 				dispatchPPCompute(cmdb, 8, 8, m_exposure.m_rtDescr.m_width, m_exposure.m_rtDescr.m_height);
 			}
 			}
@@ -167,13 +167,13 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_upscale.m_grProg.get());
 			cmdb.bindShaderProgram(m_upscale.m_grProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, m_runCtx.m_exposureRt);
-			cmdb.bindTexture(0, 2, TextureView(&m_upscale.m_lensDirtImage->getTexture(), TextureSubresourceDescriptor::all()));
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_exposureRt);
+			cmdb.bindTexture(ANKI_REG(t1), TextureView(&m_upscale.m_lensDirtImage->getTexture(), TextureSubresourceDescriptor::all()));
 
 
 			if(g_preferComputeCVar.get())
 			if(g_preferComputeCVar.get())
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 3, m_runCtx.m_upscaleRt);
+				rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_upscaleRt);
 
 
 				dispatchPPCompute(cmdb, 8, 8, m_upscale.m_rtDescr.m_width, m_upscale.m_rtDescr.m_height);
 				dispatchPPCompute(cmdb, 8, 8, m_upscale.m_rtDescr.m_width, m_upscale.m_rtDescr.m_height);
 			}
 			}

+ 8 - 8
AnKi/Renderer/ClusterBinning.cpp

@@ -87,10 +87,10 @@ void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
 			for(GpuSceneNonRenderableObjectType type : EnumIterable<GpuSceneNonRenderableObjectType>())
 			for(GpuSceneNonRenderableObjectType type : EnumIterable<GpuSceneNonRenderableObjectType>())
 			{
 			{
 				const BufferView& buff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
 				const BufferView& buff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
-				cmdb.bindStorageBuffer(0, 0, buff, U32(type));
+				cmdb.bindStorageBuffer(Register(HlslResourceType::kSrv, U32(type)), buff);
 			}
 			}
 
 
-			cmdb.bindStorageBuffer(0, 1, indirectArgsBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(u0), indirectArgsBuff);
 
 
 			cmdb.dispatchCompute(1, 1, 1);
 			cmdb.dispatchCompute(1, 1, 1);
 
 
@@ -116,7 +116,7 @@ void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
 				cmdb.bindShaderProgram(m_binningGrProgs[type].get());
 				cmdb.bindShaderProgram(m_binningGrProgs[type].get());
 
 
 				const BufferView& idsBuff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
 				const BufferView& idsBuff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
-				cmdb.bindStorageBuffer(0, 0, idsBuff);
+				cmdb.bindStorageBuffer(ANKI_REG(t0), idsBuff);
 
 
 				PtrSize objBufferOffset = 0;
 				PtrSize objBufferOffset = 0;
 				PtrSize objBufferRange = 0;
 				PtrSize objBufferRange = 0;
@@ -152,8 +152,8 @@ void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
 					objBufferRange = GpuSceneBuffer::getSingleton().getBufferView().getRange();
 					objBufferRange = GpuSceneBuffer::getSingleton().getBufferView().getRange();
 				}
 				}
 
 
-				cmdb.bindStorageBuffer(0, 1, BufferView(&GpuSceneBuffer::getSingleton().getBuffer(), objBufferOffset, objBufferRange));
-				cmdb.bindStorageBuffer(0, 2, m_runCtx.m_clustersBuffer);
+				cmdb.bindStorageBuffer(ANKI_REG(t1), BufferView(&GpuSceneBuffer::getSingleton().getBuffer(), objBufferOffset, objBufferRange));
+				cmdb.bindStorageBuffer(ANKI_REG(u0), m_runCtx.m_clustersBuffer);
 
 
 				struct ClusterBinningUniforms
 				struct ClusterBinningUniforms
 				{
 				{
@@ -258,11 +258,11 @@ void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
 					objBufferRange = GpuSceneBuffer::getSingleton().getBufferView().getRange();
 					objBufferRange = GpuSceneBuffer::getSingleton().getBufferView().getRange();
 				}
 				}
 
 
-				cmdb.bindStorageBuffer(0, 0, BufferView(&GpuSceneBuffer::getSingleton().getBuffer(), objBufferOffset, objBufferRange));
-				cmdb.bindStorageBuffer(0, 1, m_runCtx.m_packedObjectsBuffers[type]);
+				cmdb.bindStorageBuffer(ANKI_REG(t0), BufferView(&GpuSceneBuffer::getSingleton().getBuffer(), objBufferOffset, objBufferRange));
+				cmdb.bindStorageBuffer(ANKI_REG(u0), m_runCtx.m_packedObjectsBuffers[type]);
 
 
 				const BufferView& idsBuff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
 				const BufferView& idsBuff = getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type);
-				cmdb.bindStorageBuffer(0, 2, idsBuff);
+				cmdb.bindStorageBuffer(ANKI_REG(t1), idsBuff);
 
 
 				cmdb.dispatchComputeIndirect(BufferView(indirectArgsBuff).setOffset(indirectArgsBuffOffset).setRange(sizeof(DispatchIndirectArgs)));
 				cmdb.dispatchComputeIndirect(BufferView(indirectArgsBuff).setOffset(indirectArgsBuffOffset).setRange(sizeof(DispatchIndirectArgs)));
 
 

+ 11 - 11
AnKi/Renderer/Dbg.cpp

@@ -135,12 +135,12 @@ void Dbg::drawNonRenderable(GpuSceneNonRenderableObjectType type, U32 objCount,
 	unis.m_camTrf = ctx.m_matrices.m_cameraTransform;
 	unis.m_camTrf = ctx.m_matrices.m_cameraTransform;
 	cmdb.setPushConstants(&unis, sizeof(unis));
 	cmdb.setPushConstants(&unis, sizeof(unis));
 
 
-	cmdb.bindStorageBuffer(0, 2, getRenderer().getClusterBinning().getPackedObjectsBuffer(type));
-	cmdb.bindStorageBuffer(0, 3, getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type));
+	cmdb.bindStorageBuffer(ANKI_REG(t1), getRenderer().getClusterBinning().getPackedObjectsBuffer(type));
+	cmdb.bindStorageBuffer(ANKI_REG(t2), getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type));
 
 
-	cmdb.bindSampler(0, 4, getRenderer().getSamplers().m_trilinearRepeat.get());
-	cmdb.bindTexture(0, 5, TextureView(&image.getTexture(), TextureSubresourceDescriptor::all()));
-	cmdb.bindTexture(0, 6, TextureView(&m_spotLightImage->getTexture(), TextureSubresourceDescriptor::all()));
+	cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearRepeat.get());
+	cmdb.bindTexture(ANKI_REG(t3), TextureView(&image.getTexture(), TextureSubresourceDescriptor::all()));
+	cmdb.bindTexture(ANKI_REG(t4), TextureView(&m_spotLightImage->getTexture(), TextureSubresourceDescriptor::all()));
 
 
 	cmdb.draw(PrimitiveTopology::kTriangles, 6, objCount);
 	cmdb.draw(PrimitiveTopology::kTriangles, 6, objCount);
 }
 }
@@ -160,8 +160,8 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	cmdb.setDepthCompareOperation((m_depthTestOn) ? CompareOperation::kLess : CompareOperation::kAlways);
 	cmdb.setDepthCompareOperation((m_depthTestOn) ? CompareOperation::kLess : CompareOperation::kAlways);
 	cmdb.setLineWidth(2.0f);
 	cmdb.setLineWidth(2.0f);
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-	rgraphCtx.bindTexture(0, 1, getRenderer().getGBuffer().getDepthRt());
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+	rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
 
 
 	// GBuffer renderables
 	// GBuffer renderables
 	{
 	{
@@ -187,12 +187,12 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 		cmdb.setVertexAttribute(VertexAttributeSemantic::kPosition, 0, Format::kR32G32B32_Sfloat, 0);
 		cmdb.setVertexAttribute(VertexAttributeSemantic::kPosition, 0, Format::kR32G32B32_Sfloat, 0);
 		cmdb.bindIndexBuffer(BufferView(m_cubeIndicesBuffer.get()), IndexType::kU16);
 		cmdb.bindIndexBuffer(BufferView(m_cubeIndicesBuffer.get()), IndexType::kU16);
 
 
-		cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::RenderableBoundingVolumeGBuffer::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::RenderableBoundingVolumeGBuffer::getSingleton().getBufferView());
 
 
 		BufferView indicesBuff;
 		BufferView indicesBuff;
 		BufferHandle dep;
 		BufferHandle dep;
 		getRenderer().getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
 		getRenderer().getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
-		cmdb.bindStorageBuffer(0, 3, indicesBuff);
+		cmdb.bindStorageBuffer(ANKI_REG(t2), indicesBuff);
 
 
 		cmdb.drawIndexed(PrimitiveTopology::kLines, 12 * 2, allAabbCount);
 		cmdb.drawIndexed(PrimitiveTopology::kLines, 12 * 2, allAabbCount);
 	}
 	}
@@ -203,12 +203,12 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 
 
 		if(allAabbCount)
 		if(allAabbCount)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::RenderableBoundingVolumeForward::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::RenderableBoundingVolumeForward::getSingleton().getBufferView());
 
 
 			BufferView indicesBuff;
 			BufferView indicesBuff;
 			BufferHandle dep;
 			BufferHandle dep;
 			getRenderer().getForwardShading().getVisibleAabbsBuffer(indicesBuff, dep);
 			getRenderer().getForwardShading().getVisibleAabbsBuffer(indicesBuff, dep);
-			cmdb.bindStorageBuffer(0, 3, indicesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(t2), indicesBuff);
 
 
 			cmdb.drawIndexed(PrimitiveTopology::kLines, 12 * 2, allAabbCount);
 			cmdb.drawIndexed(PrimitiveTopology::kLines, 12 * 2, allAabbCount);
 		}
 		}

+ 7 - 7
AnKi/Renderer/DepthDownscale.cpp

@@ -138,13 +138,13 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 					surface.m_mipmap = 0; // Put something random
 					surface.m_mipmap = 0; // Put something random
 				}
 				}
 
 
-				rgraphCtx.bindStorageTexture(0, 0, m_runCtx.m_rt, surface, mip);
+				rgraphCtx.bindTexture(Register(HlslResourceType::kUav, mip + 1), m_runCtx.m_rt, surface);
 			}
 			}
 
 
-			cmdb.bindStorageBuffer(0, 1, BufferView(m_counterBuffer.get(), 0, sizeof(U32)));
+			cmdb.bindStorageBuffer(ANKI_REG(u0), BufferView(m_counterBuffer.get(), 0, sizeof(U32)));
 
 
-			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 3, getRenderer().getGBuffer().getDepthRt());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
 
 
 			cmdb.dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
 			cmdb.dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
 		});
 		});
@@ -177,15 +177,15 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 
 				cmdb.bindShaderProgram(m_grProg.get());
 				cmdb.bindShaderProgram(m_grProg.get());
-				cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
+				cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
 				if(mip == 0)
 				if(mip == 0)
 				{
 				{
-					rgraphCtx.bindTexture(0, 0, getRenderer().getGBuffer().getDepthRt());
+					rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
 				}
 				}
 				else
 				else
 				{
 				{
-					rgraphCtx.bindTexture(0, 0, m_runCtx.m_rt, TextureSubresourceDescriptor::surface(mip - 1, 0, 0));
+					rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_rt, TextureSubresourceDescriptor::surface(mip - 1, 0, 0));
 				}
 				}
 
 
 				const UVec2 size = (getRenderer().getInternalResolution() / 2) >> mip;
 				const UVec2 size = (getRenderer().getInternalResolution() / 2) >> mip;

+ 5 - 5
AnKi/Renderer/DownscaleBlur.cpp

@@ -119,25 +119,25 @@ void DownscaleBlur::run(U32 passIdx, RenderPassWorkContext& rgraphCtx)
 	const U32 vpWidth = m_rtTex->getWidth() >> passIdx;
 	const U32 vpWidth = m_rtTex->getWidth() >> passIdx;
 	const U32 vpHeight = m_rtTex->getHeight() >> passIdx;
 	const U32 vpHeight = m_rtTex->getHeight() >> passIdx;
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
 	if(passIdx > 0)
 	if(passIdx > 0)
 	{
 	{
-		rgraphCtx.bindTexture(0, 1, m_runCtx.m_rt, TextureSubresourceDescriptor::surface(passIdx - 1, 0, 0));
+		rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_rt, TextureSubresourceDescriptor::surface(passIdx - 1, 0, 0));
 	}
 	}
 	else
 	else
 	{
 	{
-		rgraphCtx.bindTexture(0, 1, getRenderer().getLightShading().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getLightShading().getRt());
 	}
 	}
 
 
-	rgraphCtx.bindStorageTexture(0, 2, getRenderer().getTonemapping().getRt());
+	rgraphCtx.bindTexture(ANKI_REG(u0), getRenderer().getTonemapping().getRt());
 
 
 	if(g_preferComputeCVar.get())
 	if(g_preferComputeCVar.get())
 	{
 	{
 		const Vec4 fbSize(F32(vpWidth), F32(vpHeight), 0.0f, 0.0f);
 		const Vec4 fbSize(F32(vpWidth), F32(vpHeight), 0.0f, 0.0f);
 		cmdb.setPushConstants(&fbSize, sizeof(fbSize));
 		cmdb.setPushConstants(&fbSize, sizeof(fbSize));
 
 
-		rgraphCtx.bindStorageTexture(0, 3, m_runCtx.m_rt, TextureSubresourceDescriptor::surface(passIdx, 0, 0));
+		rgraphCtx.bindTexture(ANKI_REG(u1), m_runCtx.m_rt, TextureSubresourceDescriptor::surface(passIdx, 0, 0));
 
 
 		dispatchPPCompute(cmdb, 8, 8, vpWidth, vpHeight);
 		dispatchPPCompute(cmdb, 8, 8, vpWidth, vpHeight);
 	}
 	}

+ 11 - 11
AnKi/Renderer/FinalComposite.cpp

@@ -133,20 +133,20 @@ void FinalComposite::run(RenderPassWorkContext& rgraphCtx)
 	// Bind stuff
 	// Bind stuff
 	if(!hasDebugRt)
 	if(!hasDebugRt)
 	{
 	{
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
-		cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
+		cmdb.bindSampler(ANKI_REG(s2), getRenderer().getSamplers().m_trilinearRepeat.get());
 
 
-		rgraphCtx.bindTexture(0, 3, getRenderer().getScale().getTonemappedRt());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getScale().getTonemappedRt());
 
 
-		rgraphCtx.bindTexture(0, 4, getRenderer().getBloom().getRt());
-		cmdb.bindTexture(0, 5, TextureView(&m_lut->getTexture(), TextureSubresourceDescriptor::all()));
-		rgraphCtx.bindTexture(0, 6, getRenderer().getMotionVectors().getMotionVectorsRt());
-		rgraphCtx.bindTexture(0, 7, getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getBloom().getRt());
+		cmdb.bindTexture(ANKI_REG(t2), TextureView(&m_lut->getTexture(), TextureSubresourceDescriptor::all()));
+		rgraphCtx.bindTexture(ANKI_REG(t3), getRenderer().getMotionVectors().getMotionVectorsRt());
+		rgraphCtx.bindTexture(ANKI_REG(t4), getRenderer().getGBuffer().getDepthRt());
 
 
 		if(dbgEnabled)
 		if(dbgEnabled)
 		{
 		{
-			rgraphCtx.bindTexture(0, 8, getRenderer().getDbg().getRt());
+			rgraphCtx.bindTexture(ANKI_REG(t5), getRenderer().getDbg().getRt());
 		}
 		}
 
 
 		const UVec4 pc(g_motionBlurSamplesCVar.get(), floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32, 0);
 		const UVec4 pc(g_motionBlurSamplesCVar.get(), floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32, 0);
@@ -154,14 +154,14 @@ void FinalComposite::run(RenderPassWorkContext& rgraphCtx)
 	}
 	}
 	else
 	else
 	{
 	{
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
 		U32 count = 1;
 		U32 count = 1;
 		for(const RenderTargetHandle& handle : dbgRts)
 		for(const RenderTargetHandle& handle : dbgRts)
 		{
 		{
 			if(handle.isValid())
 			if(handle.isValid())
 			{
 			{
-				rgraphCtx.bindTexture(0, count++, handle);
+				rgraphCtx.bindTexture(Register(HlslResourceType::kSrv, count++), handle);
 			}
 			}
 		}
 		}
 	}
 	}

+ 10 - 9
AnKi/Renderer/ForwardShading.cpp

@@ -71,22 +71,23 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 		cmdb.setBlendFactors(0, BlendFactor::kSrcAlpha, BlendFactor::kOneMinusSrcAlpha);
 		cmdb.setBlendFactors(0, BlendFactor::kSrcAlpha, BlendFactor::kOneMinusSrcAlpha);
 
 
 		// Bind stuff
 		// Bind stuff
-		const U32 set = U32(MaterialSet::kGlobal);
-		cmdb.bindSampler(set, U32(MaterialBinding::kLinearClampSampler), getRenderer().getSamplers().m_trilinearClamp.get());
-		cmdb.bindSampler(set, U32(MaterialBinding::kShadowSampler), getRenderer().getSamplers().m_trilinearClampShadow.get());
+		cmdb.bindSampler(ANKI_REG(ANKI_MATERIAL_REGISTER_LINEAR_CLAMP_SAMPLER), getRenderer().getSamplers().m_trilinearClamp.get());
+		cmdb.bindSampler(ANKI_REG(ANKI_MATERIAL_REGISTER_SHADOW_SAMPLER), getRenderer().getSamplers().m_trilinearClampShadow.get());
 
 
-		rgraphCtx.bindTexture(set, U32(MaterialBinding::kDepthRt), getRenderer().getDepthDownscale().getRt(),
+		rgraphCtx.bindTexture(ANKI_REG(ANKI_MATERIAL_REGISTER_SCENE_DEPTH), getRenderer().getDepthDownscale().getRt(),
 							  DepthDownscale::kQuarterInternalResolution);
 							  DepthDownscale::kQuarterInternalResolution);
-		rgraphCtx.bindTexture(set, U32(MaterialBinding::kLightVolume), getRenderer().getVolumetricLightingAccumulation().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(ANKI_MATERIAL_REGISTER_LIGHT_VOLUME), getRenderer().getVolumetricLightingAccumulation().getRt());
 
 
-		cmdb.bindUniformBuffer(set, U32(MaterialBinding::kClusterShadingUniforms), ctx.m_globalRenderingUniformsBuffer);
+		cmdb.bindUniformBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_UNIFORMS), ctx.m_globalRenderingUniformsBuffer);
 
 
-		cmdb.bindStorageBuffer(set, U32(MaterialBinding::kClusterShadingLights),
+		cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_POINT_LIGHTS),
+							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_SPOT_LIGHTS),
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 
 
-		rgraphCtx.bindTexture(set, U32(MaterialBinding::kClusterShadingLights) + 1, getRenderer().getShadowMapping().getShadowmapRt());
+		rgraphCtx.bindTexture(ANKI_REG(ANKI_MATERIAL_REGISTER_SHADOW_ATLAS), getRenderer().getShadowMapping().getShadowmapRt());
 
 
-		cmdb.bindStorageBuffer(set, U32(MaterialBinding::kClusters), getRenderer().getClusterBinning().getClustersBuffer());
+		cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_CLUSTERS), getRenderer().getClusterBinning().getClustersBuffer());
 
 
 		// Draw
 		// Draw
 		RenderableDrawerArguments args;
 		RenderableDrawerArguments args;

+ 6 - 8
AnKi/Renderer/GBufferPost.cpp

@@ -56,17 +56,15 @@ void GBufferPost::populateRenderGraph(RenderingContext& ctx)
 		cmdb.setBlendFactors(1, BlendFactor::kOne, BlendFactor::kSrcAlpha, BlendFactor::kZero, BlendFactor::kOne);
 		cmdb.setBlendFactors(1, BlendFactor::kOne, BlendFactor::kSrcAlpha, BlendFactor::kZero, BlendFactor::kOne);
 
 
 		// Bind all
 		// Bind all
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
-		rgraphCtx.bindTexture(0, 1, getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
 
 
-		cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
+		cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearRepeat.get());
 
 
-		cmdb.bindUniformBuffer(0, 3, ctx.m_globalRenderingUniformsBuffer);
-		cmdb.bindStorageBuffer(0, 4, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kDecal));
-		cmdb.bindStorageBuffer(0, 5, getRenderer().getClusterBinning().getClustersBuffer());
-
-		cmdb.bindAllBindless(1);
+		cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t0), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kDecal));
+		cmdb.bindStorageBuffer(ANKI_REG(t1), getRenderer().getClusterBinning().getClustersBuffer());
 
 
 		// Draw
 		// Draw
 		cmdb.draw(PrimitiveTopology::kTriangles, 3);
 		cmdb.draw(PrimitiveTopology::kTriangles, 3);

+ 4 - 4
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -487,15 +487,15 @@ void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
 				cmdb.bindShaderProgram(m_irradiance.m_grProg.get());
 				cmdb.bindShaderProgram(m_irradiance.m_grProg.get());
 
 
 				// Bind resources
 				// Bind resources
-				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-				rgraphCtx.bindTexture(0, 1, lightShadingRt);
+				cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+				rgraphCtx.bindTexture(ANKI_REG(t0), lightShadingRt);
 
 
 				for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
 				for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
 				{
 				{
-					rgraphCtx.bindTexture(0, 2, gbufferColorRts[i], i);
+					rgraphCtx.bindTexture(Register(HlslResourceType::kSrv, i + 1), gbufferColorRts[i]);
 				}
 				}
 
 
-				rgraphCtx.bindStorageTexture(0, 3, irradianceVolume);
+				rgraphCtx.bindTexture(ANKI_REG(u0), irradianceVolume);
 
 
 				class
 				class
 				{
 				{

+ 7 - 7
AnKi/Renderer/LensFlare.cpp

@@ -76,17 +76,17 @@ void LensFlare::populateRenderGraph(RenderingContext& ctx)
 		cmdb.setPushConstants(&ctx.m_matrices.m_viewProjectionJitter, sizeof(ctx.m_matrices.m_viewProjectionJitter));
 		cmdb.setPushConstants(&ctx.m_matrices.m_viewProjectionJitter, sizeof(ctx.m_matrices.m_viewProjectionJitter));
 
 
 		// Write flare info
 		// Write flare info
-		Vec4* flarePositions = allocateAndBindStorageBuffer<Vec4>(cmdb, 0, 0, flareCount);
+		Vec4* flarePositions = allocateAndBindStorageBuffer<Vec4>(cmdb, ANKI_REG(t0), flareCount);
 		for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
 		for(const LensFlareComponent& comp : SceneGraph::getSingleton().getComponentArrays().getLensFlares())
 		{
 		{
 			*flarePositions = Vec4(comp.getWorldPosition(), 1.0f);
 			*flarePositions = Vec4(comp.getWorldPosition(), 1.0f);
 			++flarePositions;
 			++flarePositions;
 		}
 		}
 
 
-		rgraphCtx.bindStorageBuffer(0, 1, m_runCtx.m_indirectBuffHandle);
+		rgraphCtx.bindStorageBuffer(ANKI_REG(u0), m_runCtx.m_indirectBuffHandle);
 		// Bind neareset because you don't need high quality
 		// Bind neareset because you don't need high quality
-		cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
 
 
 		cmdb.dispatchCompute(flareCount, 1, 1);
 		cmdb.dispatchCompute(flareCount, 1, 1);
 	});
 	});
@@ -123,7 +123,7 @@ void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBuffer& cmdb)
 		U32 spritesCount = max<U32>(1, m_maxSpritesPerFlare);
 		U32 spritesCount = max<U32>(1, m_maxSpritesPerFlare);
 
 
 		// Get uniform memory
 		// Get uniform memory
-		LensFlareSprite* tmpSprites = allocateAndBindStorageBuffer<LensFlareSprite>(cmdb, 0, 0, spritesCount);
+		LensFlareSprite* tmpSprites = allocateAndBindStorageBuffer<LensFlareSprite>(cmdb, ANKI_REG(t0), spritesCount);
 		WeakArray<LensFlareSprite> sprites(tmpSprites, spritesCount);
 		WeakArray<LensFlareSprite> sprites(tmpSprites, spritesCount);
 
 
 		// misc
 		// misc
@@ -138,8 +138,8 @@ void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBuffer& cmdb)
 		++c;
 		++c;
 
 
 		// Render
 		// Render
-		cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearRepeat.get());
-		cmdb.bindTexture(0, 2, TextureView(&comp.getImage().getTexture(), TextureSubresourceDescriptor::all()));
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearRepeat.get());
+		cmdb.bindTexture(ANKI_REG(t1), TextureView(&comp.getImage().getTexture(), TextureSubresourceDescriptor::all()));
 
 
 		cmdb.drawIndirect(PrimitiveTopology::kTriangleStrip, BufferView(m_runCtx.m_indirectBuff).incrementOffset(count * sizeof(DrawIndirectArgs)));
 		cmdb.drawIndirect(PrimitiveTopology::kTriangleStrip, BufferView(m_runCtx.m_indirectBuff).incrementOffset(count * sizeof(DrawIndirectArgs)));
 
 

+ 27 - 27
AnKi/Renderer/LightShading.cpp

@@ -108,25 +108,25 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 		cmdb.setDepthWrite(false);
 		cmdb.setDepthWrite(false);
 
 
 		// Bind all
 		// Bind all
-		cmdb.bindUniformBuffer(0, 0, ctx.m_globalRenderingUniformsBuffer);
-		cmdb.bindStorageBuffer(0, 1, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		cmdb.bindStorageBuffer(0, 2,
+		cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t0), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindStorageBuffer(ANKI_REG(t1), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindStorageBuffer(ANKI_REG(t2),
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
-		cmdb.bindStorageBuffer(0, 3, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
-		cmdb.bindStorageBuffer(0, 5, getRenderer().getClusterBinning().getClustersBuffer());
-
-		cmdb.bindSampler(0, 6, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		cmdb.bindSampler(0, 7, getRenderer().getSamplers().m_trilinearClamp.get());
-		rgraphCtx.bindTexture(0, 8, getRenderer().getGBuffer().getColorRt(0));
-		rgraphCtx.bindTexture(0, 9, getRenderer().getGBuffer().getColorRt(1));
-		rgraphCtx.bindTexture(0, 10, getRenderer().getGBuffer().getColorRt(2));
-		rgraphCtx.bindTexture(0, 11, getRenderer().getGBuffer().getDepthRt());
-		rgraphCtx.bindTexture(0, 12, getRenderer().getShadowmapsResolve().getRt());
-		rgraphCtx.bindTexture(0, 13, getRenderer().getSsao().getRt());
-		rgraphCtx.bindTexture(0, 14, getRenderer().getSsr().getRt());
-		cmdb.bindTexture(0, 15, TextureView(&getRenderer().getProbeReflections().getIntegrationLut(), TextureSubresourceDescriptor::all()));
-
-		cmdb.bindAllBindless(1);
+		cmdb.bindStorageBuffer(ANKI_REG(t3),
+							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
+		cmdb.bindStorageBuffer(ANKI_REG(t4), getRenderer().getClusterBinning().getClustersBuffer());
+
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t5), getRenderer().getGBuffer().getColorRt(0));
+		rgraphCtx.bindTexture(ANKI_REG(t6), getRenderer().getGBuffer().getColorRt(1));
+		rgraphCtx.bindTexture(ANKI_REG(t7), getRenderer().getGBuffer().getColorRt(2));
+		rgraphCtx.bindTexture(ANKI_REG(t8), getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t9), getRenderer().getShadowmapsResolve().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t10), getRenderer().getSsao().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t11), getRenderer().getSsr().getRt());
+		cmdb.bindTexture(ANKI_REG(t12), TextureView(&getRenderer().getProbeReflections().getIntegrationLut(), TextureSubresourceDescriptor::all()));
 
 
 		// Draw
 		// Draw
 		drawQuad(cmdb);
 		drawQuad(cmdb);
@@ -175,16 +175,16 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 
 
 			cmdb.setPushConstants(&pc, sizeof(pc));
 			cmdb.setPushConstants(&pc, sizeof(pc));
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeatAnisoResolutionScalingBias.get());
-			cmdb.bindTexture(0, 1, TextureView(&sky->getImageResource().getTexture(), TextureSubresourceDescriptor::all()));
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearRepeatAnisoResolutionScalingBias.get());
+			cmdb.bindTexture(ANKI_REG(t0), TextureView(&sky->getImageResource().getTexture(), TextureSubresourceDescriptor::all()));
 		}
 		}
 		else
 		else
 		{
 		{
 			cmdb.bindShaderProgram(m_skybox.m_grProgs[2].get());
 			cmdb.bindShaderProgram(m_skybox.m_grProgs[2].get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, getRenderer().getSky().getSkyLutRt());
-			cmdb.bindUniformBuffer(0, 2, ctx.m_globalRenderingUniformsBuffer);
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getSky().getSkyLutRt());
+			cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
 		}
 		}
 
 
 		drawQuad(cmdb);
 		drawQuad(cmdb);
@@ -198,11 +198,11 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 		cmdb.bindShaderProgram(m_applyFog.m_grProg.get());
 		cmdb.bindShaderProgram(m_applyFog.m_grProg.get());
 
 
 		// Bind all
 		// Bind all
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
-		rgraphCtx.bindTexture(0, 2, getRenderer().getGBuffer().getDepthRt());
-		rgraphCtx.bindTexture(0, 3, getRenderer().getVolumetricFog().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getVolumetricFog().getRt());
 
 
 		class PushConsts
 		class PushConsts
 		{
 		{

+ 2 - 2
AnKi/Renderer/MainRenderer.cpp

@@ -118,8 +118,8 @@ Error MainRenderer::render(Texture* presentTex)
 			cmdb.setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());
 			cmdb.setViewport(0, 0, m_swapchainResolution.x(), m_swapchainResolution.y());
 
 
 			cmdb.bindShaderProgram(m_blitGrProg.get());
 			cmdb.bindShaderProgram(m_blitGrProg.get());
-			cmdb.bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, m_runCtx.m_ctx->m_outRenderTarget);
+			cmdb.bindSampler(ANKI_REG(s0), m_r->getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_ctx->m_outRenderTarget);
 
 
 			cmdb.draw(PrimitiveTopology::kTriangles, 3);
 			cmdb.draw(PrimitiveTopology::kTriangles, 3);
 		});
 		});

+ 5 - 5
AnKi/Renderer/MotionVectors.cpp

@@ -71,9 +71,9 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 
 
 		cmdb.bindShaderProgram(m_grProg.get());
 		cmdb.bindShaderProgram(m_grProg.get());
 
 
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		rgraphCtx.bindTexture(0, 1, getRenderer().getGBuffer().getDepthRt());
-		rgraphCtx.bindTexture(0, 2, getRenderer().getGBuffer().getColorRt(3));
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getGBuffer().getColorRt(3));
 
 
 		class Uniforms
 		class Uniforms
 		{
 		{
@@ -82,7 +82,7 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 			Mat4 m_currentInvViewProjMat;
 			Mat4 m_currentInvViewProjMat;
 			Mat4 m_prevViewProjMat;
 			Mat4 m_prevViewProjMat;
 		} * pc;
 		} * pc;
-		pc = allocateAndBindConstants<Uniforms>(cmdb, 0, 3);
+		pc = allocateAndBindConstants<Uniforms>(cmdb, ANKI_REG(b0));
 
 
 		pc->m_currentViewProjMat = ctx.m_matrices.m_viewProjection;
 		pc->m_currentViewProjMat = ctx.m_matrices.m_viewProjection;
 		pc->m_currentInvViewProjMat = ctx.m_matrices.m_invertedViewProjection;
 		pc->m_currentInvViewProjMat = ctx.m_matrices.m_invertedViewProjection;
@@ -90,7 +90,7 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 
 
 		if(g_preferComputeCVar.get())
 		if(g_preferComputeCVar.get())
 		{
 		{
-			rgraphCtx.bindStorageTexture(0, 4, m_runCtx.m_motionVectorsRtHandle);
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_motionVectorsRtHandle);
 		}
 		}
 
 
 		if(g_preferComputeCVar.get())
 		if(g_preferComputeCVar.get())

+ 7 - 7
AnKi/Renderer/ProbeReflections.cpp

@@ -461,11 +461,11 @@ void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
 
 
 			cmdb.bindShaderProgram(m_irradiance.m_grProg.get());
 			cmdb.bindShaderProgram(m_irradiance.m_grProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
-			rgraphCtx.bindTexture(0, 1, probeTexture);
+			rgraphCtx.bindTexture(ANKI_REG(t0), probeTexture);
 
 
-			cmdb.bindStorageBuffer(0, 3, BufferView(m_irradiance.m_diceValuesBuff.get()));
+			cmdb.bindStorageBuffer(ANKI_REG(u0), BufferView(m_irradiance.m_diceValuesBuff.get()));
 
 
 			cmdb.dispatchCompute(1, 1, 1);
 			cmdb.dispatchCompute(1, 1, 1);
 		});
 		});
@@ -492,18 +492,18 @@ void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
 			cmdb.bindShaderProgram(m_irradianceToRefl.m_grProg.get());
 			cmdb.bindShaderProgram(m_irradianceToRefl.m_grProg.get());
 
 
 			// Bind resources
 			// Bind resources
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
 			for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
 			for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
 			{
 			{
-				rgraphCtx.bindTexture(0, 1, gbufferColorRts[i], i);
+				rgraphCtx.bindTexture(Register(HlslResourceType::kSrv, i), gbufferColorRts[i]);
 			}
 			}
 
 
-			cmdb.bindStorageBuffer(0, 2, BufferView(m_irradiance.m_diceValuesBuff.get()));
+			cmdb.bindStorageBuffer(ANKI_REG(t3), BufferView(m_irradiance.m_diceValuesBuff.get()));
 
 
 			for(U8 f = 0; f < 6; ++f)
 			for(U8 f = 0; f < 6; ++f)
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 3, probeTexture, TextureSubresourceDescriptor::surface(0, f, 0), f);
+				rgraphCtx.bindTexture(Register(HlslResourceType::kUav, f), probeTexture, TextureSubresourceDescriptor::surface(0, f, 0));
 			}
 			}
 
 
 			dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
 			dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);

+ 1 - 1
AnKi/Renderer/Renderer.cpp

@@ -553,7 +553,7 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, Text
 
 
 					const TextureView view(tex.get(), TextureSubresourceDescriptor::surface(mip, face, layer));
 					const TextureView view(tex.get(), TextureSubresourceDescriptor::surface(mip, face, layer));
 
 
-					cmdb->bindStorageTexture(0, 0, view);
+					cmdb->bindTexture(ANKI_REG(u0), view);
 
 
 					const TextureBarrierInfo barrier = {view, TextureUsageBit::kNone, TextureUsageBit::kStorageComputeWrite};
 					const TextureBarrierInfo barrier = {view, TextureUsageBit::kNone, TextureUsageBit::kStorageComputeWrite};
 					cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
 					cmdb->setPipelineBarrier({&barrier, 1}, {}, {});

+ 4 - 4
AnKi/Renderer/RendererObject.h

@@ -62,22 +62,22 @@ protected:
 	}
 	}
 
 
 	template<typename T>
 	template<typename T>
-	static T* allocateAndBindConstants(CommandBuffer& cmdb, U32 set, U32 binding)
+	static T* allocateAndBindConstants(CommandBuffer& cmdb, Register reg)
 	{
 	{
 		T* ptr;
 		T* ptr;
 		const RebarAllocation alloc = RebarTransientMemoryPool::getSingleton().allocateFrame(1, ptr);
 		const RebarAllocation alloc = RebarTransientMemoryPool::getSingleton().allocateFrame(1, ptr);
 		ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(ptr)));
 		ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(ptr)));
-		cmdb.bindUniformBuffer(set, binding, alloc);
+		cmdb.bindUniformBuffer(reg, alloc);
 		return ptr;
 		return ptr;
 	}
 	}
 
 
 	template<typename T>
 	template<typename T>
-	static T* allocateAndBindStorageBuffer(CommandBuffer& cmdb, U32 set, U32 binding, U32 count = 1)
+	static T* allocateAndBindStorageBuffer(CommandBuffer& cmdb, Register reg, U32 count = 1)
 	{
 	{
 		T* ptr;
 		T* ptr;
 		const RebarAllocation alloc = RebarTransientMemoryPool::getSingleton().allocateFrame(count, ptr);
 		const RebarAllocation alloc = RebarTransientMemoryPool::getSingleton().allocateFrame(count, ptr);
 		ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(ptr)));
 		ANKI_ASSERT(isAligned(alignof(T), ptrToNumber(ptr)));
-		cmdb.bindStorageBuffer(set, binding, alloc);
+		cmdb.bindStorageBuffer(reg, alloc);
 		return ptr;
 		return ptr;
 	}
 	}
 
 

+ 54 - 59
AnKi/Renderer/RtShadows.cpp

@@ -221,8 +221,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_setupBuildSbtGrProg.get());
 			cmdb.bindShaderProgram(m_setupBuildSbtGrProg.get());
 
 
-			cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 1, sbtBuildIndirectArgsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(t0), GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(u0), sbtBuildIndirectArgsBuffer);
 
 
 			cmdb.dispatchCompute(1, 1, 1);
 			cmdb.dispatchCompute(1, 1, 1);
 		});
 		});
@@ -260,11 +260,11 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_buildSbtGrProg.get());
 			cmdb.bindShaderProgram(m_buildSbtGrProg.get());
 
 
-			cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::Renderable::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 1, BufferView(&GpuSceneBuffer::getSingleton().getBuffer()));
-			cmdb.bindStorageBuffer(0, 2, visibleRenderableIndicesBuff);
-			cmdb.bindStorageBuffer(0, 3, BufferView(&m_rtLibraryGrProg->getShaderGroupHandlesGpuBuffer()));
-			cmdb.bindStorageBuffer(0, 4, sbtBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(t0), GpuSceneArrays::Renderable::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t1), BufferView(&GpuSceneBuffer::getSingleton().getBuffer()));
+			cmdb.bindStorageBuffer(ANKI_REG(t2), visibleRenderableIndicesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(t3), BufferView(&m_rtLibraryGrProg->getShaderGroupHandlesGpuBuffer()));
+			cmdb.bindStorageBuffer(ANKI_REG(u0), sbtBuffer);
 
 
 			RtShadowsSbtBuildUniforms unis = {};
 			RtShadowsSbtBuildUniforms unis = {};
 			ANKI_ASSERT(m_sbtRecordSize % 4 == 0);
 			ANKI_ASSERT(m_sbtRecordSize % 4 == 0);
@@ -308,41 +308,37 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 
 				memset(globalUniforms, 0, sizeof(*globalUniforms)); // Don't care for now
 				memset(globalUniforms, 0, sizeof(*globalUniforms)); // Don't care for now
 
 
-				cmdb.bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms), globalUniformsToken);
+				cmdb.bindUniformBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_GLOBAL_UNIFORMS), globalUniformsToken);
 			}
 			}
 
 
 			// More globals
 			// More globals
-			cmdb.bindAllBindless(U32(MaterialSet::kBindless));
-			cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler),
-							 getRenderer().getSamplers().m_trilinearRepeat.get());
-			cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), GpuSceneBuffer::getSingleton().getBufferView());
-
-#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
-	cmdb.bindReadOnlyTexelBuffer( \
-		U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
+			cmdb.bindSampler(ANKI_REG(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER), getRenderer().getSamplers().m_trilinearRepeat.get());
+			cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_GPU_SCENE), GpuSceneBuffer::getSingleton().getBufferView());
+
+#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
+	cmdb.bindTexelBuffer( \
+		ANKI_REG(reg), \
 		BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
 		BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
 				   getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
 				   getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
 		Format::k##fmt);
 		Format::k##fmt);
 #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
 #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
 
 
-			constexpr U32 kSet = 2;
-
-			cmdb.bindUniformBuffer(kSet, 0, ctx.m_globalRenderingUniformsBuffer);
-			cmdb.bindStorageBuffer(kSet, 1, getRenderer().getClusterBinning().getClustersBuffer());
+			cmdb.bindUniformBuffer(ANKI_REG2(b0, space2), ctx.m_globalRenderingUniformsBuffer);
 
 
-			cmdb.bindSampler(kSet, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
+			cmdb.bindSampler(ANKI_REG2(s0, space2), getRenderer().getSamplers().m_trilinearRepeat.get());
 
 
-			rgraphCtx.bindStorageTexture(kSet, 3, m_runCtx.m_intermediateShadowsRts[0]);
-			rgraphCtx.bindTexture(kSet, 4, m_runCtx.m_historyRt);
-			cmdb.bindSampler(kSet, 5, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(kSet, 6, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-			rgraphCtx.bindTexture(kSet, 7, getRenderer().getMotionVectors().getMotionVectorsRt());
-			cmdb.bindTexture(kSet, 8, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
-			rgraphCtx.bindTexture(kSet, 9, getRenderer().getGBuffer().getColorRt(2));
-			rgraphCtx.bindAccelerationStructure(kSet, 10, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
-			rgraphCtx.bindTexture(kSet, 11, m_runCtx.m_prevMomentsRt);
-			rgraphCtx.bindStorageTexture(kSet, 12, m_runCtx.m_currentMomentsRt);
-			cmdb.bindTexture(kSet, 13, TextureView(&m_blueNoiseImage->getTexture(), TextureSubresourceDescriptor::all()));
+			rgraphCtx.bindTexture(ANKI_REG2(u0, space2), m_runCtx.m_intermediateShadowsRts[0]);
+			rgraphCtx.bindTexture(ANKI_REG2(t0, space2), m_runCtx.m_historyRt);
+			cmdb.bindSampler(ANKI_REG2(s1, space2), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG2(t1, space2), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindTexture(ANKI_REG2(t2, space2), getRenderer().getMotionVectors().getMotionVectorsRt());
+			cmdb.bindTexture(ANKI_REG2(t3, space2), TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
+			rgraphCtx.bindTexture(ANKI_REG2(t4, space2), getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindAccelerationStructure(ANKI_REG2(t5, space2),
+												getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
+			rgraphCtx.bindTexture(ANKI_REG2(t6, space2), m_runCtx.m_prevMomentsRt);
+			rgraphCtx.bindTexture(ANKI_REG2(u1, space2), m_runCtx.m_currentMomentsRt);
+			cmdb.bindTexture(ANKI_REG2(t7, space2), TextureView(&m_blueNoiseImage->getTexture(), TextureSubresourceDescriptor::all()));
 
 
 			cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
 			cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
 						   getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, 1);
 						   getRenderer().getInternalResolution().x() / 2, getRenderer().getInternalResolution().y() / 2, 1);
@@ -401,15 +397,15 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_svgfVarianceGrProg.get());
 			cmdb.bindShaderProgram(m_svgfVarianceGrProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
-			rgraphCtx.bindTexture(0, 1, m_runCtx.m_intermediateShadowsRts[0]);
-			rgraphCtx.bindTexture(0, 2, m_runCtx.m_currentMomentsRt);
-			cmdb.bindTexture(0, 3, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
-			rgraphCtx.bindTexture(0, 4, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_intermediateShadowsRts[0]);
+			rgraphCtx.bindTexture(ANKI_REG(t1), m_runCtx.m_currentMomentsRt);
+			cmdb.bindTexture(ANKI_REG(t2), TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
+			rgraphCtx.bindTexture(ANKI_REG(t3), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 
 
-			rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_intermediateShadowsRts[1]);
-			rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_varianceRts[1]);
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_intermediateShadowsRts[1]);
+			rgraphCtx.bindTexture(ANKI_REG(u1), m_runCtx.m_varianceRts[1]);
 
 
 			const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 			const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 			cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
 			cmdb.setPushConstants(&invProjMat, sizeof(invProjMat));
@@ -460,21 +456,20 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 					cmdb.bindShaderProgram(m_svgfAtrousGrProg.get());
 					cmdb.bindShaderProgram(m_svgfAtrousGrProg.get());
 				}
 				}
 
 
-				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-				cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
+				cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
-				rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-				rgraphCtx.bindTexture(0, 3, m_runCtx.m_intermediateShadowsRts[readRtIdx]);
-				rgraphCtx.bindTexture(0, 4, m_runCtx.m_varianceRts[readRtIdx]);
+				rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+				rgraphCtx.bindTexture(ANKI_REG(t1), m_runCtx.m_intermediateShadowsRts[readRtIdx]);
+				rgraphCtx.bindTexture(ANKI_REG(t2), m_runCtx.m_varianceRts[readRtIdx]);
 
 
 				if(!lastPass)
 				if(!lastPass)
 				{
 				{
-					rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
-					rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_varianceRts[!readRtIdx]);
+					rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_intermediateShadowsRts[!readRtIdx]);
+					rgraphCtx.bindTexture(ANKI_REG(u1), m_runCtx.m_varianceRts[!readRtIdx]);
 				}
 				}
 				else
 				else
 				{
 				{
-					rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_historyRt);
+					rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_historyRt);
 				}
 				}
 
 
 				const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 				const Mat4& invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
@@ -501,12 +496,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_upscaleGrProg.get());
 			cmdb.bindShaderProgram(m_upscaleGrProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
-			rgraphCtx.bindTexture(0, 1, m_runCtx.m_historyRt);
-			rgraphCtx.bindStorageTexture(0, 2, m_runCtx.m_upscaledRt);
-			rgraphCtx.bindTexture(0, 3, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-			rgraphCtx.bindTexture(0, 4, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_historyRt);
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_upscaledRt);
+			rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getGBuffer().getDepthRt());
 
 
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 		});
 		});
@@ -520,14 +515,14 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
 
 
 	cmdb.bindShaderProgram((horizontal) ? m_grDenoiseHorizontalProg.get() : m_grDenoiseVerticalProg.get());
 	cmdb.bindShaderProgram((horizontal) ? m_grDenoiseHorizontalProg.get() : m_grDenoiseVerticalProg.get());
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-	rgraphCtx.bindTexture(0, 1, m_runCtx.m_intermediateShadowsRts[(horizontal) ? 0 : 1]);
-	rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-	rgraphCtx.bindTexture(0, 3, getRenderer().getGBuffer().getColorRt(2));
-	rgraphCtx.bindTexture(0, 4, m_runCtx.m_currentMomentsRt);
-	cmdb.bindTexture(0, 5, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+	rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_intermediateShadowsRts[(horizontal) ? 0 : 1]);
+	rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+	rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getGBuffer().getColorRt(2));
+	rgraphCtx.bindTexture(ANKI_REG(t3), m_runCtx.m_currentMomentsRt);
+	cmdb.bindTexture(ANKI_REG(t4), TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDescriptor::all()));
 
 
-	rgraphCtx.bindStorageTexture(0, 6, (horizontal) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
+	rgraphCtx.bindTexture(ANKI_REG(u0), (horizontal) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
 
 
 	RtShadowsDenoiseUniforms consts;
 	RtShadowsDenoiseUniforms consts;
 	consts.m_invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;
 	consts.m_invViewProjMat = ctx.m_matrices.m_invertedViewProjectionJitter;

+ 10 - 10
AnKi/Renderer/Scale.cpp

@@ -298,12 +298,12 @@ void Scale::runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb.bindShaderProgram(m_scaleGrProg.get());
 	cmdb.bindShaderProgram(m_scaleGrProg.get());
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-	rgraphCtx.bindTexture(0, 1, inRt);
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+	rgraphCtx.bindTexture(ANKI_REG(t0), inRt);
 
 
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{
-		rgraphCtx.bindStorageTexture(0, 2, outRt);
+		rgraphCtx.bindTexture(ANKI_REG(u0), outRt);
 	}
 	}
 
 
 	if(m_upscalingMethod == UpscalingMethod::kFsr)
 	if(m_upscalingMethod == UpscalingMethod::kFsr)
@@ -363,12 +363,12 @@ void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb.bindShaderProgram(m_sharpenGrProg.get());
 	cmdb.bindShaderProgram(m_sharpenGrProg.get());
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-	rgraphCtx.bindTexture(0, 1, inRt);
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+	rgraphCtx.bindTexture(ANKI_REG(t0), inRt);
 
 
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{
-		rgraphCtx.bindStorageTexture(0, 2, outRt);
+		rgraphCtx.bindTexture(ANKI_REG(u0), outRt);
 	}
 	}
 
 
 	class
 	class
@@ -435,10 +435,10 @@ void Scale::runTonemapping(RenderPassWorkContext& rgraphCtx)
 
 
 	cmdb.bindShaderProgram(m_tonemapGrProg.get());
 	cmdb.bindShaderProgram(m_tonemapGrProg.get());
 
 
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-	rgraphCtx.bindTexture(0, 1, inRt);
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+	rgraphCtx.bindTexture(ANKI_REG(t0), inRt);
 
 
-	rgraphCtx.bindStorageTexture(0, 2, getRenderer().getTonemapping().getRt());
+	rgraphCtx.bindTexture(ANKI_REG(u0), getRenderer().getTonemapping().getRt());
 
 
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{
@@ -451,7 +451,7 @@ void Scale::runTonemapping(RenderPassWorkContext& rgraphCtx)
 		pc.m_viewportSizeOverOne = 1.0f / Vec2(getRenderer().getPostProcessResolution());
 		pc.m_viewportSizeOverOne = 1.0f / Vec2(getRenderer().getPostProcessResolution());
 		pc.m_viewportSize = getRenderer().getPostProcessResolution();
 		pc.m_viewportSize = getRenderer().getPostProcessResolution();
 		cmdb.setPushConstants(&pc, sizeof(pc));
 		cmdb.setPushConstants(&pc, sizeof(pc));
-		rgraphCtx.bindStorageTexture(0, 3, outRt);
+		rgraphCtx.bindTexture(ANKI_REG(u1), outRt);
 
 
 		dispatchPPCompute(cmdb, 8, 8, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
 		dispatchPPCompute(cmdb, 8, 8, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
 	}
 	}

+ 6 - 6
AnKi/Renderer/ShadowMapping.cpp

@@ -594,12 +594,12 @@ BufferView ShadowMapping::createVetVisibilityPass(CString passName, const LightC
 		const UVec4 lightIndex(lightc.getGpuSceneLightAllocation().getIndex());
 		const UVec4 lightIndex(lightc.getGpuSceneLightAllocation().getIndex());
 		cmdb.setPushConstants(&lightIndex, sizeof(lightIndex));
 		cmdb.setPushConstants(&lightIndex, sizeof(lightIndex));
 
 
-		cmdb.bindStorageBuffer(0, 0, hashBuff);
-		cmdb.bindStorageBuffer(0, 1, mdiBuff);
-		cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::Light::getSingleton().getBufferView());
-		cmdb.bindStorageBuffer(0, 3, GpuSceneArrays::LightVisibleRenderablesHash::getSingleton().getBufferView());
-		cmdb.bindStorageBuffer(0, 4, clearTileIndirectArgs);
-		cmdb.bindStorageBuffer(0, 5, taskShadersIndirectArgs);
+		cmdb.bindStorageBuffer(ANKI_REG(t0), hashBuff);
+		cmdb.bindStorageBuffer(ANKI_REG(u0), mdiBuff);
+		cmdb.bindStorageBuffer(ANKI_REG(u1), GpuSceneArrays::Light::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(u2), GpuSceneArrays::LightVisibleRenderablesHash::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(u3), clearTileIndirectArgs);
+		cmdb.bindStorageBuffer(ANKI_REG(u4), taskShadersIndirectArgs);
 
 
 		ANKI_ASSERT(RenderStateBucketContainer::getSingleton().getBucketCount(RenderingTechnique::kDepth) <= 64 && "TODO");
 		ANKI_ASSERT(RenderStateBucketContainer::getSingleton().getBucketCount(RenderingTechnique::kDepth) <= 64 && "TODO");
 		cmdb.dispatchCompute(1, 1, 1);
 		cmdb.dispatchCompute(1, 1, 1);

+ 13 - 12
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -111,28 +111,29 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 
 
 	cmdb.bindShaderProgram(m_grProg.get());
 	cmdb.bindShaderProgram(m_grProg.get());
 
 
-	cmdb.bindUniformBuffer(0, 0, ctx.m_globalRenderingUniformsBuffer);
-	cmdb.bindStorageBuffer(0, 1, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-	rgraphCtx.bindTexture(0, 2, getRenderer().getShadowMapping().getShadowmapRt());
-	cmdb.bindStorageBuffer(0, 3, getRenderer().getClusterBinning().getClustersBuffer());
+	cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
+	cmdb.bindStorageBuffer(ANKI_REG(t0), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+	cmdb.bindStorageBuffer(ANKI_REG(t1), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+	rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getShadowMapping().getShadowmapRt());
+	cmdb.bindStorageBuffer(ANKI_REG(t3), getRenderer().getClusterBinning().getClustersBuffer());
 
 
-	cmdb.bindSampler(0, 4, getRenderer().getSamplers().m_trilinearClamp.get());
-	cmdb.bindSampler(0, 5, getRenderer().getSamplers().m_trilinearClampShadow.get());
-	cmdb.bindSampler(0, 6, getRenderer().getSamplers().m_trilinearRepeat.get());
+	cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+	cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClampShadow.get());
+	cmdb.bindSampler(ANKI_REG(s2), getRenderer().getSamplers().m_trilinearRepeat.get());
 
 
 	if(m_quarterRez)
 	if(m_quarterRez)
 	{
 	{
-		rgraphCtx.bindTexture(0, 7, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+		rgraphCtx.bindTexture(ANKI_REG(t4), getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 	}
 	}
 	else
 	else
 	{
 	{
-		rgraphCtx.bindTexture(0, 7, getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindTexture(ANKI_REG(t4), getRenderer().getGBuffer().getDepthRt());
 	}
 	}
-	cmdb.bindTexture(0, 8, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
+	cmdb.bindTexture(ANKI_REG(t5), TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
 
 
 	if(getRenderer().getRtShadowsEnabled())
 	if(getRenderer().getRtShadowsEnabled())
 	{
 	{
-		rgraphCtx.bindTexture(0, 9, getRenderer().getRtShadows().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t6), getRenderer().getRtShadows().getRt());
 	}
 	}
 
 
 	if(g_preferComputeCVar.get() || g_shadowMappingPcfCVar.get())
 	if(g_preferComputeCVar.get() || g_shadowMappingPcfCVar.get())
@@ -143,7 +144,7 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 
 
 	if(g_preferComputeCVar.get())
 	if(g_preferComputeCVar.get())
 	{
 	{
-		rgraphCtx.bindStorageTexture(0, 10, m_runCtx.m_rt);
+		rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_rt);
 		dispatchPPCompute(cmdb, 8, 8, m_rtDescr.m_width, m_rtDescr.m_height);
 		dispatchPPCompute(cmdb, 8, 8, m_rtDescr.m_width, m_rtDescr.m_height);
 	}
 	}
 	else
 	else

+ 11 - 11
AnKi/Renderer/Sky.cpp

@@ -112,7 +112,7 @@ void Sky::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_transmittanceLutGrProg.get());
 			cmdb.bindShaderProgram(m_transmittanceLutGrProg.get());
 
 
-			rgraphCtx.bindStorageTexture(0, 0, transmittanceLutRt);
+			rgraphCtx.bindTexture(ANKI_REG(u0), transmittanceLutRt);
 
 
 			dispatchPPCompute(cmdb, 8, 8, kTransmittanceLutSize.x(), kTransmittanceLutSize.y());
 			dispatchPPCompute(cmdb, 8, 8, kTransmittanceLutSize.x(), kTransmittanceLutSize.y());
 		});
 		});
@@ -133,9 +133,9 @@ void Sky::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_multipleScatteringLutGrProg.get());
 			cmdb.bindShaderProgram(m_multipleScatteringLutGrProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, transmittanceLutRt);
-			cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindStorageTexture(0, 2, multipleScatteringLutRt);
+			rgraphCtx.bindTexture(ANKI_REG(t0), transmittanceLutRt);
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(u0), multipleScatteringLutRt);
 
 
 			dispatchPPCompute(cmdb, 8, 8, kMultipleScatteringLutSize.x(), kMultipleScatteringLutSize.y());
 			dispatchPPCompute(cmdb, 8, 8, kMultipleScatteringLutSize.x(), kMultipleScatteringLutSize.y());
 		});
 		});
@@ -157,11 +157,11 @@ void Sky::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_skyLutGrProg.get());
 			cmdb.bindShaderProgram(m_skyLutGrProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, transmittanceLutRt);
-			rgraphCtx.bindTexture(0, 1, multipleScatteringLutRt);
-			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindStorageTexture(0, 3, m_runCtx.m_skyLutRt);
-			cmdb.bindUniformBuffer(0, 4, ctx.m_globalRenderingUniformsBuffer);
+			rgraphCtx.bindTexture(ANKI_REG(t0), transmittanceLutRt);
+			rgraphCtx.bindTexture(ANKI_REG(t1), multipleScatteringLutRt);
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_skyLutRt);
+			cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
 
 
 			dispatchPPCompute(cmdb, 8, 8, kSkyLutSize.x(), kSkyLutSize.y());
 			dispatchPPCompute(cmdb, 8, 8, kSkyLutSize.x(), kSkyLutSize.y());
 		});
 		});
@@ -180,8 +180,8 @@ void Sky::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_computeSunColorGrProg.get());
 			cmdb.bindShaderProgram(m_computeSunColorGrProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, transmittanceLutRt);
-			cmdb.bindStorageBuffer(0, 1, ctx.m_globalRenderingUniformsBuffer);
+			rgraphCtx.bindTexture(ANKI_REG(t0), transmittanceLutRt);
+			cmdb.bindStorageBuffer(ANKI_REG(u0), ctx.m_globalRenderingUniformsBuffer);
 
 
 			cmdb.dispatchCompute(1, 1, 1);
 			cmdb.dispatchCompute(1, 1, 1);
 		});
 		});

+ 15 - 15
AnKi/Renderer/Ssao.cpp

@@ -130,13 +130,13 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_grProg.get());
 			cmdb.bindShaderProgram(m_grProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, getRenderer().getGBuffer().getColorRt(2));
-			rgraphCtx.bindTexture(0, 1,
+			rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindTexture(ANKI_REG(t1),
 								  (g_ssaoQuarterRez.get()) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt());
 								  (g_ssaoQuarterRez.get()) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt());
 
 
-			cmdb.bindTexture(0, 2, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
-			cmdb.bindSampler(0, 3, getRenderer().getSamplers().m_trilinearRepeat.get());
-			cmdb.bindSampler(0, 4, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindTexture(ANKI_REG(t2), TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearRepeat.get());
+			cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
 
 
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
 
@@ -156,7 +156,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 
 			if(g_preferComputeCVar.get())
 			if(g_preferComputeCVar.get())
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 5, finalRt);
+				rgraphCtx.bindTexture(ANKI_REG(u0), finalRt);
 
 
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 			}
 			}
@@ -194,9 +194,9 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_spatialDenoiseGrProg.get());
 			cmdb.bindShaderProgram(m_spatialDenoiseGrProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, finalRt);
-			rgraphCtx.bindTexture(0, 2, getRenderer().getGBuffer().getDepthRt());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), finalRt);
+			rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getGBuffer().getDepthRt());
 
 
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
 
@@ -207,7 +207,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 
 			if(g_preferComputeCVar.get())
 			if(g_preferComputeCVar.get())
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 3, bentNormalsAndSsaoTempRt);
+				rgraphCtx.bindTexture(ANKI_REG(u0), bentNormalsAndSsaoTempRt);
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 			}
 			}
 			else
 			else
@@ -244,16 +244,16 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_tempralDenoiseGrProg.get());
 			cmdb.bindShaderProgram(m_tempralDenoiseGrProg.get());
 
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 1, bentNormalsAndSsaoTempRt);
-			rgraphCtx.bindTexture(0, 2, historyRt);
-			rgraphCtx.bindTexture(0, 3, getRenderer().getMotionVectors().getMotionVectorsRt());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t0), bentNormalsAndSsaoTempRt);
+			rgraphCtx.bindTexture(ANKI_REG(t1), historyRt);
+			rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getMotionVectors().getMotionVectorsRt());
 
 
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
 
 			if(g_preferComputeCVar.get())
 			if(g_preferComputeCVar.get())
 			{
 			{
-				rgraphCtx.bindStorageTexture(0, 4, finalRt);
+				rgraphCtx.bindTexture(ANKI_REG(u0), finalRt);
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 			}
 			}
 			else
 			else

+ 7 - 7
AnKi/Renderer/Ssr.cpp

@@ -126,17 +126,17 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 		consts.m_unprojectionParameters = ctx.m_matrices.m_unprojectionParameters;
 		consts.m_unprojectionParameters = ctx.m_matrices.m_unprojectionParameters;
 		consts.m_prevViewProjMatMulInvViewProjMat = ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 		consts.m_prevViewProjMatMulInvViewProjMat = ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 		consts.m_normalMat = Mat3x4(Vec3(0.0f), ctx.m_matrices.m_view.getRotationPart());
 		consts.m_normalMat = Mat3x4(Vec3(0.0f), ctx.m_matrices.m_view.getRotationPart());
-		*allocateAndBindConstants<SsrUniforms>(cmdb, 0, 0) = consts;
+		*allocateAndBindConstants<SsrUniforms>(cmdb, ANKI_REG(b0)) = consts;
 
 
-		cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
-		rgraphCtx.bindTexture(0, 2, getRenderer().getGBuffer().getColorRt(1));
-		rgraphCtx.bindTexture(0, 3, getRenderer().getGBuffer().getColorRt(2));
-		rgraphCtx.bindTexture(0, 4, getRenderer().getDepthDownscale().getRt());
-		rgraphCtx.bindTexture(0, 5, getRenderer().getDownscaleBlur().getRt());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getGBuffer().getColorRt(1));
+		rgraphCtx.bindTexture(ANKI_REG(t1), getRenderer().getGBuffer().getColorRt(2));
+		rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getDepthDownscale().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t3), getRenderer().getDownscaleBlur().getRt());
 
 
 		if(g_preferComputeCVar.get())
 		if(g_preferComputeCVar.get())
 		{
 		{
-			rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_ssrRt);
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_ssrRt);
 			dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 			dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
 		}
 		}
 		else
 		else

+ 7 - 7
AnKi/Renderer/TemporalAA.cpp

@@ -113,16 +113,16 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 
 
 		cmdb.bindShaderProgram(m_grProg.get());
 		cmdb.bindShaderProgram(m_grProg.get());
 
 
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-		rgraphCtx.bindTexture(0, 1, getRenderer().getLightShading().getRt());
-		rgraphCtx.bindTexture(0, 2, m_runCtx.m_historyRt);
-		rgraphCtx.bindTexture(0, 3, getRenderer().getMotionVectors().getMotionVectorsRt());
-		rgraphCtx.bindStorageTexture(0, 4, getRenderer().getTonemapping().getRt());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getLightShading().getRt());
+		rgraphCtx.bindTexture(ANKI_REG(t1), m_runCtx.m_historyRt);
+		rgraphCtx.bindTexture(ANKI_REG(t2), getRenderer().getMotionVectors().getMotionVectorsRt());
+		rgraphCtx.bindTexture(ANKI_REG(u0), getRenderer().getTonemapping().getRt());
 
 
 		if(g_preferComputeCVar.get())
 		if(g_preferComputeCVar.get())
 		{
 		{
-			rgraphCtx.bindStorageTexture(0, 5, m_runCtx.m_renderRt);
-			rgraphCtx.bindStorageTexture(0, 6, m_runCtx.m_tonemappedRt);
+			rgraphCtx.bindTexture(ANKI_REG(u1), m_runCtx.m_renderRt);
+			rgraphCtx.bindTexture(ANKI_REG(u2), m_runCtx.m_tonemappedRt);
 
 
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 		}
 		}

+ 2 - 2
AnKi/Renderer/Tonemapping.cpp

@@ -62,8 +62,8 @@ void Tonemapping::populateRenderGraph(RenderingContext& ctx)
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 
 		cmdb.bindShaderProgram(m_grProg.get());
 		cmdb.bindShaderProgram(m_grProg.get());
-		rgraphCtx.bindStorageTexture(0, 1, m_runCtx.m_exposureLuminanceHandle);
-		rgraphCtx.bindTexture(0, 0, getRenderer().getDownscaleBlur().getRt(), TextureSubresourceDescriptor::surface(m_inputTexMip, 0, 0));
+		rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_exposureLuminanceHandle);
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getDownscaleBlur().getRt(), TextureSubresourceDescriptor::surface(m_inputTexMip, 0, 0));
 
 
 		cmdb.dispatchCompute(1, 1, 1);
 		cmdb.dispatchCompute(1, 1, 1);
 	});
 	});

+ 14 - 17
AnKi/Renderer/Utils/Drawer.cpp

@@ -46,37 +46,34 @@ void RenderableDrawer::setState(const RenderableDrawerArguments& args, CommandBu
 
 
 		globalUniforms->m_enableHzbTesting = args.m_hzbTexture.isValid();
 		globalUniforms->m_enableHzbTesting = args.m_hzbTexture.isValid();
 
 
-		cmdb.bindUniformBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGlobalUniforms), globalUniformsToken);
+		cmdb.bindUniformBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_GLOBAL_UNIFORMS), globalUniformsToken);
 	}
 	}
 
 
 	// More globals
 	// More globals
-	cmdb.bindAllBindless(U32(MaterialSet::kBindless));
-	cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTrilinearRepeatSampler), args.m_sampler);
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kGpuScene), GpuSceneBuffer::getSingleton().getBufferView());
+	cmdb.bindSampler(ANKI_REG(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER), args.m_sampler);
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_GPU_SCENE), GpuSceneBuffer::getSingleton().getBufferView());
 
 
-#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType) \
-	cmdb.bindReadOnlyTexelBuffer( \
-		U32(MaterialSet::kGlobal), U32(MaterialBinding::kUnifiedGeometry_##fmt), \
+#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
+	cmdb.bindTexelBuffer( \
+		ANKI_REG(reg), \
 		BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
 		BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
 				   getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
 				   getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
 		Format::k##fmt);
 		Format::k##fmt);
 #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
 #include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
 
 
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kMeshletBoundingVolumes),
-						   UnifiedGeometryBuffer::getSingleton().getBufferView());
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kMeshletGeometryDescriptors),
-						   UnifiedGeometryBuffer::getSingleton().getBufferView());
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_MESHLET_BOUNDING_VOLUMES), UnifiedGeometryBuffer::getSingleton().getBufferView());
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_MESHLET_GEOMETRY_DESCRIPTORS), UnifiedGeometryBuffer::getSingleton().getBufferView());
 	if(args.m_mesh.m_meshletGroupInstancesBuffer.isValid())
 	if(args.m_mesh.m_meshletGroupInstancesBuffer.isValid())
 	{
 	{
-		cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kMeshletGroups), args.m_mesh.m_meshletGroupInstancesBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_MESHLET_GROUPS), args.m_mesh.m_meshletGroupInstancesBuffer);
 	}
 	}
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kRenderables), GpuSceneArrays::Renderable::getSingleton().getBufferView());
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kMeshLods), GpuSceneArrays::MeshLod::getSingleton().getBufferView());
-	cmdb.bindStorageBuffer(U32(MaterialSet::kGlobal), U32(MaterialBinding::kTransforms), GpuSceneArrays::Transform::getSingleton().getBufferView());
-	cmdb.bindTexture(U32(MaterialSet::kGlobal), U32(MaterialBinding::kHzbTexture),
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_RENDERABLES), GpuSceneArrays::Renderable::getSingleton().getBufferView());
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_MESH_LODS), GpuSceneArrays::MeshLod::getSingleton().getBufferView());
+	cmdb.bindStorageBuffer(ANKI_REG(ANKI_MATERIAL_REGISTER_TRANSFORMS), GpuSceneArrays::Transform::getSingleton().getBufferView());
+	cmdb.bindTexture(ANKI_REG(ANKI_MATERIAL_REGISTER_HZB_TEXTURE),
 					 (args.m_hzbTexture.isValid()) ? args.m_hzbTexture
 					 (args.m_hzbTexture.isValid()) ? args.m_hzbTexture
 												   : TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDescriptor::all()));
 												   : TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDescriptor::all()));
-	cmdb.bindSampler(U32(MaterialSet::kGlobal), U32(MaterialBinding::kNearestClampSampler), getRenderer().getSamplers().m_nearestNearestClamp.get());
+	cmdb.bindSampler(ANKI_REG(ANKI_MATERIAL_REGISTER_NEAREST_CLAMP_SAMPLER), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
 	// Misc
 	// Misc
 	cmdb.bindIndexBuffer(UnifiedGeometryBuffer::getSingleton().getBufferView(), IndexType::kU16);
 	cmdb.bindIndexBuffer(UnifiedGeometryBuffer::getSingleton().getBufferView(), IndexType::kU16);

+ 40 - 39
AnKi/Renderer/Utils/GpuVisibility.cpp

@@ -424,25 +424,26 @@ void GpuVisibility::populateRenderGraphInternal(Bool distanceBased, BaseGpuVisib
 			ANKI_ASSERT(0);
 			ANKI_ASSERT(0);
 		}
 		}
 
 
-		cmdb.bindStorageBuffer(0, 0, aabbsBuffer);
-		cmdb.bindStorageBuffer(0, 1, GpuSceneArrays::Renderable::getSingleton().getBufferView());
-		cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
-		cmdb.bindStorageBuffer(0, 3, GpuSceneArrays::Transform::getSingleton().getBufferView());
-		cmdb.bindStorageBuffer(0, 4, GpuSceneBuffer::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(t0), aabbsBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::Renderable::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(t2), GpuSceneArrays::MeshLod::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(t3), GpuSceneArrays::Transform::getSingleton().getBufferView());
+		cmdb.bindStorageBuffer(ANKI_REG(t4), GpuSceneBuffer::getSingleton().getBufferView());
 		if(gatherType & 1u)
 		if(gatherType & 1u)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 5, out.m_legacy.m_renderableInstancesBuffer);
-			cmdb.bindStorageBuffer(0, 6, out.m_legacy.m_drawIndexedIndirectArgsBuffer);
-			cmdb.bindStorageBuffer(0, 7, out.m_legacy.m_mdiDrawCountsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u0), out.m_legacy.m_renderableInstancesBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u1), out.m_legacy.m_drawIndexedIndirectArgsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u2), out.m_legacy.m_drawIndexedIndirectArgsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u3), out.m_legacy.m_mdiDrawCountsBuffer);
 		}
 		}
 		if(gatherType & 2u)
 		if(gatherType & 2u)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 8, out.m_mesh.m_taskShaderIndirectArgsBuffer);
-			cmdb.bindStorageBuffer(0, 9, out.m_mesh.m_meshletGroupInstancesBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u4), out.m_mesh.m_taskShaderIndirectArgsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u5), out.m_mesh.m_meshletGroupInstancesBuffer);
 		}
 		}
 
 
 		const U32 bucketCount = RenderStateBucketContainer::getSingleton().getBucketCount(technique);
 		const U32 bucketCount = RenderStateBucketContainer::getSingleton().getBucketCount(technique);
-		UVec2* instanceRanges = allocateAndBindStorageBuffer<UVec2>(cmdb, 0, 10, bucketCount);
+		UVec2* instanceRanges = allocateAndBindStorageBuffer<UVec2>(cmdb, ANKI_REG(t5), bucketCount);
 		for(U32 i = 0; i < bucketCount; ++i)
 		for(U32 i = 0; i < bucketCount; ++i)
 		{
 		{
 			const Bool legacyBucket = m_runCtx.m_renderableInstanceRanges[technique][i].m_instanceCount > 0;
 			const Bool legacyBucket = m_runCtx.m_renderableInstanceRanges[technique][i].m_instanceCount > 0;
@@ -461,7 +462,7 @@ void GpuVisibility::populateRenderGraphInternal(Bool distanceBased, BaseGpuVisib
 
 
 		if(frustumTestData)
 		if(frustumTestData)
 		{
 		{
-			FrustumGpuVisibilityUniforms* unis = allocateAndBindConstants<FrustumGpuVisibilityUniforms>(cmdb, 0, 11);
+			FrustumGpuVisibilityUniforms* unis = allocateAndBindConstants<FrustumGpuVisibilityUniforms>(cmdb, ANKI_REG(b0));
 
 
 			Array<Plane, 6> planes;
 			Array<Plane, 6> planes;
 			extractClipPlanes(frustumTestData->m_viewProjMat, planes);
 			extractClipPlanes(frustumTestData->m_viewProjMat, planes);
@@ -482,8 +483,8 @@ void GpuVisibility::populateRenderGraphInternal(Bool distanceBased, BaseGpuVisib
 
 
 			if(frustumTestData->m_hzbRt.isValid())
 			if(frustumTestData->m_hzbRt.isValid())
 			{
 			{
-				rpass.bindTexture(0, 12, frustumTestData->m_hzbRt);
-				cmdb.bindSampler(0, 13, getRenderer().getSamplers().m_nearestNearestClamp.get());
+				rpass.bindTexture(ANKI_REG(t6), frustumTestData->m_hzbRt);
+				cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 			}
 			}
 		}
 		}
 		else
 		else
@@ -504,12 +505,12 @@ void GpuVisibility::populateRenderGraphInternal(Bool distanceBased, BaseGpuVisib
 
 
 		if(gatherAabbIndices)
 		if(gatherAabbIndices)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 14, out.m_visibleAaabbIndicesBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u6), out.m_visibleAaabbIndicesBuffer);
 		}
 		}
 
 
 		if(genHash)
 		if(genHash)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 15, out.m_visiblesHashBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u7), out.m_visiblesHashBuffer);
 		}
 		}
 
 
 		dispatchPPCompute(cmdb, 64, 1, aabbCount, 1);
 		dispatchPPCompute(cmdb, 64, 1, aabbCount, 1);
@@ -612,17 +613,17 @@ void GpuVisibility::populateRenderGraphMeshletInternal(Bool passthrough, BaseGpu
 
 
 			cmdb.bindShaderProgram(m_meshletCullingGrProgs[hasHzb][isPassthrough].get());
 			cmdb.bindShaderProgram(m_meshletCullingGrProgs[hasHzb][isPassthrough].get());
 
 
-			cmdb.bindStorageBuffer(0, 0, meshletGroupInstancesBuffer);
-			cmdb.bindStorageBuffer(0, 1, GpuSceneArrays::Renderable::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 3, GpuSceneArrays::Transform::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 4, UnifiedGeometryBuffer::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 5, out.m_drawIndirectArgsBuffer);
-			cmdb.bindStorageBuffer(0, 6, out.m_meshletInstancesBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(t0), meshletGroupInstancesBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::Renderable::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t2), GpuSceneArrays::MeshLod::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t3), GpuSceneArrays::Transform::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t4), UnifiedGeometryBuffer::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(u0), out.m_drawIndirectArgsBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u1), out.m_meshletInstancesBuffer);
 			if(hasHzb)
 			if(hasHzb)
 			{
 			{
-				rpass.bindTexture(0, 7, nonPassthroughData->m_hzbRt);
-				cmdb.bindSampler(0, 8, getRenderer().getSamplers().m_nearestNearestClamp.get());
+				rpass.bindTexture(ANKI_REG(t5), nonPassthroughData->m_hzbRt);
+				cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 			}
 			}
 
 
 			class Consts
 			class Consts
@@ -808,7 +809,7 @@ void GpuVisibilityNonRenderables::populateRenderGraph(GpuVisibilityNonRenderable
 		default:
 		default:
 			ANKI_ASSERT(0);
 			ANKI_ASSERT(0);
 		}
 		}
-		cmdb.bindStorageBuffer(0, 0, objBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t0), objBuffer);
 
 
 		GpuVisibilityNonRenderableUniforms unis;
 		GpuVisibilityNonRenderableUniforms unis;
 		Array<Plane, 6> planes;
 		Array<Plane, 6> planes;
@@ -819,12 +820,12 @@ void GpuVisibilityNonRenderables::populateRenderGraph(GpuVisibilityNonRenderable
 		}
 		}
 		cmdb.setPushConstants(&unis, sizeof(unis));
 		cmdb.setPushConstants(&unis, sizeof(unis));
 
 
-		rgraph.bindStorageBuffer(0, 1, visibleIndicesBuffHandle);
-		cmdb.bindStorageBuffer(0, 2, BufferView(counterBuffer.get(), counterBufferOffset, sizeof(U32) * kCountersPerDispatch));
+		rgraph.bindStorageBuffer(ANKI_REG(u0), visibleIndicesBuffHandle);
+		cmdb.bindStorageBuffer(ANKI_REG(u1), BufferView(counterBuffer.get(), counterBufferOffset, sizeof(U32) * kCountersPerDispatch));
 
 
 		if(needsFeedback)
 		if(needsFeedback)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 3, feedbackBuffer);
+			cmdb.bindStorageBuffer(ANKI_REG(u2), feedbackBuffer);
 		}
 		}
 
 
 		dispatchPPCompute(cmdb, 64, 1, objCount, 1);
 		dispatchPPCompute(cmdb, 64, 1, objCount, 1);
@@ -901,14 +902,14 @@ void GpuVisibilityAccelerationStructures::pupulateRenderGraph(GpuVisibilityAccel
 
 
 			cmdb.setPushConstants(&unis, sizeof(unis));
 			cmdb.setPushConstants(&unis, sizeof(unis));
 
 
-			cmdb.bindStorageBuffer(0, 0, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 1, GpuSceneArrays::Renderable::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 3, GpuSceneArrays::Transform::getSingleton().getBufferView());
-			cmdb.bindStorageBuffer(0, 4, instancesBuff);
-			cmdb.bindStorageBuffer(0, 5, indicesBuff);
-			cmdb.bindStorageBuffer(0, 6, BufferView(m_counterBuffer.get(), 0, sizeof(U32) * 2));
-			cmdb.bindStorageBuffer(0, 7, zeroInstancesDispatchArgsBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(t0), GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::Renderable::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t2), GpuSceneArrays::MeshLod::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t3), GpuSceneArrays::Transform::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(u0), instancesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(u1), indicesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(u2), BufferView(m_counterBuffer.get(), 0, sizeof(U32) * 2));
+			cmdb.bindStorageBuffer(ANKI_REG(u3), zeroInstancesDispatchArgsBuff);
 
 
 			const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();
 			const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();
 			dispatchPPCompute(cmdb, 64, 1, aabbCount, 1);
 			dispatchPPCompute(cmdb, 64, 1, aabbCount, 1);
@@ -930,8 +931,8 @@ void GpuVisibilityAccelerationStructures::pupulateRenderGraph(GpuVisibilityAccel
 
 
 			cmdb.bindShaderProgram(m_zeroRemainingInstancesGrProg.get());
 			cmdb.bindShaderProgram(m_zeroRemainingInstancesGrProg.get());
 
 
-			cmdb.bindStorageBuffer(0, 0, indicesBuff);
-			cmdb.bindStorageBuffer(0, 1, instancesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(t0), indicesBuff);
+			cmdb.bindStorageBuffer(ANKI_REG(U0), instancesBuff);
 
 
 			cmdb.dispatchComputeIndirect(zeroInstancesDispatchArgsBuff);
 			cmdb.dispatchComputeIndirect(zeroInstancesDispatchArgsBuff);
 		});
 		});

+ 10 - 8
AnKi/Renderer/Utils/HzbGenerator.cpp

@@ -119,7 +119,7 @@ void HzbGenerator::populateRenderGraphInternal(ConstWeakArray<DispatchInput> dis
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 
 		cmdb.bindShaderProgram(m_genPyramidGrProg.get());
 		cmdb.bindShaderProgram(m_genPyramidGrProg.get());
-		cmdb.bindSampler(0, 3, m_maxSampler.isCreated() ? m_maxSampler.get() : getRenderer().getSamplers().m_trilinearClamp.get());
+		cmdb.bindSampler(ANKI_REG(s0), m_maxSampler.isCreated() ? m_maxSampler.get() : getRenderer().getSamplers().m_trilinearClamp.get());
 
 
 		for(U32 dispatch = 0; dispatch < dispatchCount; ++dispatch)
 		for(U32 dispatch = 0; dispatch < dispatchCount; ++dispatch)
 		{
 		{
@@ -149,6 +149,7 @@ void HzbGenerator::populateRenderGraphInternal(ConstWeakArray<DispatchInput> dis
 
 
 			cmdb.setPushConstants(&pc, sizeof(pc));
 			cmdb.setPushConstants(&pc, sizeof(pc));
 
 
+			Register mipsReg(ANKI_REG(u1));
 			for(U32 mip = 0; mip < kMaxMipsSinglePassDownsamplerCanProduce; ++mip)
 			for(U32 mip = 0; mip < kMaxMipsSinglePassDownsamplerCanProduce; ++mip)
 			{
 			{
 				TextureSubresourceDescriptor subresource = TextureSubresourceDescriptor::firstSurface();
 				TextureSubresourceDescriptor subresource = TextureSubresourceDescriptor::firstSurface();
@@ -161,12 +162,13 @@ void HzbGenerator::populateRenderGraphInternal(ConstWeakArray<DispatchInput> dis
 					subresource.m_mipmap = 0; // Put something random
 					subresource.m_mipmap = 0; // Put something random
 				}
 				}
 
 
-				rgraphCtx.bindStorageTexture(0, 0, in.m_dstHzbRt, subresource, mip);
+				rgraphCtx.bindTexture(mipsReg, in.m_dstHzbRt, subresource);
+				++mipsReg.m_bindPoint;
 			}
 			}
 
 
 			cmdb.bindStorageBuffer(
 			cmdb.bindStorageBuffer(
-				0, 1, BufferView(m_counterBuffer.get(), (firstCounterBufferElement + dispatch) * m_counterBufferElementSize, sizeof(U32)));
-			rgraphCtx.bindTexture(0, 2, in.m_srcDepthRt, TextureSubresourceDescriptor::firstSurface(DepthStencilAspectBit::kDepth));
+				ANKI_REG(u0), BufferView(m_counterBuffer.get(), (firstCounterBufferElement + dispatch) * m_counterBufferElementSize, sizeof(U32)));
+			rgraphCtx.bindTexture(ANKI_REG(t0), in.m_srcDepthRt, TextureSubresourceDescriptor::firstSurface(DepthStencilAspectBit::kDepth));
 
 
 			cmdb.dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
 			cmdb.dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
 		}
 		}
@@ -209,9 +211,9 @@ void HzbGenerator::populateRenderGraphDirectionalLight(const HzbDirectionalLight
 		pass.setWork([this, depthBufferRt = in.m_depthBufferRt, maxDepthRt, maxDepthRtSize](RenderPassWorkContext& rgraphCtx) {
 		pass.setWork([this, depthBufferRt = in.m_depthBufferRt, maxDepthRt, maxDepthRtSize](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 
-			rgraphCtx.bindTexture(0, 0, depthBufferRt, TextureSubresourceDescriptor::firstSurface(DepthStencilAspectBit::kDepth));
-			cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindStorageTexture(0, 2, maxDepthRt);
+			rgraphCtx.bindTexture(ANKI_REG(t0), depthBufferRt, TextureSubresourceDescriptor::firstSurface(DepthStencilAspectBit::kDepth));
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(u0), maxDepthRt);
 
 
 			cmdb.bindShaderProgram(m_maxDepthGrProg.get());
 			cmdb.bindShaderProgram(m_maxDepthGrProg.get());
 
 
@@ -283,7 +285,7 @@ void HzbGenerator::populateRenderGraphDirectionalLight(const HzbDirectionalLight
 
 
 			cmdb.bindShaderProgram(m_maxBoxGrProg.get());
 			cmdb.bindShaderProgram(m_maxBoxGrProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, maxDepthRt);
+			rgraphCtx.bindTexture(ANKI_REG(t0), maxDepthRt);
 
 
 			struct Uniforms
 			struct Uniforms
 			{
 			{

+ 21 - 20
AnKi/Renderer/Utils/TraditionalDeferredShading.cpp

@@ -59,8 +59,8 @@ void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShading
 	{
 	{
 		cmdb.bindShaderProgram(m_skyboxGrProgs[skyc->getSkyboxType()].get());
 		cmdb.bindShaderProgram(m_skyboxGrProgs[skyc->getSkyboxType()].get());
 
 
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		rgraphCtx.bindTexture(0, 1, info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t0), info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
 
 
 		TraditionalDeferredSkyboxUniforms unis = {};
 		TraditionalDeferredSkyboxUniforms unis = {};
 		unis.m_invertedViewProjectionMat = info.m_invViewProjectionMatrix;
 		unis.m_invertedViewProjectionMat = info.m_invViewProjectionMatrix;
@@ -74,16 +74,16 @@ void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShading
 		}
 		}
 		else if(skyc->getSkyboxType() == SkyboxType::kImage2D)
 		else if(skyc->getSkyboxType() == SkyboxType::kImage2D)
 		{
 		{
-			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearRepeatAniso.get());
-			cmdb.bindTexture(0, 3, TextureView(&skyc->getImageResource().getTexture(), TextureSubresourceDescriptor::all()));
+			cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearRepeatAniso.get());
+			cmdb.bindTexture(ANKI_REG(t1), TextureView(&skyc->getImageResource().getTexture(), TextureSubresourceDescriptor::all()));
 		}
 		}
 		else
 		else
 		{
 		{
-			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindTexture(0, 3, info.m_skyLutRenderTarget);
+			cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(t1), info.m_skyLutRenderTarget);
 		}
 		}
 
 
-		cmdb.bindUniformBuffer(0, 4, info.m_globalRendererConsts);
+		cmdb.bindUniformBuffer(ANKI_REG(b0), info.m_globalRendererConsts);
 
 
 		cmdb.setPushConstants(&unis, sizeof(unis));
 		cmdb.setPushConstants(&unis, sizeof(unis));
 
 
@@ -92,7 +92,7 @@ void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShading
 
 
 	// Light shading
 	// Light shading
 	{
 	{
-		TraditionalDeferredShadingUniforms* unis = allocateAndBindConstants<TraditionalDeferredShadingUniforms>(cmdb, 0, 0);
+		TraditionalDeferredShadingUniforms* unis = allocateAndBindConstants<TraditionalDeferredShadingUniforms>(cmdb, ANKI_REG(b0));
 
 
 		unis->m_invViewProjMat = info.m_invViewProjectionMatrix;
 		unis->m_invViewProjMat = info.m_invViewProjectionMatrix;
 		unis->m_cameraPos = info.m_cameraPosWSpace.xyz();
 		unis->m_cameraPos = info.m_cameraPosWSpace.xyz();
@@ -103,38 +103,39 @@ void TraditionalDeferredLightShading::drawLights(TraditionalDeferredLightShading
 			unis->m_dirLight.m_lightMatrix = info.m_dirLightMatrix;
 			unis->m_dirLight.m_lightMatrix = info.m_dirLightMatrix;
 		}
 		}
 
 
-		cmdb.bindStorageBuffer(0, 1, info.m_visibleLightsBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t0), info.m_visibleLightsBuffer);
 		if(GpuSceneArrays::Light::getSingleton().getElementCount() > 0)
 		if(GpuSceneArrays::Light::getSingleton().getElementCount() > 0)
 		{
 		{
-			cmdb.bindStorageBuffer(0, 2, GpuSceneArrays::Light::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneArrays::Light::getSingleton().getBufferView());
 		}
 		}
 		else
 		else
 		{
 		{
 			// Set something random
 			// Set something random
-			cmdb.bindStorageBuffer(0, 2, GpuSceneBuffer::getSingleton().getBufferView());
+			cmdb.bindStorageBuffer(ANKI_REG(t1), GpuSceneBuffer::getSingleton().getBufferView());
 		}
 		}
 
 
 		// NOTE: Use nearest sampler because we don't want the result to sample the near tiles
 		// NOTE: Use nearest sampler because we don't want the result to sample the near tiles
-		cmdb.bindSampler(0, 3, getRenderer().getSamplers().m_nearestNearestClamp.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
 
 
-		rgraphCtx.bindTexture(0, 4, info.m_gbufferRenderTargets[0], info.m_gbufferRenderTargetSubresource[0]);
-		rgraphCtx.bindTexture(0, 5, info.m_gbufferRenderTargets[1], info.m_gbufferRenderTargetSubresource[1]);
-		rgraphCtx.bindTexture(0, 6, info.m_gbufferRenderTargets[2], info.m_gbufferRenderTargetSubresource[2]);
-		rgraphCtx.bindTexture(0, 7, info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
+		rgraphCtx.bindTexture(ANKI_REG(t2), info.m_gbufferRenderTargets[0], info.m_gbufferRenderTargetSubresource[0]);
+		rgraphCtx.bindTexture(ANKI_REG(t3), info.m_gbufferRenderTargets[1], info.m_gbufferRenderTargetSubresource[1]);
+		rgraphCtx.bindTexture(ANKI_REG(t4), info.m_gbufferRenderTargets[2], info.m_gbufferRenderTargetSubresource[2]);
+		rgraphCtx.bindTexture(ANKI_REG(t5), info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
 
 
-		cmdb.bindSampler(0, 8, m_shadowSampler.get());
+		cmdb.bindSampler(ANKI_REG(s1), m_shadowSampler.get());
 		if(dirLightc && dirLightc->getShadowEnabled())
 		if(dirLightc && dirLightc->getShadowEnabled())
 		{
 		{
 			ANKI_ASSERT(info.m_directionalLightShadowmapRenderTarget.isValid());
 			ANKI_ASSERT(info.m_directionalLightShadowmapRenderTarget.isValid());
-			rgraphCtx.bindTexture(0, 9, info.m_directionalLightShadowmapRenderTarget, info.m_directionalLightShadowmapRenderTargetSubresource);
+			rgraphCtx.bindTexture(ANKI_REG(t6), info.m_directionalLightShadowmapRenderTarget,
+								  info.m_directionalLightShadowmapRenderTargetSubresource);
 		}
 		}
 		else
 		else
 		{
 		{
 			// No shadows for the dir light, bind a random depth texture (need depth because validation complains)
 			// No shadows for the dir light, bind a random depth texture (need depth because validation complains)
-			rgraphCtx.bindTexture(0, 9, info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
+			rgraphCtx.bindTexture(ANKI_REG(t6), info.m_gbufferDepthRenderTarget, info.m_gbufferDepthRenderTargetSubresource);
 		}
 		}
 
 
-		cmdb.bindUniformBuffer(0, 10, info.m_globalRendererConsts);
+		cmdb.bindUniformBuffer(ANKI_REG(b1), info.m_globalRendererConsts);
 
 
 		cmdb.bindShaderProgram(m_lightGrProg[info.m_computeSpecular].get());
 		cmdb.bindShaderProgram(m_lightGrProg[info.m_computeSpecular].get());
 
 

+ 3 - 3
AnKi/Renderer/VolumetricFog.cpp

@@ -58,10 +58,10 @@ void VolumetricFog::populateRenderGraph(RenderingContext& ctx)
 
 
 		cmdb.bindShaderProgram(m_grProg.get());
 		cmdb.bindShaderProgram(m_grProg.get());
 
 
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-		rgraphCtx.bindTexture(0, 1, getRenderer().getVolumetricLightingAccumulation().getRt());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearClamp.get());
+		rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getVolumetricLightingAccumulation().getRt());
 
 
-		rgraphCtx.bindStorageTexture(0, 2, m_runCtx.m_rt);
+		rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_rt);
 
 
 		const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
 		const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
 
 

+ 14 - 14
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -96,25 +96,25 @@ void VolumetricLightingAccumulation::populateRenderGraph(RenderingContext& ctx)
 		cmdb.bindShaderProgram(m_grProg.get());
 		cmdb.bindShaderProgram(m_grProg.get());
 
 
 		// Bind all
 		// Bind all
-		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
-		cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
-		cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
+		cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_trilinearRepeat.get());
+		cmdb.bindSampler(ANKI_REG(s1), getRenderer().getSamplers().m_trilinearClamp.get());
+		cmdb.bindSampler(ANKI_REG(s2), getRenderer().getSamplers().m_trilinearClampShadow.get());
 
 
-		rgraphCtx.bindStorageTexture(0, 3, m_runCtx.m_rts[1]);
+		rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_rts[1]);
 
 
-		cmdb.bindTexture(0, 4, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
+		cmdb.bindTexture(ANKI_REG(t0), TextureView(&m_noiseImage->getTexture(), TextureSubresourceDescriptor::all()));
 
 
-		rgraphCtx.bindTexture(0, 5, m_runCtx.m_rts[0]);
+		rgraphCtx.bindTexture(ANKI_REG(t1), m_runCtx.m_rts[0]);
 
 
-		cmdb.bindUniformBuffer(0, 6, ctx.m_globalRenderingUniformsBuffer);
-		cmdb.bindStorageBuffer(0, 7, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		rgraphCtx.bindTexture(0, 8, getRenderer().getShadowMapping().getShadowmapRt());
-		cmdb.bindStorageBuffer(0, 9,
+		cmdb.bindUniformBuffer(ANKI_REG(b0), ctx.m_globalRenderingUniformsBuffer);
+		cmdb.bindStorageBuffer(ANKI_REG(t2), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindStorageBuffer(ANKI_REG(t3), getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		rgraphCtx.bindTexture(ANKI_REG(t4), getRenderer().getShadowMapping().getShadowmapRt());
+		cmdb.bindStorageBuffer(ANKI_REG(t5),
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
 							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
-		cmdb.bindStorageBuffer(0, 10, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kFogDensityVolume));
-		cmdb.bindStorageBuffer(0, 11, getRenderer().getClusterBinning().getClustersBuffer());
-
-		cmdb.bindAllBindless(1);
+		cmdb.bindStorageBuffer(ANKI_REG(t6),
+							   getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kFogDensityVolume));
+		cmdb.bindStorageBuffer(ANKI_REG(t7), getRenderer().getClusterBinning().getClustersBuffer());
 
 
 		const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
 		const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
 
 

+ 6 - 6
AnKi/Renderer/VrsSriGeneration.cpp

@@ -140,9 +140,9 @@ void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_grProg.get());
 			cmdb.bindShaderProgram(m_grProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, getRenderer().getLightShading().getRt());
-			cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_nearestNearestClamp.get());
-			rgraphCtx.bindStorageTexture(0, 2, m_runCtx.m_rt);
+			rgraphCtx.bindTexture(ANKI_REG(t0), getRenderer().getLightShading().getRt());
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_rt);
 			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), g_vrsThresholdCVar.get(), 0.0f);
 			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), g_vrsThresholdCVar.get(), 0.0f);
 			cmdb.setPushConstants(&pc, sizeof(pc));
 			cmdb.setPushConstants(&pc, sizeof(pc));
 
 
@@ -167,9 +167,9 @@ void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 
 
 			cmdb.bindShaderProgram(m_downscaleGrProg.get());
 			cmdb.bindShaderProgram(m_downscaleGrProg.get());
 
 
-			rgraphCtx.bindTexture(0, 0, m_runCtx.m_rt);
-			cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_nearestNearestClamp.get());
-			rgraphCtx.bindStorageTexture(0, 2, m_runCtx.m_downscaledRt);
+			rgraphCtx.bindTexture(ANKI_REG(t0), m_runCtx.m_rt);
+			cmdb.bindSampler(ANKI_REG(s0), getRenderer().getSamplers().m_nearestNearestClamp.get());
+			rgraphCtx.bindTexture(ANKI_REG(u0), m_runCtx.m_downscaledRt);
 			const Vec4 pc(1.0f / Vec2(rezDownscaled), 0.0f, 0.0f);
 			const Vec4 pc(1.0f / Vec2(rezDownscaled), 0.0f, 0.0f);
 			cmdb.setPushConstants(&pc, sizeof(pc));
 			cmdb.setPushConstants(&pc, sizeof(pc));
 
 

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

@@ -73,7 +73,7 @@ Error GlobalIlluminationProbeComponent::update(SceneComponentUpdateInfo& info, B
 		cmdb->setPipelineBarrier({&texBarrier, 1}, {}, {});
 		cmdb->setPipelineBarrier({&texBarrier, 1}, {}, {});
 
 
 		cmdb->bindShaderProgram(&variant->getProgram());
 		cmdb->bindShaderProgram(&variant->getProgram());
-		cmdb->bindStorageTexture(0, 0, TextureView(m_volTex.get(), TextureSubresourceDescriptor::all()));
+		cmdb->bindTexture(ANKI_REG(u0), TextureView(m_volTex.get(), TextureSubresourceDescriptor::all()));
 
 
 		const Vec4 clearColor(0.0f);
 		const Vec4 clearColor(0.0f);
 		cmdb->setPushConstants(&clearColor, sizeof(clearColor));
 		cmdb->setPushConstants(&clearColor, sizeof(clearColor));

+ 20 - 0
AnKi/ShaderCompiler/Dxc.cpp

@@ -106,6 +106,26 @@ static Error compileHlsl(CString src, ShaderType shaderType, Bool compileWith16b
 		dxcArgs.emplaceBack("-spirv");
 		dxcArgs.emplaceBack("-spirv");
 		dxcArgs.emplaceBack("-fspv-target-env=vulkan1.1spirv1.4");
 		dxcArgs.emplaceBack("-fspv-target-env=vulkan1.1spirv1.4");
 		// dxcArgs.emplaceBack("-fvk-support-nonzero-base-instance"); // Match DX12's behavior, SV_INSTANCEID starts from zero
 		// dxcArgs.emplaceBack("-fvk-support-nonzero-base-instance"); // Match DX12's behavior, SV_INSTANCEID starts from zero
+
+		// Shift the bindings in order to identify the registers when doing reflection
+		for(U32 ds = 0; ds < kMaxDescriptorSets; ++ds)
+		{
+			dxcArgs.emplaceBack("-fvk-b-shift");
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kCbv]));
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+
+			dxcArgs.emplaceBack("-fvk-t-shift");
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kSrv]));
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+
+			dxcArgs.emplaceBack("-fvk-u-shift");
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kUav]));
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+
+			dxcArgs.emplaceBack("-fvk-s-shift");
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kSampler]));
+			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+		}
 	}
 	}
 	else
 	else
 	{
 	{

+ 6 - 0
AnKi/ShaderCompiler/Dxc.h

@@ -13,6 +13,12 @@ namespace anki {
 /// @addtogroup shader_compiler
 /// @addtogroup shader_compiler
 /// @{
 /// @{
 
 
+inline constexpr Array2d<U32, kMaxDescriptorSets, U32(HlslResourceType::kCount)> kDxcVkBindingShifts = {
+	{{1000, 2000, 3000, 4000}, {5000, 6000, 7000, 8000}, {9000, 10000, 11000, 12000}}};
+
+// !!!!WARNING!!!! Need to change HLSL if you change the value bellow
+inline constexpr U32 kDxcVkBindlessRegisterSpace = 1000000;
+
 /// Compile HLSL to SPIR-V.
 /// Compile HLSL to SPIR-V.
 Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16bitTypes, ShaderCompilerDynamicArray<U8>& spirv,
 Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16bitTypes, ShaderCompilerDynamicArray<U8>& spirv,
 						 ShaderCompilerString& errorMessage);
 						 ShaderCompilerString& errorMessage);

+ 95 - 67
AnKi/ShaderCompiler/ShaderCompiler.cpp

@@ -110,25 +110,7 @@ static Bool spinDials(ShaderCompilerDynamicArray<U32>& dials, ConstWeakArray<Sha
 	return done;
 	return done;
 }
 }
 
 
-template<typename TFunc>
-static void visitSpirv(ConstWeakArray<U32> spv, TFunc func)
-{
-	ANKI_ASSERT(spv.getSize() > 5);
-
-	const U32* it = &spv[5];
-	do
-	{
-		const U32 instructionCount = *it >> 16u;
-		const U32 opcode = *it & 0xFFFFu;
-
-		func(opcode);
-
-		it += instructionCount;
-	} while(it < spv.getEnd());
-
-	ANKI_ASSERT(it == spv.getEnd());
-}
-
+/// Does SPIR-V reflection and re-writes the SPIR-V binary's bindings
 Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
 Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
 {
 {
 	spirv_cross::Compiler spvc(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32));
 	spirv_cross::Compiler spvc(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32));
@@ -137,16 +119,15 @@ Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflect
 
 
 	auto func = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& resources, const DescriptorType origType,
 	auto func = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& resources, const DescriptorType origType,
 					const DescriptorFlag origFlags) -> Error {
 					const DescriptorFlag origFlags) -> Error {
-#if ANKI_GR_BACKEND_VULKAN
 		for(const spirv_cross::Resource& r : resources)
 		for(const spirv_cross::Resource& r : resources)
 		{
 		{
 			const U32 id = r.id;
 			const U32 id = r.id;
 
 
 			const U32 set = spvc.get_decoration(id, spv::Decoration::DecorationDescriptorSet);
 			const U32 set = spvc.get_decoration(id, spv::Decoration::DecorationDescriptorSet);
 			const U32 binding = spvc.get_decoration(id, spv::Decoration::DecorationBinding);
 			const U32 binding = spvc.get_decoration(id, spv::Decoration::DecorationBinding);
-			if(set >= kMaxDescriptorSets || binding >= kMaxBindingsPerDescriptorSet)
+			if(set >= kMaxDescriptorSets && set != kDxcVkBindlessRegisterSpace)
 			{
 			{
-				errorStr.sprintf("Exceeded set or binding for: %s", r.name.c_str());
+				errorStr.sprintf("Exceeded set for: %s", r.name.c_str());
 				return Error::kUserData;
 				return Error::kUserData;
 			}
 			}
 
 
@@ -154,81 +135,127 @@ Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflect
 			U32 arraySize = 1;
 			U32 arraySize = 1;
 			if(typeInfo.array.size() != 0)
 			if(typeInfo.array.size() != 0)
 			{
 			{
-				if(typeInfo.array.size() != 1 || (arraySize = typeInfo.array[0]) == 0)
+				if(typeInfo.array.size() != 1)
 				{
 				{
 					errorStr.sprintf("Only 1D arrays are supported: %s", r.name.c_str());
 					errorStr.sprintf("Only 1D arrays are supported: %s", r.name.c_str());
 					return Error::kUserData;
 					return Error::kUserData;
 				}
 				}
-			}
 
 
-			refl.m_descriptorSetMask.set(set);
+				if(set == kDxcVkBindlessRegisterSpace && typeInfo.array[0] != 0)
+				{
+					errorStr.sprintf("Only the bindless descriptor set can be an unbound array: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				arraySize = typeInfo.array[0];
+			}
 
 
 			// Images are special, they might be texel buffers
 			// Images are special, they might be texel buffers
 			DescriptorType type = origType;
 			DescriptorType type = origType;
 			DescriptorFlag flags = origFlags;
 			DescriptorFlag flags = origFlags;
-			if(type == DescriptorType::kTexture)
+			if(type == DescriptorType::kTexture && typeInfo.image.dim == spv::DimBuffer)
 			{
 			{
-				if(typeInfo.image.dim == spv::DimBuffer)
-				{
-					type = DescriptorType::kTexelBuffer;
+				type = DescriptorType::kTexelBuffer;
 
 
-					if(typeInfo.image.sampled == 1)
-					{
-						flags = DescriptorFlag::kRead;
-					}
-					else
-					{
-						ANKI_ASSERT(typeInfo.image.sampled == 2);
-						flags = DescriptorFlag::kReadWrite;
-					}
+				if(typeInfo.image.sampled == 1)
+				{
+					flags = DescriptorFlag::kRead;
+				}
+				else
+				{
+					ANKI_ASSERT(typeInfo.image.sampled == 2);
+					flags = DescriptorFlag::kReadWrite;
 				}
 				}
 			}
 			}
 
 
-			// Check that there are no other descriptors with the same binding
-			if(refl.m_descriptorTypes[set][binding] == DescriptorType::kCount)
+			if(set == kDxcVkBindlessRegisterSpace)
 			{
 			{
-				// New binding, init it
-				refl.m_descriptorTypes[set][binding] = type;
-				refl.m_descriptorArraySizes[set][binding] = U16(arraySize);
-				refl.m_descriptorFlags[set][binding] = flags;
+				// Bindless dset
+
+				if(arraySize != 0)
+				{
+					errorStr.sprintf("Unexpected unbound array for bindless: %s", r.name.c_str());
+				}
+
+				if(type != DescriptorType::kTexture || flags != DescriptorFlag::kRead)
+				{
+					errorStr.sprintf("Unexpected bindless binding: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				refl.m_descriptor.m_hasVkBindlessDescriptorSet = true;
 			}
 			}
 			else
 			else
 			{
 			{
-				// Same binding, make sure the type is compatible
-				if(refl.m_descriptorTypes[set][binding] != type || refl.m_descriptorArraySizes[set][binding] != arraySize
-				   || refl.m_descriptorFlags[set][binding] != flags)
+				// Regular binding
+
+				if(origType == DescriptorType::kStorageBuffer && binding >= kDxcVkBindingShifts[set][HlslResourceType::kSrv]
+				   && binding < kDxcVkBindingShifts[set][HlslResourceType::kSrv] + 1000)
+				{
+					// Storage buffer is read only
+					flags = DescriptorFlag::kRead;
+				}
+
+				const HlslResourceType hlslResourceType = descriptorTypeToHlslResourceType(type, flags);
+				if(binding < kDxcVkBindingShifts[set][hlslResourceType] || binding >= kDxcVkBindingShifts[set][hlslResourceType] + 1000)
 				{
 				{
-					errorStr.sprintf("Descriptor with same binding but different type or array size: %s", r.name.c_str());
+					errorStr.sprintf("Unexpected binding: %s", r.name.c_str());
 					return Error::kUserData;
 					return Error::kUserData;
 				}
 				}
+
+				ShaderReflectionBinding akBinding;
+				akBinding.m_registerBindingPoint = binding - kDxcVkBindingShifts[set][hlslResourceType];
+				akBinding.m_arraySize = U16(arraySize);
+				akBinding.m_type = type;
+				akBinding.m_flags = flags;
+
+				refl.m_descriptor.m_bindings[set][refl.m_descriptor.m_bindingCounts[set]] = akBinding;
+				++refl.m_descriptor.m_bindingCounts[set];
 			}
 			}
 		}
 		}
-#endif
 
 
 		return Error::kNone;
 		return Error::kNone;
 	};
 	};
 
 
-	Error err = Error::kNone;
-	err = func(rsrc.uniform_buffers, DescriptorType::kUniformBuffer, DescriptorFlag::kRead);
-	if(!err)
+	Error err = func(rsrc.uniform_buffers, DescriptorType::kUniformBuffer, DescriptorFlag::kRead);
+	if(err)
 	{
 	{
-		err = func(rsrc.separate_images, DescriptorType::kTexture, DescriptorFlag::kRead); // This also handles texel buffers
+		return err;
 	}
 	}
-	if(!err)
+
+	err = func(rsrc.separate_images, DescriptorType::kTexture, DescriptorFlag::kRead); // This also handles texel buffers
+	if(err)
 	{
 	{
-		err = func(rsrc.separate_samplers, DescriptorType::kSampler, DescriptorFlag::kRead);
+		return err;
 	}
 	}
-	if(!err)
+
+	err = func(rsrc.separate_samplers, DescriptorType::kSampler, DescriptorFlag::kRead);
+	if(err)
 	{
 	{
-		err = func(rsrc.storage_buffers, DescriptorType::kStorageBuffer, DescriptorFlag::kReadWrite);
+		return err;
 	}
 	}
-	if(!err)
+
+	err = func(rsrc.storage_buffers, DescriptorType::kStorageBuffer, DescriptorFlag::kReadWrite);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.storage_images, DescriptorType::kTexture, DescriptorFlag::kReadWrite);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.acceleration_structures, DescriptorType::kAccelerationStructure, DescriptorFlag::kRead);
+	if(err)
 	{
 	{
-		err = func(rsrc.storage_images, DescriptorType::kTexture, DescriptorFlag::kReadWrite);
+		return err;
 	}
 	}
-	if(!err)
+
+	for(U32 i = 0; i < kMaxDescriptorSets; ++i)
 	{
 	{
-		err = func(rsrc.acceleration_structures, DescriptorType::kAccelerationStructure, DescriptorFlag::kRead);
+		std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
 	}
 	}
 
 
 	// Color attachments
 	// Color attachments
@@ -319,12 +346,13 @@ Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflect
 	// Discards?
 	// Discards?
 	if(type == ShaderType::kFragment)
 	if(type == ShaderType::kFragment)
 	{
 	{
-		visitSpirv(ConstWeakArray<U32>(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32)), [&](U32 cmd) {
-			if(cmd == spv::OpKill)
-			{
-				refl.m_fragment.m_discards = true;
-			}
-		});
+		visitSpirv<ConstWeakArray>(ConstWeakArray<U32>(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32)),
+								   [&](U32 cmd, [[maybe_unused]] ConstWeakArray<U32> instructions) {
+									   if(cmd == spv::OpKill)
+									   {
+										   refl.m_fragment.m_discards = true;
+									   }
+								   });
 	}
 	}
 
 
 	return Error::kNone;
 	return Error::kNone;

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramBinary.xml

@@ -0,0 +1 @@
+

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramBinaryExtra.h

@@ -0,0 +1 @@
+

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramCompiler.cpp

@@ -0,0 +1 @@
+

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramCompiler.h

@@ -0,0 +1 @@
+

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramParser.cpp

@@ -0,0 +1 @@
+

+ 1 - 0
AnKi/ShaderCompiler/ShaderProgramParser.h

@@ -0,0 +1 @@
+

+ 4 - 4
AnKi/Shaders/ApplyIrradianceToReflection.ankiprog

@@ -7,10 +7,10 @@
 #include <AnKi/Shaders/PackFunctions.hlsl>
 #include <AnKi/Shaders/PackFunctions.hlsl>
 #include <AnKi/Shaders/LightFunctions.hlsl>
 #include <AnKi/Shaders/LightFunctions.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(1)]] TextureCube<Vec4> g_gbufferTex[3u];
-[[vk::binding(2)]] StructuredBuffer<RVec4> g_irradianceDice;
-[[vk::binding(3)]] RWTexture2D<RVec4> g_cubeTex[6u]; // RWTexture2D because there is no RWTextureCube
+SamplerState g_nearestAnyClampSampler : register(s0);
+TextureCube<Vec4> g_gbufferTex[3u] : register(t0);
+StructuredBuffer<RVec4> g_irradianceDice : register(t3);
+RWTexture2D<RVec4> g_cubeTex[6u] : register(u0); // RWTexture2D because there is no RWTextureCube
 
 
 [numthreads(8, 8, 6)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID, UVec3 svGroupThreadId : SV_GROUPTHREADID)
 [numthreads(8, 8, 6)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID, UVec3 svGroupThreadId : SV_GROUPTHREADID)
 {
 {

+ 5 - 6
AnKi/Shaders/Blit.ankiprog

@@ -6,8 +6,8 @@
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #	include <AnKi/Shaders/Functions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<RVec4> g_inputTex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec4> g_inputTex : register(t0);
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 #		define USE_COMPUTE 1
 #		define USE_COMPUTE 1
@@ -16,21 +16,20 @@
 #	endif
 #	endif
 
 
 #	if USE_COMPUTE
 #	if USE_COMPUTE
-[[vk::binding(2)]] RWTexture2D<RVec4> g_storageTex;
+RWTexture2D<RVec4> g_storageTex : register(u0);
 
 
 struct Uniforms
 struct Uniforms
 {
 {
 	Vec2 m_viewportSize;
 	Vec2 m_viewportSize;
 	UVec2 m_viewportSizeU;
 	UVec2 m_viewportSizeU;
 };
 };
-
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 #	endif
 #	endif
 
 
 #	if USE_COMPUTE
 #	if USE_COMPUTE
 [numthreads(8, 8, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(8, 8, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
 #	else
 #	else
-RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+RVec3 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 #	endif
 #	endif
 {
 {
 #	if USE_COMPUTE
 #	if USE_COMPUTE

+ 8 - 8
AnKi/Shaders/Bloom.ankiprog

@@ -6,11 +6,12 @@
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #	include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #	include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
-constexpr U32 kTonemappingBinding = 2u;
-#	include <AnKi/Shaders/TonemappingResources.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<RVec4> g_inTex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec4> g_inTex : register(t0);
+
+#	define TONEMAPPING_REGISTER u0
+#	include <AnKi/Shaders/TonemappingResources.hlsl>
 
 
 struct Uniforms
 struct Uniforms
 {
 {
@@ -19,19 +20,18 @@ struct Uniforms
 	F32 m_padding0;
 	F32 m_padding0;
 	F32 m_padding1;
 	F32 m_padding1;
 };
 };
-
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 #		define THREADGROUP_SIZE_X 8
 #		define THREADGROUP_SIZE_X 8
 #		define THREADGROUP_SIZE_Y 8
 #		define THREADGROUP_SIZE_Y 8
-[[vk::binding(3)]] RWTexture2D<RVec4> g_storageTex;
+RWTexture2D<RVec4> g_storageTex : register(u1);
 #	endif
 #	endif
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 [numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 #	else
 #	else
-RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+RVec3 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 #	endif
 #	endif
 {
 {
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER

+ 5 - 5
AnKi/Shaders/BloomUpscale.ankiprog

@@ -15,13 +15,13 @@ constexpr F32 kHaloWidth = 0.4;
 constexpr F32 kChromaticDistortion = 3.0;
 constexpr F32 kChromaticDistortion = 3.0;
 constexpr F32 kHaloOpacity = 0.5;
 constexpr F32 kHaloOpacity = 0.5;
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<RVec4> g_inputTex;
-[[vk::binding(2)]] Texture2D<RVec3> g_lensDirtTex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec4> g_inputTex : register(t0);
+Texture2D<RVec3> g_lensDirtTex : register(t1);
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 #		define THREADGROUP_SIZE_XY 8
 #		define THREADGROUP_SIZE_XY 8
-[[vk::binding(3)]] RWTexture2D<RVec4> g_storageTex;
+RWTexture2D<RVec4> g_storageTex : register(u0);
 #	endif
 #	endif
 
 
 RVec3 textureDistorted(Texture2D<RVec4> tex, SamplerState sampl, Vec2 uv,
 RVec3 textureDistorted(Texture2D<RVec4> tex, SamplerState sampl, Vec2 uv,
@@ -92,7 +92,7 @@ RVec3 upscale(Vec2 uv)
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 [numthreads(THREADGROUP_SIZE_XY, THREADGROUP_SIZE_XY, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(THREADGROUP_SIZE_XY, THREADGROUP_SIZE_XY, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 #	else
 #	else
-RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+RVec3 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 #	endif
 #	endif
 {
 {
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER

+ 5 - 5
AnKi/Shaders/ClearTextureCompute.ankiprog

@@ -20,19 +20,19 @@ struct Uniforms
 #endif
 #endif
 };
 };
 
 
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 #if TEXTURE_DIMENSIONS == 2
 #if TEXTURE_DIMENSIONS == 2
 #	if COMPONENT_TYPE == 0
 #	if COMPONENT_TYPE == 0
-[[vk::binding(0)]] RWTexture2D<Vec4> g_storageTex;
+RWTexture2D<Vec4> g_storageTex : register(u0);
 #	else
 #	else
-[[vk::binding(0)]] RWTexture2D<UVec4> g_storageTex;
+RWTexture2D<UVec4> g_storageTex : register(u0);
 #	endif
 #	endif
 #else
 #else
 #	if COMPONENT_TYPE == 0
 #	if COMPONENT_TYPE == 0
-[[vk::binding(0)]] RWTexture3D<Vec4> g_storageTex;
+RWTexture3D<Vec4> g_storageTex : register(u0);
 #	else
 #	else
-[[vk::binding(0)]] RWTexture3D<UVec4> g_storageTex;
+RWTexture3D<UVec4> g_storageTex : register(u0);
 #	endif
 #	endif
 #endif
 #endif
 
 

+ 4 - 5
AnKi/Shaders/ClusterBinning.ankiprog

@@ -44,13 +44,12 @@ struct ClusterBinningUniforms
 
 
 	Mat4 m_invertedViewProjMat;
 	Mat4 m_invertedViewProjMat;
 };
 };
+ANKI_PUSH_CONSTANTS(ClusterBinningUniforms, g_unis)
 
 
-[[vk::push_constant]] ConstantBuffer<ClusterBinningUniforms> g_unis;
+StructuredBuffer<U32> g_visibleObjectIds : register(t0); // 1st index is the count and then the indices to the g_objects
+StructuredBuffer<GpuSceneType> g_objects : register(t1);
 
 
-[[vk::binding(0)]] StructuredBuffer<U32> g_visibleObjectIds; // 1st index is the count and then the indices to the g_objects
-[[vk::binding(1)]] StructuredBuffer<GpuSceneType> g_objects;
-
-[[vk::binding(2)]] RWStructuredBuffer<Cluster> g_clusters;
+RWStructuredBuffer<Cluster> g_clusters : register(u0);
 
 
 #define THREADGROUP_SIZE 64
 #define THREADGROUP_SIZE 64
 
 

+ 3 - 3
AnKi/Shaders/ClusterBinningPackVisibles.ankiprog

@@ -29,9 +29,9 @@ typedef GpuSceneGlobalIlluminationProbe GpuSceneType;
 #	error See file
 #	error See file
 #endif
 #endif
 
 
-[[vk::binding(0)]] StructuredBuffer<GpuSceneType> g_inBuffer;
-[[vk::binding(1)]] RWStructuredBuffer<ClusteredType> g_outBuffer;
-[[vk::binding(2)]] StructuredBuffer<U32> g_visibles;
+StructuredBuffer<GpuSceneType> g_inBuffer : register(t0);
+RWStructuredBuffer<ClusteredType> g_outBuffer : register(u0);
+StructuredBuffer<U32> g_visibles : register(t1);
 
 
 #define THREAD_GROUP_SIZE 64
 #define THREAD_GROUP_SIZE 64
 
 

+ 3 - 3
AnKi/Shaders/ClusterBinningSetup.ankiprog

@@ -10,11 +10,11 @@
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 
 
-[[vk::binding(0)]] StructuredBuffer<U32> g_visibleIndices[(U32)GpuSceneNonRenderableObjectType::kCount];
+StructuredBuffer<U32> g_visibleIndices[(U32)GpuSceneNonRenderableObjectType::kCount] : register(t0);
 
 
 // This has a size of 2*GpuSceneNonRenderableObjectType::kCount. The first GpuSceneNonRenderableObjectType::kCount elements are for the cluster
 // This has a size of 2*GpuSceneNonRenderableObjectType::kCount. The first GpuSceneNonRenderableObjectType::kCount elements are for the cluster
 // binning dispatches and the rest GpuSceneNonRenderableObjectType::kCount for the packing dispatches
 // binning dispatches and the rest GpuSceneNonRenderableObjectType::kCount for the packing dispatches
-[[vk::binding(1)]] RWStructuredBuffer<DispatchIndirectArgs> g_indirectArgs;
+RWStructuredBuffer<DispatchIndirectArgs> g_indirectArgs : register(u0);
 
 
 struct Uniforms
 struct Uniforms
 {
 {
@@ -23,7 +23,7 @@ struct Uniforms
 	U32 m_padding2;
 	U32 m_padding2;
 	U32 m_padding3;
 	U32 m_padding3;
 };
 };
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 constexpr U32 kSampleCount = 8;
 constexpr U32 kSampleCount = 8;
 constexpr U32 kClusterBinningThreadgroupSize = 64;
 constexpr U32 kClusterBinningThreadgroupSize = 64;

+ 58 - 0
AnKi/Shaders/Common.hlsl

@@ -13,6 +13,64 @@
 #	include <AnKi/Shaders/Include/Common.h>
 #	include <AnKi/Shaders/Include/Common.h>
 #endif
 #endif
 
 
+#if ANKI_GR_BACKEND_VULKAN
+#	define ANKI_PUSH_CONSTANTS(type, var) [[vk::push_constant]] ConstantBuffer<type> var;
+#else
+#	define ANKI_PUSH_CONSTANTS(type, var) ConstantBuffer<type> var : register(b0, space3000);
+#endif
+
+#if ANKI_GR_BACKEND_VULKAN
+#	define ANKI_BINDLESS(texType, compType) \
+		[[vk::binding(0, 1000000)]] Texture##texType<compType> g_bindlessTextures##texType##compType[]; \
+		Texture##texType<compType> getBindlessTexture##texType##compType(U32 idx) \
+		{ \
+			return g_bindlessTextures##texType##compType[idx]; \
+		} \
+		Texture##texType<compType> getBindlessTextureNonUniformIndex##texType##compType(U32 idx) \
+		{ \
+			return g_bindlessTextures##texType##compType[NonUniformResourceIndex(idx)]; \
+		}
+#else
+#	define ANKI_BINDLESS(texType, compType) \
+		Texture##texType<compType> getBindlessTexture##texType##compType(U32 idx) \
+		{ \
+			Texture##texType<compType> tex = ResourceDescriptorHeap[idx]; \
+			return tex; \
+		} \
+		Texture##texType<compType> getBindlessTextureNonUniformIndex##texType##compType(U32 idx) \
+		{ \
+			Texture##texType<compType> tex = ResourceDescriptorHeap[NonUniformResourceIndex(idx)]; \
+			return tex; \
+		}
+#endif
+
+#if ANKI_SUPPORTS_16BIT_TYPES
+#	define ANKI_BINDLESS2(texType) \
+		ANKI_BINDLESS(texType, UVec4) \
+		ANKI_BINDLESS(texType, IVec4) \
+		ANKI_BINDLESS(texType, Vec4)
+
+#	define ANKI_BINDLESS3() \
+		ANKI_BINDLESS2(2D) \
+		ANKI_BINDLESS2(Cube) \
+		ANKI_BINDLESS2(2DArray) \
+		ANKI_BINDLESS2(3D)
+#else
+#	define ANKI_BINDLESS2(texType) \
+		ANKI_BINDLESS(texType, UVec4) \
+		ANKI_BINDLESS(texType, IVec4) \
+		ANKI_BINDLESS(texType, Vec4) \
+		ANKI_BINDLESS(texType, RVec4)
+
+#	define ANKI_BINDLESS3() \
+		ANKI_BINDLESS2(2D) \
+		ANKI_BINDLESS2(Cube) \
+		ANKI_BINDLESS2(2DArray) \
+		ANKI_BINDLESS2(3D)
+#endif
+
+ANKI_BINDLESS3()
+
 template<typename T>
 template<typename T>
 T uvToNdc(T x)
 T uvToNdc(T x)
 {
 {

+ 8 - 8
AnKi/Shaders/DbgBillboard.ankiprog

@@ -19,7 +19,7 @@ struct Uniforms
 	Mat3x4 m_camTrf;
 	Mat3x4 m_camTrf;
 };
 };
 
 
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 #if OBJECT_TYPE == ANKI_GPU_SCENE_NON_RENDERABLE_OBJECT_TYPE_LIGHT
 #if OBJECT_TYPE == ANKI_GPU_SCENE_NON_RENDERABLE_OBJECT_TYPE_LIGHT
 typedef LightUnion ClusteredType;
 typedef LightUnion ClusteredType;
@@ -35,8 +35,8 @@ typedef GlobalIlluminationProbe ClusteredType;
 #	error See file
 #	error See file
 #endif
 #endif
 
 
-[[vk::binding(2)]] StructuredBuffer<ClusteredType> g_visibleObjects;
-[[vk::binding(3)]] StructuredBuffer<U32> g_visibleObjectCount;
+StructuredBuffer<ClusteredType> g_visibleObjects : register(t1);
+StructuredBuffer<U32> g_visibleObjectCount : register(t2);
 
 
 struct VertOut
 struct VertOut
 {
 {
@@ -102,14 +102,14 @@ VertOut main(VertIn input)
 #pragma anki technique_start frag
 #pragma anki technique_start frag
 #include <AnKi/Shaders/ImportanceSampling.hlsl>
 #include <AnKi/Shaders/ImportanceSampling.hlsl>
 
 
-[[vk::binding(4)]] SamplerState g_trilinearRepeatSampler;
-[[vk::binding(5)]] Texture2D<Vec4> g_tex;
-[[vk::binding(6)]] Texture2D<Vec4> g_tex2;
+SamplerState g_trilinearRepeatSampler : register(s1);
+Texture2D<Vec4> g_tex : register(t3);
+Texture2D<Vec4> g_tex2 : register(t4);
 
 
 // NOTE: Don't eliminate the binding because it confuses the descriptor set creation
 // NOTE: Don't eliminate the binding because it confuses the descriptor set creation
 #if DEPTH_FAIL_VISUALIZATION == 1
 #if DEPTH_FAIL_VISUALIZATION == 1
-[[vk::binding(0)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(1)]] Texture2D g_depthRt;
+SamplerState g_nearestAnyClampSampler : register(s0);
+Texture2D g_depthRt : register(t0);
 #endif
 #endif
 
 
 Vec4 main(VertOut input) : SV_TARGET0
 Vec4 main(VertOut input) : SV_TARGET0

+ 6 - 6
AnKi/Shaders/DbgRenderables.ankiprog

@@ -14,10 +14,10 @@ struct Uniforms
 	Mat4 m_viewProjMat;
 	Mat4 m_viewProjMat;
 };
 };
 
 
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
-[[vk::binding(2)]] StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes;
-[[vk::binding(3)]] StructuredBuffer<U32> g_visibleRenderableBoundingVolumeIndices;
+StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes : register(t1);
+StructuredBuffer<U32> g_visibleRenderableBoundingVolumeIndices : register(t2);
 
 
 struct VertOut
 struct VertOut
 {
 {
@@ -27,7 +27,7 @@ struct VertOut
 #pragma anki technique_start vert
 #pragma anki technique_start vert
 struct VertIn
 struct VertIn
 {
 {
-	[[vk::location(0)]] Vec3 m_position : POSITION;
+	Vec3 m_position : POSITION;
 	U32 m_svInstanceId : SV_INSTANCEID;
 	U32 m_svInstanceId : SV_INSTANCEID;
 };
 };
 
 
@@ -59,8 +59,8 @@ VertOut main(VertIn input)
 
 
 // NOTE: Don't eliminate the binding because it confuses the descriptor set creation
 // NOTE: Don't eliminate the binding because it confuses the descriptor set creation
 #if DEPTH_FAIL_VISUALIZATION == 1
 #if DEPTH_FAIL_VISUALIZATION == 1
-[[vk::binding(0)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(1)]] Texture2D g_depthRt;
+SamplerState g_nearestAnyClampSampler : register(s0);
+Texture2D g_depthRt : register(t0);
 #endif
 #endif
 
 
 Vec4 main(VertOut input) : SV_TARGET0
 Vec4 main(VertOut input) : SV_TARGET0

+ 5 - 5
AnKi/Shaders/DepthAwareBlur.ankiprog

@@ -30,13 +30,13 @@ typedef F32 ColorType;
 #		error See file
 #		error See file
 #	endif
 #	endif
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<ColorType> g_inTex;
-[[vk::binding(2)]] Texture2D<Vec4> g_depthTex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<ColorType> g_inTex : register(t0);
+Texture2D<Vec4> g_depthTex : register(t1);
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 #		define THREADGROUP_SQRT_SIZE 8
 #		define THREADGROUP_SQRT_SIZE 8
-[[vk::binding(3)]] RWTexture2D<ColorType> g_outImg;
+RWTexture2D<ColorType> g_outImg : register(u0);
 #	endif
 #	endif
 
 
 F32 computeDepthWeight(F32 refDepth, F32 depth)
 F32 computeDepthWeight(F32 refDepth, F32 depth)
@@ -62,7 +62,7 @@ void sampleTex(Vec2 uv, F32 refDepth, inout ColorType col, inout F32 weight)
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 [numthreads(THREADGROUP_SQRT_SIZE, THREADGROUP_SQRT_SIZE, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(THREADGROUP_SQRT_SIZE, THREADGROUP_SQRT_SIZE, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 #	else
 #	else
-ColorType main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+ColorType main(Vec2 uv : TEXCOORD) : SV_TARGET0
 #	endif
 #	endif
 {
 {
 	UVec2 textureSize;
 	UVec2 textureSize;

+ 8 - 8
AnKi/Shaders/DepthDownscale.ankiprog

@@ -9,13 +9,13 @@
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 
 
-[[vk::push_constant]] ConstantBuffer<DepthDownscaleUniforms> g_unis;
+ANKI_PUSH_CONSTANTS(DepthDownscaleUniforms, g_unis)
 
 
-[[vk::binding(0)]] RWTexture2D<Vec4> g_dstStorageTextures[kMaxMipsSinglePassDownsamplerCanProduce];
-[[vk::binding(1)]] globallycoherent RWStructuredBuffer<U32> g_spdCounter;
+globallycoherent RWStructuredBuffer<U32> g_spdCounter : register(u0);
+RWTexture2D<Vec4> g_dstStorageTextures[kMaxMipsSinglePassDownsamplerCanProduce] : register(u1);
 
 
-[[vk::binding(2)]] SamplerState u_linearAnyClampSampler;
-[[vk::binding(3)]] Texture2D g_srcTex;
+SamplerState u_linearAnyClampSampler : register(s0);
+Texture2D g_srcTex : register(t0);
 
 
 // Include SPD
 // Include SPD
 #define A_GPU 1
 #define A_GPU 1
@@ -101,10 +101,10 @@ AF4 SpdReduce4(AF4 v0, AF4 v1, AF4 v2, AF4 v3)
 #pragma anki technique_start frag
 #pragma anki technique_start frag
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 
 
-[[vk::binding(0)]] Texture2D<Vec4> g_inputTex;
-[[vk::binding(1)]] SamplerState g_linearAnyClampSampler;
+Texture2D<Vec4> g_inputTex : register(t0);
+SamplerState g_linearAnyClampSampler : register(s0);
 
 
-F32 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+F32 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 {
 {
 	return g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).x;
 	return g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).x;
 }
 }

+ 6 - 6
AnKi/Shaders/DownscaleBlur.ankiprog

@@ -7,10 +7,10 @@
 #	include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #	include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<RVec3> g_tex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec3> g_tex : register(t0);
 
 
-constexpr U32 kTonemappingBinding = 2u;
+#	define TONEMAPPING_REGISTER u0
 #	include <AnKi/Shaders/TonemappingResources.hlsl>
 #	include <AnKi/Shaders/TonemappingResources.hlsl>
 
 
 struct Uniforms
 struct Uniforms
@@ -18,16 +18,16 @@ struct Uniforms
 	Vec2 m_fbSize;
 	Vec2 m_fbSize;
 	UVec2 m_padding;
 	UVec2 m_padding;
 };
 };
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
-[[vk::binding(3)]] RWTexture2D<RVec4> g_storageTex;
+RWTexture2D<RVec4> g_storageTex : register(u1);
 #	endif
 #	endif
 
 
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
 [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
 #	else
 #	else
-RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+RVec3 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 #	endif
 #	endif
 {
 {
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER

+ 0 - 123
AnKi/Shaders/DrawerStats.ankiprog

@@ -1,123 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-// Used in stat collection in the RenderableDrawer.
-// It's simple drawcall that draws a very small quad to the screen. Only one thread of the fragment shader will read the multi-draw counts and write
-// the number of drawcalls in a buffer.
-
-#pragma anki mutator COLOR_ATTACHMENT_COUNT 0 1 4
-
-#include <AnKi/Shaders/Common.hlsl>
-
-constexpr U32 kQuadSizeXY = 4;
-constexpr U32 kThreadCount = kQuadSizeXY * kQuadSizeXY;
-
-struct Uniforms
-{
-	UVec4 m_viewport;
-};
-
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
-
-#pragma anki technique_start vert
-
-struct VertOut
-{
-	Vec4 m_position : SV_POSITION;
-};
-
-VertOut main(U32 vertId : SV_VERTEXID)
-{
-	Vec2 uv = Vec2(vertId & 1u, ((vertId + 1u) / 3u) & 1u);
-
-	uv *= 1.0f / Vec2(g_unis.m_viewport.zw) * F32(kQuadSizeXY);
-
-	VertOut output;
-	output.m_position = Vec4(uv * 2.0 - 1.0, 0.0, 1.0);
-
-	return output;
-}
-#pragma anki technique_end vert
-
-#pragma anki technique_start frag
-
-[[vk::binding(0)]] StructuredBuffer<U32> g_mdiDrawCounts;
-[[vk::binding(1)]] StructuredBuffer<DrawIndexedIndirectArgs> g_drawArguments;
-[[vk::binding(2)]] StructuredBuffer<U32> g_bucketFirstDrawArgIndex;
-
-[[vk::binding(3)]] RWStructuredBuffer<U32> g_stats;
-[[vk::binding(4)]] RWStructuredBuffer<U32> g_threadExecuted;
-
-#if COLOR_ATTACHMENT_COUNT > 0
-struct FragOut
-{
-	Vec4 m_color0 : SV_TARGET0;
-#	if COLOR_ATTACHMENT_COUNT == 4
-	Vec4 m_color1 : SV_TARGET1;
-	Vec4 m_color2 : SV_TARGET2;
-	Vec2 m_color3 : SV_TARGET3;
-#	endif
-};
-#endif
-
-#if COLOR_ATTACHMENT_COUNT > 0
-FragOut
-#else
-void
-#endif
-main(Vec4 svPosition : SV_POSITION)
-{
-	const UVec2 pos = UVec2(svPosition.xy - Vec2(g_unis.m_viewport.xy));
-	const U32 threadIdx = pos.y * kQuadSizeXY + pos.x;
-
-	U32 threadsExecuted;
-	InterlockedAdd(g_threadExecuted[0], 1, threadsExecuted);
-	++threadsExecuted;
-
-	const Bool firstPass = threadsExecuted <= kThreadCount;
-
-	U32 bucketCount, unused;
-	g_mdiDrawCounts.GetDimensions(bucketCount, unused);
-
-	// Calc visible count
-	U32 visiblesCount = 0u;
-	U32 itemsPerThread = (bucketCount + (kThreadCount - 1)) / kThreadCount;
-	for(U32 bucket = threadIdx * itemsPerThread; bucket < min(bucketCount, (threadIdx + 1u) * itemsPerThread); ++bucket)
-	{
-		visiblesCount += g_mdiDrawCounts[bucket];
-	}
-
-	// Calc primitive count
-	U32 primitiveCount = 0u;
-	for(U32 bucket = 0; bucket < bucketCount; ++bucket)
-	{
-		const U32 drawCount = g_mdiDrawCounts[bucket];
-		itemsPerThread = (drawCount + (kThreadCount - 1)) / kThreadCount;
-
-		for(U32 draw = threadIdx * itemsPerThread; draw < min(drawCount, (threadIdx + 1u) * itemsPerThread); ++draw)
-		{
-			primitiveCount += g_drawArguments[g_bucketFirstDrawArgIndex[bucket] + draw].m_indexCount;
-		}
-	}
-
-	if(firstPass)
-	{
-		U32 origValue;
-		InterlockedExchange(g_stats[threadIdx], visiblesCount, origValue);
-		InterlockedExchange(g_stats[threadIdx + kThreadCount], primitiveCount, origValue);
-	}
-	else
-	{
-		InterlockedAdd(g_stats[threadIdx], visiblesCount);
-		InterlockedAdd(g_stats[threadIdx + kThreadCount], primitiveCount);
-	}
-
-	discard;
-
-#if COLOR_ATTACHMENT_COUNT > 0
-	return (FragOut)0;
-#endif
-}
-#pragma anki technique_end frag

+ 11 - 12
AnKi/Shaders/FinalComposite.ankiprog

@@ -15,16 +15,16 @@
 #include <AnKi/Shaders/Functions.hlsl>
 #include <AnKi/Shaders/Functions.hlsl>
 #include <AnKi/Shaders/MotionBlur.hlsl>
 #include <AnKi/Shaders/MotionBlur.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(1)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(2)]] SamplerState g_trilinearRepeatSampler;
-[[vk::binding(3)]] Texture2D<RVec4> g_lightShadingRt;
-[[vk::binding(4)]] Texture2D<RVec4> g_ppsBloomLfRt;
-[[vk::binding(5)]] Texture3D<RVec4> g_lut;
-[[vk::binding(6)]] Texture2D g_motionVectorsRt;
-[[vk::binding(7)]] Texture2D g_depthRt;
+SamplerState g_nearestAnyClampSampler : register(s0);
+SamplerState g_linearAnyClampSampler : register(s1);
+SamplerState g_trilinearRepeatSampler : register(s2);
+Texture2D<RVec4> g_lightShadingRt : register(t0);
+Texture2D<RVec4> g_ppsBloomLfRt : register(t1);
+Texture3D<RVec4> g_lut : register(t2);
+Texture2D g_motionVectorsRt : register(t3);
+Texture2D g_depthRt : register(t4);
 #if DBG_ENABLED
 #if DBG_ENABLED
-[[vk::binding(8)]] Texture2D<RVec4> g_dbgOutlineRt;
+Texture2D<RVec4> g_dbgOutlineRt : register(t5);
 #endif
 #endif
 
 
 struct Uniforms
 struct Uniforms
@@ -34,8 +34,7 @@ struct Uniforms
 	U32 m_frameCount;
 	U32 m_frameCount;
 	U32 m_padding;
 	U32 m_padding;
 };
 };
-
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 RVec3 colorGrading(RVec3 color)
 RVec3 colorGrading(RVec3 color)
 {
 {
@@ -50,7 +49,7 @@ RVec3 colorGrading(RVec3 color)
 	return g_lut.SampleLevel(g_trilinearRepeatSampler, lutCoords, 0.0).rgb;
 	return g_lut.SampleLevel(g_trilinearRepeatSampler, lutCoords, 0.0).rgb;
 }
 }
 
 
-RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD) : SV_TARGET0
+RVec3 main(Vec2 uv : TEXCOORD) : SV_TARGET0
 {
 {
 	RVec3 outColor;
 	RVec3 outColor;
 
 

+ 1 - 1
AnKi/Shaders/ForwardShadingGenericTransparent.ankiprog

@@ -62,7 +62,7 @@ FragOut main(VertOut input)
 	output.m_color = RVec4(1.0, 1.0, 1.0, 1.0);
 	output.m_color = RVec4(1.0, 1.0, 1.0, 1.0);
 
 
 #if TEXTURE == 1
 #if TEXTURE == 1
-	output.m_color = g_bindlessTextures2dF32[localUniforms.m_texture].Sample(g_globalSampler, input.m_uv);
+	output.m_color = getBindlessTexture2DRVec4(localUniforms.m_texture).Sample(g_globalSampler, input.m_uv);
 #endif
 #endif
 
 
 #if LIGHT == 1
 #if LIGHT == 1

+ 3 - 3
AnKi/Shaders/ForwardShadingParticles.ankiprog

@@ -76,10 +76,10 @@ FragOut main(VertOut input)
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, WaveReadLaneFirst(input.m_uniformsOffset));
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, WaveReadLaneFirst(input.m_uniformsOffset));
 
 
 #if ANIMATED_TEXTURE == 1
 #if ANIMATED_TEXTURE == 1
-	RVec4 texCol = readAnimatedTextureRgba(g_bindlessTextures2dArrayF32[localUniforms.m_diffuseMap], g_globalSampler, localUniforms.m_animationPeriod,
-										   input.m_uv, g_globalRendererUniforms.m_time);
+	RVec4 texCol = readAnimatedTextureRgba(getBindlessTexture2DArrayRVec4(localUniforms.m_diffuseMap), g_globalSampler,
+										   localUniforms.m_animationPeriod, input.m_uv, g_globalRendererUniforms.m_time);
 #else
 #else
-	RVec4 texCol = g_bindlessTextures2dF32[localUniforms.m_diffuseMap].Sample(g_globalSampler, input.m_uv);
+	RVec4 texCol = getBindlessTexture2DRVec4(localUniforms.m_diffuseMap).Sample(g_globalSampler, input.m_uv);
 #endif
 #endif
 
 
 #if LIGHT
 #if LIGHT

+ 4 - 4
AnKi/Shaders/Fsr.ankiprog

@@ -10,10 +10,10 @@
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #if ANKI_COMPUTE_SHADER || ANKI_FRAGMENT_SHADER
 #	include <AnKi/Shaders/Functions.hlsl>
 #	include <AnKi/Shaders/Functions.hlsl>
 
 
-[[vk::binding(0)]] SamplerState g_linearAnyClampSampler;
-[[vk::binding(1)]] Texture2D<Vec4> g_tex;
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<Vec4> g_tex : register(t0);
 #	if ANKI_COMPUTE_SHADER
 #	if ANKI_COMPUTE_SHADER
-[[vk::binding(2)]] RWTexture2D<Vec4> g_storageTex;
+RWTexture2D<Vec4> g_storageTex : register(u0);
 #	endif
 #	endif
 
 
 struct Uniforms
 struct Uniforms
@@ -26,7 +26,7 @@ struct Uniforms
 	UVec2 m_padding;
 	UVec2 m_padding;
 };
 };
 
 
-[[vk::push_constant]] ConstantBuffer<Uniforms> g_unis;
+ANKI_PUSH_CONSTANTS(Uniforms, g_unis)
 
 
 // FSR begin
 // FSR begin
 #	define A_GPU 1
 #	define A_GPU 1

+ 12 - 14
AnKi/Shaders/GBufferGeneric.ankiprog

@@ -89,7 +89,7 @@
 struct VertIn
 struct VertIn
 {
 {
 	U32 m_svVertexId : SV_VERTEXID;
 	U32 m_svVertexId : SV_VERTEXID;
-	[[vk::location(0)]] UVec4 m_instanceData : MISC0;
+	UVec4 m_instanceData : MISC0;
 };
 };
 
 
 struct VertOut
 struct VertOut
@@ -329,7 +329,7 @@ struct FirstPayload
 	UVec4 m_val;
 	UVec4 m_val;
 };
 };
 
 
-[[vk::push_constant]] ConstantBuffer<FirstPayload> g_firstPayload;
+ANKI_PUSH_CONSTANTS(FirstPayload, g_firstPayload)
 
 
 [numthreads(ANKI_TASK_SHADER_THREADGROUP_SIZE, 1, 1)] void main(U32 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX)
 [numthreads(ANKI_TASK_SHADER_THREADGROUP_SIZE, 1, 1)] void main(U32 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX)
 {
 {
@@ -549,9 +549,9 @@ main(U32 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX, in payload Ta
 #if ANKI_FRAGMENT_SHADER
 #if ANKI_FRAGMENT_SHADER
 
 
 #	if SW_MESHLETS
 #	if SW_MESHLETS
-#		define TEX_IDX(x) NonUniformResourceIndex(x)
+#		define BINDLESS(x) getBindlessTextureNonUniformIndex2DRVec4(x)
 #	else
 #	else
-#		define TEX_IDX(x) x
+#		define BINDLESS(x) getBindlessTexture2DRVec4(x)
 #	endif
 #	endif
 
 
 #	if !GBUFFER && !REALLY_ALPHA_TEST // Shadows without alpha
 #	if !GBUFFER && !REALLY_ALPHA_TEST // Shadows without alpha
@@ -577,7 +577,7 @@ void main(
 #		endif
 #		endif
 
 
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, uniformsOffset);
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, uniformsOffset);
-	const RVec4 diffColorA = g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_diffuseTex)].Sample(g_globalSampler, vertInput.m_uv);
+	const RVec4 diffColorA = BINDLESS(localUniforms.m_diffuseTex).Sample(g_globalSampler, vertInput.m_uv);
 	if(diffColorA.a * localUniforms.m_diffuseScale.a < 0.5f)
 	if(diffColorA.a * localUniforms.m_diffuseScale.a < 0.5f)
 	{
 	{
 		discard;
 		discard;
@@ -611,7 +611,7 @@ FragOut main(
 	ANKI_MAYBE_UNUSED(uv);
 	ANKI_MAYBE_UNUSED(uv);
 
 
 #		if DIFFUSE_TEX
 #		if DIFFUSE_TEX
-	const RVec4 diffColorA = g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_diffuseTex)].Sample(g_globalSampler, uv) * localUniforms.m_diffuseScale;
+	const RVec4 diffColorA = BINDLESS(localUniforms.m_diffuseTex).Sample(g_globalSampler, uv) * localUniforms.m_diffuseScale;
 	const RVec3 diffColor = diffColorA.rgb;
 	const RVec3 diffColor = diffColorA.rgb;
 #			if REALLY_ALPHA_TEST
 #			if REALLY_ALPHA_TEST
 	if(diffColorA.a < 0.5f)
 	if(diffColorA.a < 0.5f)
@@ -624,14 +624,13 @@ FragOut main(
 #		endif
 #		endif
 
 
 #		if SPECULAR_TEX
 #		if SPECULAR_TEX
-	const RVec3 specColor =
-		g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_specularTex)].Sample(g_globalSampler, uv).rgb * localUniforms.m_specularScale;
+	const RVec3 specColor = BINDLESS(localUniforms.m_specularTex).Sample(g_globalSampler, uv).rgb * localUniforms.m_specularScale;
 #		else
 #		else
 	const RVec3 specColor = localUniforms.m_specularScale;
 	const RVec3 specColor = localUniforms.m_specularScale;
 #		endif
 #		endif
 
 
 #		if ROUGHNESS_METALNESS_TEX
 #		if ROUGHNESS_METALNESS_TEX
-	const RVec3 comp = g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_roughnessMetalnessTex)].Sample(g_globalSampler, uv).rgb;
+	const RVec3 comp = BINDLESS(localUniforms.m_roughnessMetalnessTex).Sample(g_globalSampler, uv).rgb;
 	const RF32 roughness = comp.g * localUniforms.m_roughnessScale;
 	const RF32 roughness = comp.g * localUniforms.m_roughnessScale;
 	const RF32 metallic = comp.b * localUniforms.m_metalnessScale;
 	const RF32 metallic = comp.b * localUniforms.m_metalnessScale;
 #		else
 #		else
@@ -640,8 +639,7 @@ FragOut main(
 #		endif
 #		endif
 
 
 #		if NORMAL_TEX
 #		if NORMAL_TEX
-	const RVec3 nAtTangentspace =
-		normalize((g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_normalTex)].Sample(g_globalSampler, uv).rgb - 0.5) * 2.0);
+	const RVec3 nAtTangentspace = normalize((BINDLESS(localUniforms.m_normalTex).Sample(g_globalSampler, uv).rgb - 0.5) * 2.0);
 	const Vec3 viewDir = normalize(g_globalUniforms.m_cameraTransform.getTranslationPart() - vertInput.m_worldPos);
 	const Vec3 viewDir = normalize(g_globalUniforms.m_cameraTransform.getTranslationPart() - vertInput.m_worldPos);
 	const RVec3 normal = perturbNormal(nAtTangentspace, viewDir, uv, normalize(vertInput.m_normal));
 	const RVec3 normal = perturbNormal(nAtTangentspace, viewDir, uv, normalize(vertInput.m_normal));
 #		else
 #		else
@@ -649,8 +647,7 @@ FragOut main(
 #		endif
 #		endif
 
 
 #		if EMISSIVE_TEX
 #		if EMISSIVE_TEX
-	const RVec3 emission =
-		g_bindlessTextures2dF32[TEX_IDX(localUniforms.m_emissiveTex)].Sample(g_globalSampler, uv).rgb * localUniforms.m_emissionScale;
+	const RVec3 emission = BINDLESS(localUniforms.m_emissiveTex).Sample(g_globalSampler, uv).rgb * localUniforms.m_emissionScale;
 #		else
 #		else
 	const RVec3 emission = localUniforms.m_emissionScale;
 	const RVec3 emission = localUniforms.m_emissionScale;
 #		endif
 #		endif
@@ -743,7 +740,8 @@ FragOut main(
 	const Vec2 uv = vert0.m_uv * bary.x + vert1.m_uv * bary.y + vert2.m_uv * bary.z;
 	const Vec2 uv = vert0.m_uv * bary.x + vert1.m_uv * bary.y + vert2.m_uv * bary.z;
 
 
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, g_gpuSceneRenderable.m_uniformsOffset);
 	const AnKiLocalUniforms localUniforms = loadAnKiLocalUniforms(g_gpuScene, g_gpuSceneRenderable.m_uniformsOffset);
-	const RVec4 diffColorA = g_bindlessTextures2dF32[localUniforms.m_diffuseTex].SampleLevel(g_globalSampler, uv, 0.0) * localUniforms.m_diffuseScale;
+	const RVec4 diffColorA =
+		getBindlessTexture2DRVec4(localUniforms.m_diffuseTex).SampleLevel(g_globalSampler, uv, 0.0) * localUniforms.m_diffuseScale;
 
 
 	if(diffColorA.a < 1.0)
 	if(diffColorA.a < 1.0)
 	{
 	{

+ 9 - 11
AnKi/Shaders/GBufferPost.ankiprog

@@ -13,15 +13,13 @@
 #include <AnKi/Shaders/ClusteredShadingFunctions.hlsl>
 #include <AnKi/Shaders/ClusteredShadingFunctions.hlsl>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 
 
-[[vk::binding(0)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(1)]] Texture2D g_depthTex;
-[[vk::binding(2)]] SamplerState g_trilinearRepeatSampler;
+SamplerState g_nearestAnyClampSampler : register(s0);
+Texture2D g_depthTex : register(t0);
+SamplerState g_trilinearRepeatSampler : register(s1);
 
 
-[[vk::binding(3)]] ConstantBuffer<GlobalRendererUniforms> g_globalUniforms;
-[[vk::binding(4)]] StructuredBuffer<Decal> g_decals;
-[[vk::binding(5)]] StructuredBuffer<Cluster> g_clusters;
-
-ANKI_BINDLESS_SET(1)
+ConstantBuffer<GlobalRendererUniforms> g_globalUniforms : register(b0);
+StructuredBuffer<Decal> g_decals : register(t1);
+StructuredBuffer<Cluster> g_clusters : register(t2);
 
 
 struct FragOut
 struct FragOut
 {
 {
@@ -29,7 +27,7 @@ struct FragOut
 	RVec4 m_roughnessAndOther : SV_TARGET1;
 	RVec4 m_roughnessAndOther : SV_TARGET1;
 };
 };
 
 
-FragOut main([[vk::location(0)]] Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITION)
+FragOut main(Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITION)
 {
 {
 	// This code blends the diffuse and the specular+rougness of the decals with GBuffer render targets.
 	// This code blends the diffuse and the specular+rougness of the decals with GBuffer render targets.
 	// Normaly the blending is being done ('D' is the decal diffuse and 'f' is decal blend factor):
 	// Normaly the blending is being done ('D' is the decal diffuse and 'f' is decal blend factor):
@@ -81,7 +79,7 @@ FragOut main([[vk::location(0)]] Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITI
 		RVec4 diff;
 		RVec4 diff;
 		if(decal.m_diffuseTexture != kMaxU32)
 		if(decal.m_diffuseTexture != kMaxU32)
 		{
 		{
-			diff = g_bindlessTextures2dF32[decal.m_diffuseTexture].Sample(g_trilinearRepeatSampler, uv);
+			diff = getBindlessTexture2DVec4(decal.m_diffuseTexture).Sample(g_trilinearRepeatSampler, uv);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -92,7 +90,7 @@ FragOut main([[vk::location(0)]] Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITI
 		RF32 roughnessMetalnessFactor;
 		RF32 roughnessMetalnessFactor;
 		if(decal.m_roughnessMetalnessTexture != kMaxU32)
 		if(decal.m_roughnessMetalnessTexture != kMaxU32)
 		{
 		{
-			roughnessMetalness = g_bindlessTextures2dF32[decal.m_roughnessMetalnessTexture].Sample(g_trilinearRepeatSampler, uv).gb;
+			roughnessMetalness = getBindlessTexture2DVec4(decal.m_roughnessMetalnessTexture).Sample(g_trilinearRepeatSampler, uv).gb;
 			roughnessMetalnessFactor = diff.a;
 			roughnessMetalnessFactor = diff.a;
 		}
 		}
 		else
 		else

+ 6 - 6
AnKi/Shaders/GpuParticlesSimulation.ankiprog

@@ -10,12 +10,12 @@
 #include <AnKi/Shaders/Include/ParticleTypes.h>
 #include <AnKi/Shaders/Include/ParticleTypes.h>
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 
 
-[[vk::binding(0, 0)]] Texture2D g_depthTex;
-[[vk::binding(0, 1)]] RWStructuredBuffer<GpuParticle> g_particles;
-[[vk::binding(1, 1)]] ConstantBuffer<GpuParticleEmitterProperties> g_props;
-[[vk::binding(2, 1)]] StructuredBuffer<F32> g_randomFactors; // The 1st element is a uint with the count of the numbers
-[[vk::binding(3, 1)]] SamplerState g_nearestAnyClampSampler;
-[[vk::binding(4, 1)]] ConstantBuffer<GpuParticleSimulationState> g_state;
+Texture2D g_depthTex : register(t0);
+RWStructuredBuffer<GpuParticle> g_particles : register(u0);
+ConstantBuffer<GpuParticleEmitterProperties> g_props : register(b0);
+StructuredBuffer<F32> g_randomFactors : register(t1); // The 1st element is a uint with the count of the numbers
+SamplerState g_nearestAnyClampSampler : register(s0);
+ConstantBuffer<GpuParticleSimulationState> g_state : register(b1);
 
 
 F32 smallerDelta(F32 left, F32 mid, F32 right)
 F32 smallerDelta(F32 left, F32 mid, F32 right)
 {
 {

+ 3 - 3
AnKi/Shaders/GpuSceneMicroPatching.ankiprog

@@ -7,9 +7,9 @@
 
 
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 
 
-[[vk::binding(0)]] StructuredBuffer<UVec2> g_patchHeaders;
-[[vk::binding(1)]] StructuredBuffer<U32> g_srcBuffer;
-[[vk::binding(2)]] RWStructuredBuffer<U32> g_dstBuffer;
+StructuredBuffer<UVec2> g_patchHeaders : register(t0);
+StructuredBuffer<U32> g_srcBuffer : register(t1);
+RWStructuredBuffer<U32> g_dstBuffer : register(u0);
 
 
 [numthreads(64, 1, 1)] void main(UVec3 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX)
 [numthreads(64, 1, 1)] void main(UVec3 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX)
 {
 {

+ 18 - 18
AnKi/Shaders/GpuVisibility.ankiprog

@@ -31,48 +31,48 @@ struct DrawIndirectArgsWithPadding
 };
 };
 
 
 // Buffers that point to the GPU scene
 // Buffers that point to the GPU scene
-[[vk::binding(0)]] StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes;
-[[vk::binding(1)]] StructuredBuffer<GpuSceneRenderable> g_renderables;
-[[vk::binding(2)]] StructuredBuffer<GpuSceneMeshLod> g_meshLods;
-[[vk::binding(3)]] StructuredBuffer<Mat3x4> g_transforms;
-[[vk::binding(4)]] ByteAddressBuffer g_gpuScene;
+StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes : register(t0);
+StructuredBuffer<GpuSceneRenderable> g_renderables : register(t1);
+StructuredBuffer<GpuSceneMeshLod> g_meshLods : register(t2);
+StructuredBuffer<Mat3x4> g_transforms : register(t3);
+ByteAddressBuffer g_gpuScene : register(t4);
 
 
 #if GATHER_MDI
 #if GATHER_MDI
 // These 3 have the same size
 // These 3 have the same size
-[[vk::binding(5)]] RWStructuredBuffer<UVec4> g_instanceRateRenderables;
-[[vk::binding(6)]] RWStructuredBuffer<DrawIndexedIndirectArgs> g_drawIndexedIndirectArgs;
-[[vk::binding(6)]] RWStructuredBuffer<DrawIndirectArgsWithPadding> g_drawIndirectArgs;
+RWStructuredBuffer<UVec4> g_instanceRateRenderables : register(u0);
+RWStructuredBuffer<DrawIndexedIndirectArgs> g_drawIndexedIndirectArgs : register(u1);
+RWStructuredBuffer<DrawIndirectArgsWithPadding> g_drawIndirectArgs : register(u2);
 
 
 // The MDI counts. One for each render state bucket
 // The MDI counts. One for each render state bucket
-[[vk::binding(7)]] RWStructuredBuffer<U32> g_mdiDrawCounts;
+RWStructuredBuffer<U32> g_mdiDrawCounts : register(u3);
 #endif
 #endif
 
 
 #if GATHER_MESHLET_GROUPS
 #if GATHER_MESHLET_GROUPS
 // For mesh shading
 // For mesh shading
-[[vk::binding(8)]] RWStructuredBuffer<DispatchIndirectArgs> g_taskShaderIndirectArgs;
-[[vk::binding(9)]] RWStructuredBuffer<GpuSceneMeshletGroupInstance> g_meshletGroupInstances;
+RWStructuredBuffer<DispatchIndirectArgs> g_taskShaderIndirectArgs : register(u4);
+RWStructuredBuffer<GpuSceneMeshletGroupInstance> g_meshletGroupInstances : register(u5);
 #endif
 #endif
 
 
 // One for each render state bucket. It's either the index of the next indirect args or the index to the next task payload
 // One for each render state bucket. It's either the index of the next indirect args or the index to the next task payload
-[[vk::binding(10)]] StructuredBuffer<UVec2> g_instanceRanges;
+StructuredBuffer<UVec2> g_instanceRanges : register(t5);
 
 
 #if DISTANCE_TEST == 0
 #if DISTANCE_TEST == 0
-[[vk::binding(11)]] ConstantBuffer<FrustumGpuVisibilityUniforms> g_unis;
+ConstantBuffer<FrustumGpuVisibilityUniforms> g_unis : register(b0);
 #else
 #else
-[[vk::push_constant]] ConstantBuffer<DistanceGpuVisibilityUniforms> g_unis;
+ANKI_PUSH_CONSTANTS(DistanceGpuVisibilityUniforms, g_unis)
 #endif
 #endif
 
 
 #if HZB_TEST
 #if HZB_TEST
-[[vk::binding(12)]] Texture2D<Vec4> g_hzbTex;
-[[vk::binding(13)]] SamplerState g_nearestAnyClampSampler;
+Texture2D<Vec4> g_hzbTex : register(t6);
+SamplerState g_nearestAnyClampSampler : register(s0);
 #endif
 #endif
 
 
 #if GATHER_AABBS
 #if GATHER_AABBS
-[[vk::binding(14)]] RWStructuredBuffer<U32> g_visibleAabbIndices; ///< Indices of the visible AABBs. The 1st element is the count.
+RWStructuredBuffer<U32> g_visibleAabbIndices : register(u6); ///< Indices of the visible AABBs. The 1st element is the count.
 #endif
 #endif
 
 
 #if HASH_VISIBLES
 #if HASH_VISIBLES
-[[vk::binding(15)]] RWStructuredBuffer<GpuVisibilityHash> g_hash;
+RWStructuredBuffer<GpuVisibilityHash> g_hash : register(u7);
 #endif
 #endif
 
 
 [numthreads(64, 1, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
 [numthreads(64, 1, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)

+ 9 - 9
AnKi/Shaders/GpuVisibilityAccelerationStructures.ankiprog

@@ -11,19 +11,19 @@
 #include <AnKi/Shaders/VisibilityAndCollisionFunctions.hlsl>
 #include <AnKi/Shaders/VisibilityAndCollisionFunctions.hlsl>
 
 
 // Buffers that point to the GPU scene
 // Buffers that point to the GPU scene
-[[vk::binding(0)]] StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes;
-[[vk::binding(1)]] StructuredBuffer<GpuSceneRenderable> g_renderables;
-[[vk::binding(2)]] StructuredBuffer<GpuSceneMeshLod> g_meshLods;
-[[vk::binding(3)]] StructuredBuffer<Mat3x4> g_transforms;
+StructuredBuffer<GpuSceneRenderableBoundingVolume> g_renderableBoundingVolumes : register(t0);
+StructuredBuffer<GpuSceneRenderable> g_renderables : register(t1);
+StructuredBuffer<GpuSceneMeshLod> g_meshLods : register(t2);
+StructuredBuffer<Mat3x4> g_transforms : register(t3);
 
 
-[[vk::binding(4)]] RWStructuredBuffer<AccelerationStructureInstance> g_visibleInstances;
-[[vk::binding(5)]] RWStructuredBuffer<U32> g_visibleRenderableIndices; // 1st element is the count
+RWStructuredBuffer<AccelerationStructureInstance> g_visibleInstances : register(u0);
+RWStructuredBuffer<U32> g_visibleRenderableIndices : register(u1); // 1st element is the count
 
 
-[[vk::binding(6)]] globallycoherent RWStructuredBuffer<U32> g_counterBuffer; // 2 counters per dispatch
+globallycoherent RWStructuredBuffer<U32> g_counterBuffer : register(u2); // 2 counters per dispatch
 
 
-[[vk::binding(7)]] RWStructuredBuffer<DispatchIndirectArgs> g_nextDispatchIndirectArgs;
+RWStructuredBuffer<DispatchIndirectArgs> g_nextDispatchIndirectArgs : register(u3);
 
 
-[[vk::push_constant]] ConstantBuffer<GpuVisibilityAccelerationStructuresUniforms> g_unis;
+ANKI_PUSH_CONSTANTS(GpuVisibilityAccelerationStructuresUniforms, g_unis)
 
 
 #define NUMTHREADS 64
 #define NUMTHREADS 64
 
 

+ 2 - 2
AnKi/Shaders/GpuVisibilityAccelerationStructuresZeroRemainingInstances.ankiprog

@@ -8,8 +8,8 @@
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Common.hlsl>
 #include <AnKi/Shaders/Include/GpuSceneTypes.h>
 #include <AnKi/Shaders/Include/GpuSceneTypes.h>
 
 
-[[vk::binding(0)]] StructuredBuffer<U32> g_visibleRenderableIndices; // 1st element is the count
-[[vk::binding(1)]] RWStructuredBuffer<AccelerationStructureInstance> g_instances;
+StructuredBuffer<U32> g_visibleRenderableIndices : register(t0); // 1st element is the count
+RWStructuredBuffer<AccelerationStructureInstance> g_instances : register(u0);
 
 
 #define NUMTHREADS 64
 #define NUMTHREADS 64
 
 

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