Browse Source

Add acceleration structure support in rendergraph

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
f8a7de6e23

+ 7 - 2
src/anki/gr/Enums.h

@@ -661,10 +661,15 @@ enum class AccelerationStructureUsageBit : U8
 	NONE = 0,
 	BUILD = 1 << 0,
 	ATTACH = 1 << 1, ///< Attached to a TLAS. Only for BLAS.
-	VERTEX_READ = 1 << 2,
+	GEOMETRY_READ = 1 << 2,
 	FRAGMENT_READ = 1 << 3,
 	COMPUTE_READ = 1 << 4,
-	RAY_GEN_READ = 1 << 5
+	RAY_GEN_READ = 1 << 5,
+
+	// Derived
+	ALL_GRAPHICS = GEOMETRY_READ | FRAGMENT_READ,
+	ALL_READ = ATTACH | GEOMETRY_READ | FRAGMENT_READ | COMPUTE_READ | RAY_GEN_READ,
+	ALL_WRITE = BUILD
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(AccelerationStructureUsageBit, inline)
 /// @}

+ 300 - 130
src/anki/gr/RenderGraph.cpp

@@ -43,42 +43,59 @@ public:
 	BufferPtr m_buffer; ///< Hold a reference.
 };
 
-/// Pipeline barrier of texture or buffer.
-class RenderGraph::Barrier
+class RenderGraph::AS
 {
 public:
-	struct TextureInfo
-	{
-		U32 m_idx;
-		TextureUsageBit m_usageBefore;
-		TextureUsageBit m_usageAfter;
-		TextureSurfaceInfo m_surface;
-	};
-
-	struct BufferInfo
-	{
-		U32 m_idx;
-		BufferUsageBit m_usageBefore;
-		BufferUsageBit m_usageAfter;
-	};
+	AccelerationStructureUsageBit m_usage;
+	AccelerationStructurePtr m_as; ///< Hold a reference.
+};
 
-	union
+/// Pipeline barrier.
+class RenderGraph::TextureBarrier
+{
+public:
+	U32 m_idx;
+	TextureUsageBit m_usageBefore;
+	TextureUsageBit m_usageAfter;
+	TextureSurfaceInfo m_surface;
+
+	TextureBarrier(U32 rtIdx, TextureUsageBit usageBefore, TextureUsageBit usageAfter, const TextureSurfaceInfo& surf)
+		: m_idx(rtIdx)
+		, m_usageBefore(usageBefore)
+		, m_usageAfter(usageAfter)
+		, m_surface(surf)
 	{
-		TextureInfo m_texture;
-		BufferInfo m_buffer;
-	};
-
-	Bool m_isTexture;
+	}
+};
 
-	Barrier(U32 rtIdx, TextureUsageBit usageBefore, TextureUsageBit usageAfter, const TextureSurfaceInfo& surf)
-		: m_texture({rtIdx, usageBefore, usageAfter, surf})
-		, m_isTexture(true)
+/// Pipeline barrier.
+class RenderGraph::BufferBarrier
+{
+public:
+	U32 m_idx;
+	BufferUsageBit m_usageBefore;
+	BufferUsageBit m_usageAfter;
+
+	BufferBarrier(U32 buffIdx, BufferUsageBit usageBefore, BufferUsageBit usageAfter)
+		: m_idx(buffIdx)
+		, m_usageBefore(usageBefore)
+		, m_usageAfter(usageAfter)
 	{
 	}
+};
 
-	Barrier(U32 buffIdx, BufferUsageBit usageBefore, BufferUsageBit usageAfter)
-		: m_buffer({buffIdx, usageBefore, usageAfter})
-		, m_isTexture(false)
+/// Pipeline barrier.
+class RenderGraph::ASBarrier
+{
+public:
+	U32 m_idx;
+	AccelerationStructureUsageBit m_usageBefore;
+	AccelerationStructureUsageBit m_usageAfter;
+
+	ASBarrier(U32 asIdx, AccelerationStructureUsageBit usageBefore, AccelerationStructureUsageBit usageAfter)
+		: m_idx(asIdx)
+		, m_usageBefore(usageBefore)
+		, m_usageAfter(usageAfter)
 	{
 	}
 };
@@ -88,19 +105,9 @@ class RenderGraph::Pass
 {
 public:
 	// WARNING!!!!!: Whatever you put here needs manual destruction in RenderGraph::reset()
-
-	/// WARNING: Should be the same as RenderPassDependency::TextureInfo
-	class ConsumedTextureInfo
-	{
-	public:
-		RenderTargetHandle m_handle;
-		TextureUsageBit m_usage;
-		TextureSubresourceInfo m_subresource;
-	};
-
 	DynamicArray<U32> m_dependsOn;
 
-	DynamicArray<ConsumedTextureInfo> m_consumedTextures;
+	DynamicArray<RenderPassDependency::TextureInfo> m_consumedTextures;
 
 	RenderPassWorkCallback m_callback;
 	void* m_userData;
@@ -132,7 +139,9 @@ class RenderGraph::Batch
 {
 public:
 	DynamicArray<U32> m_passIndices;
-	DynamicArray<Barrier> m_barriersBefore;
+	DynamicArray<TextureBarrier> m_textureBarriersBefore;
+	DynamicArray<BufferBarrier> m_bufferBarriersBefore;
+	DynamicArray<ASBarrier> m_asBarriersBefore;
 	CommandBuffer* m_cmdb; ///< Someone else holds the ref already so have a ptr here.
 };
 
@@ -142,10 +151,11 @@ class RenderGraph::BakeContext
 public:
 	StackAllocator<U8> m_alloc;
 	DynamicArray<Pass> m_passes;
-	BitSet<MAX_RENDER_GRAPH_PASSES, U64> m_passIsInBatch = {false};
+	BitSet<MAX_RENDER_GRAPH_PASSES, U64> m_passIsInBatch{false};
 	DynamicArray<Batch> m_batches;
 	DynamicArray<RT> m_rts;
 	DynamicArray<Buffer> m_buffers;
+	DynamicArray<AS> m_as;
 
 	DynamicArray<CommandBufferPtr> m_graphicsCmdbs;
 
@@ -315,6 +325,11 @@ void RenderGraph::reset()
 		buff.m_buffer.reset(nullptr);
 	}
 
+	for(AS& as : m_ctx->m_as)
+	{
+		as.m_as.reset(nullptr);
+	}
+
 	for(auto& it : m_renderTargetCache)
 	{
 		it.m_texturesInUse = 0;
@@ -464,8 +479,6 @@ FramebufferPtr RenderGraph::getOrCreateFramebuffer(const FramebufferDescription&
 
 		// Create
 		fb = getManager().newFramebuffer(fbInit);
-
-		// TODO: Check why the hell it compiles if you remove the parameter "hash"
 		m_fbCache.emplace(getAllocator(), hash, fb);
 	}
 
@@ -490,11 +503,11 @@ Bool RenderGraph::passADependsOnB(const RenderPassDescriptionBase& a, const Rend
 	// Render targets
 	{
 		// Compute the 3 types of dependencies
-		BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aReadBWrite = a.m_readRtMask & b.m_writeRtMask;
-		BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aWriteBRead = a.m_writeRtMask & b.m_readRtMask;
-		BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aWriteBWrite = a.m_writeRtMask & b.m_writeRtMask;
+		const BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aReadBWrite = a.m_readRtMask & b.m_writeRtMask;
+		const BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aWriteBRead = a.m_writeRtMask & b.m_readRtMask;
+		const BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> aWriteBWrite = a.m_writeRtMask & b.m_writeRtMask;
 
-		BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
+		const BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
 
 		if(fullDep.getAny())
 		{
@@ -530,13 +543,13 @@ Bool RenderGraph::passADependsOnB(const RenderPassDescriptionBase& a, const Rend
 	}
 
 	// Buffers
-	if(a.m_hasBufferDeps)
+	if(a.m_readBuffMask || a.m_writeBuffMask)
 	{
-		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aReadBWrite = a.m_readBuffMask & b.m_writeBuffMask;
-		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aWriteBRead = a.m_writeBuffMask & b.m_readBuffMask;
-		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aWriteBWrite = a.m_writeBuffMask & b.m_writeBuffMask;
+		const BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aReadBWrite = a.m_readBuffMask & b.m_writeBuffMask;
+		const BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aWriteBRead = a.m_writeBuffMask & b.m_readBuffMask;
+		const BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> aWriteBWrite = a.m_writeBuffMask & b.m_writeBuffMask;
 
-		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
+		const BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
 
 		if(fullDep.getAny())
 		{
@@ -569,6 +582,43 @@ Bool RenderGraph::passADependsOnB(const RenderPassDescriptionBase& a, const Rend
 		}
 	}
 
+	// AS
+	if(a.m_readAsMask || a.m_writeAsMask)
+	{
+		const BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> aReadBWrite = a.m_readAsMask & b.m_writeAsMask;
+		const BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> aWriteBRead = a.m_writeAsMask & b.m_readAsMask;
+		const BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> aWriteBWrite = a.m_writeAsMask & b.m_writeAsMask;
+
+		const BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
+
+		if(fullDep)
+		{
+			for(const RenderPassDependency& aDep : a.m_asDeps)
+			{
+				if(!fullDep.get(aDep.m_as.m_handle.m_idx))
+				{
+					continue;
+				}
+
+				for(const RenderPassDependency& bDep : b.m_asDeps)
+				{
+					if(aDep.m_as.m_handle != bDep.m_as.m_handle)
+					{
+						continue;
+					}
+
+					if(!((aDep.m_as.m_usage | bDep.m_as.m_usage) & AccelerationStructureUsageBit::ALL_WRITE))
+					{
+						// Don't care about read to read deps
+						continue;
+					}
+
+					return true;
+				}
+			}
+		}
+	}
+
 	return false;
 }
 
@@ -676,6 +726,15 @@ RenderGraph::BakeContext* RenderGraph::newContext(const RenderGraphDescription&
 		ctx->m_buffers[buffIdx].m_buffer = descr.m_buffers[buffIdx].m_importedBuff;
 	}
 
+	// AS
+	ctx->m_as.create(alloc, descr.m_as.getSize());
+	for(U32 i = 0; i < descr.m_as.getSize(); ++i)
+	{
+		ctx->m_as[i].m_usage = descr.m_as[i].m_usage;
+		ctx->m_as[i].m_as = descr.m_as[i].m_importedAs;
+		ANKI_ASSERT(ctx->m_as[i].m_as.isCreated());
+	}
+
 	ctx->m_gatherStatistics = descr.m_gatherStatistics;
 
 	return ctx;
@@ -701,9 +760,9 @@ void RenderGraph::initRenderPassesAndSetDeps(const RenderGraphDescription& descr
 		for(U32 depIdx = 0; depIdx < inPass.m_rtDeps.getSize(); ++depIdx)
 		{
 			const RenderPassDependency& inDep = inPass.m_rtDeps[depIdx];
-			ANKI_ASSERT(inDep.m_isTexture);
+			ANKI_ASSERT(inDep.m_type == RenderPassDependency::Type::TEXTURE);
 
-			Pass::ConsumedTextureInfo& inf = outPass.m_consumedTextures[depIdx];
+			RenderPassDependency::TextureInfo& inf = outPass.m_consumedTextures[depIdx];
 
 			ANKI_ASSERT(sizeof(inf) == sizeof(inDep.m_texture));
 			memcpy(&inf, &inDep.m_texture, sizeof(inf));
@@ -904,7 +963,7 @@ void RenderGraph::iterateSurfsOrVolumes(const TexturePtr& tex, const TextureSubr
 
 void RenderGraph::setTextureBarrier(Batch& batch, const RenderPassDependency& dep)
 {
-	ANKI_ASSERT(dep.m_isTexture);
+	ANKI_ASSERT(dep.m_type == RenderPassDependency::Type::TEXTURE);
 
 	BakeContext& ctx = *m_ctx;
 	const U32 batchIdx = U32(&batch - &ctx.m_batches[0]);
@@ -925,11 +984,11 @@ void RenderGraph::setTextureBarrier(Batch& batch, const RenderPassDependency& de
 					crntUsage |= depUsage;
 
 					Bool found = false;
-					for(Barrier& b : batch.m_barriersBefore)
+					for(TextureBarrier& b : batch.m_textureBarriersBefore)
 					{
-						if(b.m_isTexture && b.m_texture.m_idx == rtIdx && b.m_texture.m_surface == surf)
+						if(b.m_idx == rtIdx && b.m_surface == surf)
 						{
-							b.m_texture.m_usageAfter |= depUsage;
+							b.m_usageAfter |= depUsage;
 							found = true;
 							break;
 						}
@@ -942,7 +1001,7 @@ void RenderGraph::setTextureBarrier(Batch& batch, const RenderPassDependency& de
 				{
 					// Create a new barrier for this surface
 
-					batch.m_barriersBefore.emplaceBack(ctx.m_alloc, rtIdx, crntUsage, depUsage, surf);
+					batch.m_textureBarriersBefore.emplaceBack(ctx.m_alloc, rtIdx, crntUsage, depUsage, surf);
 
 					crntUsage = depUsage;
 					rt.m_lastBatchThatTransitionedIt[surfOrVolIdx] = U16(batchIdx);
@@ -961,80 +1020,127 @@ void RenderGraph::setBatchBarriers(const RenderGraphDescription& descr)
 	// For all batches
 	for(Batch& batch : ctx.m_batches)
 	{
-		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> buffHasBarrierMask = {false};
+		BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> buffHasBarrierMask(false);
+		BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> asHasBarrierMask(false);
 
 		// For all passes of that batch
 		for(U32 passIdx : batch.m_passIndices)
 		{
 			const RenderPassDescriptionBase& pass = *descr.m_passes[passIdx];
 
-			// For all deps
+			// Do textures
 			for(const RenderPassDependency& dep : pass.m_rtDeps)
 			{
 				setTextureBarrier(batch, dep);
 			}
 
+			// Do buffers
 			for(const RenderPassDependency& dep : pass.m_buffDeps)
 			{
 				const U32 buffIdx = dep.m_buffer.m_handle.m_idx;
 				const BufferUsageBit depUsage = dep.m_buffer.m_usage;
+				BufferUsageBit& crntUsage = ctx.m_buffers[buffIdx].m_usage;
 
-				if(depUsage != ctx.m_buffers[buffIdx].m_usage)
+				if(depUsage == crntUsage)
 				{
-					const Bool buffHasBarrier = buffHasBarrierMask.get(buffIdx);
+					continue;
+				}
 
-					if(!buffHasBarrier)
-					{
-						// Buff hasn't had a barrier in this batch, add a new barrier
+				const Bool buffHasBarrier = buffHasBarrierMask.get(buffIdx);
 
-						batch.m_barriersBefore.emplaceBack(alloc, buffIdx, ctx.m_buffers[buffIdx].m_usage, depUsage);
+				if(!buffHasBarrier)
+				{
+					// Buff hasn't had a barrier in this batch, add a new barrier
 
-						ctx.m_buffers[buffIdx].m_usage = depUsage;
-						buffHasBarrierMask.set(buffIdx);
-					}
-					else
-					{
-						// Buff already in a barrier, merge the 2 barriers
+					batch.m_bufferBarriersBefore.emplaceBack(alloc, buffIdx, crntUsage, depUsage);
 
-						Barrier* barrierToMergeTo = nullptr;
-						for(Barrier& b : batch.m_barriersBefore)
+					crntUsage = depUsage;
+					buffHasBarrierMask.set(buffIdx);
+				}
+				else
+				{
+					// Buff already in a barrier, merge the 2 barriers
+
+					BufferBarrier* barrierToMergeTo = nullptr;
+					for(BufferBarrier& b : batch.m_bufferBarriersBefore)
+					{
+						if(b.m_idx == buffIdx)
 						{
-							if(!b.m_isTexture && b.m_buffer.m_idx == buffIdx)
-							{
-								barrierToMergeTo = &b;
-								break;
-							}
+							barrierToMergeTo = &b;
+							break;
 						}
+					}
+
+					ANKI_ASSERT(barrierToMergeTo);
+					ANKI_ASSERT(!!barrierToMergeTo->m_usageAfter);
+					barrierToMergeTo->m_usageAfter |= depUsage;
+					crntUsage = barrierToMergeTo->m_usageAfter;
+				}
+			}
 
-						ANKI_ASSERT(barrierToMergeTo);
-						ANKI_ASSERT(!!barrierToMergeTo->m_buffer.m_usageAfter);
-						barrierToMergeTo->m_buffer.m_usageAfter |= depUsage;
-						ctx.m_buffers[buffIdx].m_usage = barrierToMergeTo->m_buffer.m_usageAfter;
+			// Do AS
+			for(const RenderPassDependency& dep : pass.m_asDeps)
+			{
+				const U32 asIdx = dep.m_as.m_handle.m_idx;
+				const AccelerationStructureUsageBit depUsage = dep.m_as.m_usage;
+				AccelerationStructureUsageBit& crntUsage = ctx.m_as[asIdx].m_usage;
+
+				if(depUsage == crntUsage)
+				{
+					continue;
+				}
+
+				const Bool asHasBarrierInThisBatch = asHasBarrierMask.get(asIdx);
+				if(!asHasBarrierInThisBatch)
+				{
+					// AS doesn't have a barrier in this batch, create a new one
+
+					batch.m_asBarriersBefore.emplaceBack(alloc, asIdx, crntUsage, depUsage);
+					crntUsage = depUsage;
+					asHasBarrierMask.set(asIdx);
+				}
+				else
+				{
+					// AS already has a barrier, merge the 2 barriers
+
+					ASBarrier* barrierToMergeTo = nullptr;
+					for(ASBarrier& other : batch.m_asBarriersBefore)
+					{
+						if(other.m_idx == asIdx)
+						{
+							barrierToMergeTo = &other;
+							break;
+						}
 					}
+
+					ANKI_ASSERT(barrierToMergeTo);
+					ANKI_ASSERT(!!barrierToMergeTo->m_usageAfter);
+					barrierToMergeTo->m_usageAfter |= depUsage;
+					crntUsage = barrierToMergeTo->m_usageAfter;
 				}
 			}
 		} // For all passes
 
 #if ANKI_DBG_RENDER_GRAPH
 		// Sort the barriers to ease the dumped graph
-		std::sort(batch.m_barriersBefore.getBegin(), batch.m_barriersBefore.getEnd(),
-				  [&](const Barrier& a, const Barrier& b) {
-					  const U aidx = (a.m_isTexture) ? a.m_texture.m_idx : a.m_buffer.m_idx;
-					  const U bidx = (b.m_isTexture) ? b.m_texture.m_idx : b.m_buffer.m_idx;
+		std::sort(batch.m_textureBarriersBefore.getBegin(), batch.m_textureBarriersBefore.getEnd(),
+				  [&](const TextureBarrier& a, const TextureBarrier& b) {
+					  const U aidx = a.m_idx;
+					  const U bidx = b.m_idx;
 
-					  if(aidx == bidx && a.m_isTexture && b.m_isTexture)
+					  if(aidx == bidx)
 					  {
-						  if(a.m_texture.m_surface.m_level != b.m_texture.m_surface.m_level)
+						  if(a.m_surface.m_level != b.m_surface.m_level)
 						  {
-							  return a.m_texture.m_surface.m_level < b.m_texture.m_surface.m_level;
+							  return a.m_surface.m_level < b.m_surface.m_level;
 						  }
-						  else if(a.m_texture.m_surface.m_face != b.m_texture.m_surface.m_face)
+						  else if(a.m_surface.m_face != b.m_surface.m_face)
 						  {
-							  return a.m_texture.m_surface.m_face < b.m_texture.m_surface.m_face;
+							  return a.m_surface.m_face < b.m_surface.m_face;
 						  }
-						  else if(a.m_texture.m_surface.m_layer != b.m_texture.m_surface.m_layer)
+						  else if(a.m_surface.m_layer != b.m_surface.m_layer)
 						  {
-							  return a.m_texture.m_surface.m_layer < b.m_texture.m_surface.m_layer;
+							  return a.m_surface.m_layer < b.m_surface.m_layer;
 						  }
 						  else
 						  {
@@ -1046,6 +1152,12 @@ void RenderGraph::setBatchBarriers(const RenderGraphDescription& descr)
 						  return aidx < bidx;
 					  }
 				  });
+
+		std::sort(batch.m_bufferBarriersBefore.getBegin(), batch.m_bufferBarriersBefore.getEnd(),
+				  [&](const BufferBarrier& a, const BufferBarrier& b) { return a.m_idx < b.m_idx; });
+
+		std::sort(batch.m_asBarriersBefore.getBegin(), batch.m_asBarriersBefore.getEnd(),
+				  [&](const ASBarrier& a, const ASBarrier& b) { return a.m_idx < b.m_idx; });
 #endif
 	} // For all batches
 }
@@ -1084,12 +1196,18 @@ TexturePtr RenderGraph::getTexture(RenderTargetHandle handle) const
 	return m_ctx->m_rts[handle.m_idx].m_texture;
 }
 
-BufferPtr RenderGraph::getBuffer(RenderPassBufferHandle handle) const
+BufferPtr RenderGraph::getBuffer(BufferHandle handle) const
 {
 	ANKI_ASSERT(m_ctx->m_buffers[handle.m_idx].m_buffer.isCreated());
 	return m_ctx->m_buffers[handle.m_idx].m_buffer;
 }
 
+AccelerationStructurePtr RenderGraph::getAs(AccelerationStructureHandle handle) const
+{
+	ANKI_ASSERT(m_ctx->m_as[handle.m_idx].m_as.isCreated());
+	return m_ctx->m_as[handle.m_idx].m_as;
+}
+
 void RenderGraph::runSecondLevel(U32 threadIdx)
 {
 	ANKI_TRACE_SCOPED_EVENT(GR_RENDER_GRAPH_2ND_LEVEL);
@@ -1141,19 +1259,20 @@ void RenderGraph::run() const
 		CommandBufferPtr& cmdb = ctx.m_commandBuffer;
 
 		// Set the barriers
-		for(const Barrier& barrier : batch.m_barriersBefore)
+		for(const TextureBarrier& barrier : batch.m_textureBarriersBefore)
 		{
-			if(barrier.m_isTexture)
-			{
-				cmdb->setTextureSurfaceBarrier(m_ctx->m_rts[barrier.m_texture.m_idx].m_texture,
-											   barrier.m_texture.m_usageBefore, barrier.m_texture.m_usageAfter,
-											   barrier.m_texture.m_surface);
-			}
-			else
-			{
-				cmdb->setBufferBarrier(m_ctx->m_buffers[barrier.m_buffer.m_idx].m_buffer,
-									   barrier.m_buffer.m_usageBefore, barrier.m_buffer.m_usageAfter, 0, MAX_PTR_SIZE);
-			}
+			cmdb->setTextureSurfaceBarrier(m_ctx->m_rts[barrier.m_idx].m_texture, barrier.m_usageBefore,
+										   barrier.m_usageAfter, barrier.m_surface);
+		}
+		for(const BufferBarrier& barrier : batch.m_bufferBarriersBefore)
+		{
+			cmdb->setBufferBarrier(m_ctx->m_buffers[barrier.m_idx].m_buffer, barrier.m_usageBefore,
+								   barrier.m_usageAfter, 0, MAX_PTR_SIZE);
+		}
+		for(const ASBarrier& barrier : batch.m_asBarriersBefore)
+		{
+			cmdb->setAccelerationStructureBarrier(m_ctx->m_as[barrier.m_idx].m_as, barrier.m_usageBefore,
+												  barrier.m_usageAfter);
 		}
 
 		// Call the passes
@@ -1223,7 +1342,7 @@ void RenderGraph::getCrntUsage(RenderTargetHandle handle, U32 batchIdx, const Te
 
 	for(U32 passIdx : batch.m_passIndices)
 	{
-		for(const Pass::ConsumedTextureInfo& consumer : m_ctx->m_passes[passIdx].m_consumedTextures)
+		for(const RenderPassDependency::TextureInfo& consumer : m_ctx->m_passes[passIdx].m_consumedTextures)
 		{
 			if(consumer.m_handle == handle && overlappingTextureSubresource(subresource, consumer.m_subresource))
 			{
@@ -1388,6 +1507,31 @@ StringAuto RenderGraph::bufferUsageToStr(StackAllocator<U8>& alloc, BufferUsageB
 	return str;
 }
 
+StringAuto RenderGraph::asUsageToStr(StackAllocator<U8>& alloc, AccelerationStructureUsageBit usage)
+{
+	StringListAuto slist(alloc);
+
+#	define ANKI_AS_USAGE(u) \
+		if(!!(usage & AccelerationStructureUsageBit::u)) \
+		{ \
+			slist.pushBackSprintf("%s", #u); \
+		}
+
+	ANKI_AS_USAGE(BUILD);
+	ANKI_AS_USAGE(ATTACH);
+	ANKI_AS_USAGE(GEOMETRY_READ);
+	ANKI_AS_USAGE(FRAGMENT_READ);
+	ANKI_AS_USAGE(COMPUTE_READ);
+	ANKI_AS_USAGE(RAY_GEN_READ);
+
+#	undef ANKI_AS_USAGE
+
+	ANKI_ASSERT(!slist.isEmpty());
+	StringAuto str(alloc);
+	slist.join(" | ", str);
+	return str;
+}
+
 Error RenderGraph::dumpDependencyDotFile(const RenderGraphDescription& descr, const BakeContext& ctx,
 										 CString path) const
 {
@@ -1453,31 +1597,57 @@ Error RenderGraph::dumpDependencyDotFile(const RenderGraphDescription& descr, co
 		StringAuto batchName(ctx.m_alloc);
 		batchName.sprintf("batch%u", batchIdx);
 
-		for(U32 barrierIdx = 0; barrierIdx < batch.m_barriersBefore.getSize(); ++barrierIdx)
+		for(U32 barrierIdx = 0; barrierIdx < batch.m_textureBarriersBefore.getSize(); ++barrierIdx)
 		{
-			const Barrier& barrier = batch.m_barriersBefore[barrierIdx];
+			const TextureBarrier& barrier = batch.m_textureBarriersBefore[barrierIdx];
+
+			StringAuto barrierLabel(ctx.m_alloc);
+			barrierLabel.sprintf("<b>%s</b> (mip,dp,f,l)=(%u,%u,%u,%u)<br/>%s <b>to</b> %s",
+								 &descr.m_renderTargets[barrier.m_idx].m_name[0], barrier.m_surface.m_level,
+								 barrier.m_surface.m_depth, barrier.m_surface.m_face, barrier.m_surface.m_layer,
+								 textureUsageToStr(alloc, barrier.m_usageBefore).cstr(),
+								 textureUsageToStr(alloc, barrier.m_usageAfter).cstr());
+
 			StringAuto barrierName(ctx.m_alloc);
+			barrierName.sprintf("%s tex barrier%u", batchName.cstr(), barrierIdx);
+
+			slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold,shape=box,label=< %s >];\n", barrierName.cstr(),
+								  COLORS[batchIdx % COLORS.getSize()], barrierLabel.cstr());
+			slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", prevBubble.cstr(), barrierName.cstr());
+
+			prevBubble = barrierName;
+		}
+
+		for(U32 barrierIdx = 0; barrierIdx < batch.m_bufferBarriersBefore.getSize(); ++barrierIdx)
+		{
+			const BufferBarrier& barrier = batch.m_bufferBarriersBefore[barrierIdx];
+
 			StringAuto barrierLabel(ctx.m_alloc);
-			if(barrier.m_isTexture)
-			{
-				barrierLabel.sprintf("<b>%s</b> (mip,dp,f,l)=(%u,%u,%u,%u)<br/>%s <b>to</b> %s",
-									 &descr.m_renderTargets[barrier.m_texture.m_idx].m_name[0],
-									 barrier.m_texture.m_surface.m_level, barrier.m_texture.m_surface.m_depth,
-									 barrier.m_texture.m_surface.m_face, barrier.m_texture.m_surface.m_layer,
-									 textureUsageToStr(alloc, barrier.m_texture.m_usageBefore).cstr(),
-									 textureUsageToStr(alloc, barrier.m_texture.m_usageAfter).cstr());
-
-				barrierName.sprintf("%s barrier%u", batchName.cstr(), barrierIdx);
-			}
-			else
-			{
-				barrierLabel.sprintf("<b>%s</b><br/>%s <b>to</b> %s",
-									 &descr.m_buffers[barrier.m_buffer.m_idx].m_name[0],
-									 bufferUsageToStr(alloc, barrier.m_buffer.m_usageBefore).cstr(),
-									 bufferUsageToStr(alloc, barrier.m_buffer.m_usageAfter).cstr());
+			barrierLabel.sprintf("<b>%s</b><br/>%s <b>to</b> %s", &descr.m_buffers[barrier.m_idx].m_name[0],
+								 bufferUsageToStr(alloc, barrier.m_usageBefore).cstr(),
+								 bufferUsageToStr(alloc, barrier.m_usageAfter).cstr());
 
-				barrierName.sprintf("%s barrier%u", batchName.cstr(), barrierIdx);
-			}
+			StringAuto barrierName(ctx.m_alloc);
+			barrierName.sprintf("%s buff barrier%u", batchName.cstr(), barrierIdx);
+
+			slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold,shape=box,label=< %s >];\n", barrierName.cstr(),
+								  COLORS[batchIdx % COLORS.getSize()], barrierLabel.cstr());
+			slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", prevBubble.cstr(), barrierName.cstr());
+
+			prevBubble = barrierName;
+		}
+
+		for(U32 barrierIdx = 0; barrierIdx < batch.m_asBarriersBefore.getSize(); ++barrierIdx)
+		{
+			const ASBarrier& barrier = batch.m_asBarriersBefore[barrierIdx];
+
+			StringAuto barrierLabel(ctx.m_alloc);
+			barrierLabel.sprintf("<b>%s</b><br/>%s <b>to</b> %s", descr.m_as[barrier.m_idx].m_name.getBegin(),
+								 asUsageToStr(alloc, barrier.m_usageBefore).cstr(),
+								 asUsageToStr(alloc, barrier.m_usageAfter).cstr());
+
+			StringAuto barrierName(ctx.m_alloc);
+			barrierName.sprintf("%s AS barrier%u", batchName.cstr(), barrierIdx);
 
 			slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold,shape=box,label=< %s >];\n", barrierName.cstr(),
 								  COLORS[batchIdx % COLORS.getSize()], barrierLabel.cstr());

+ 99 - 57
src/anki/gr/RenderGraph.h

@@ -13,6 +13,7 @@
 #include <anki/gr/Framebuffer.h>
 #include <anki/gr/TimestampQuery.h>
 #include <anki/gr/CommandBuffer.h>
+#include <anki/gr/AccelerationStructure.h>
 #include <anki/util/HashMap.h>
 #include <anki/util/BitSet.h>
 #include <anki/util/WeakArray.h>
@@ -29,13 +30,15 @@ class RenderGraphDescription;
 
 /// @name RenderGraph constants
 /// @{
-static constexpr U MAX_RENDER_GRAPH_PASSES = 128;
-static constexpr U MAX_RENDER_GRAPH_RENDER_TARGETS = 64; ///< Max imported or not render targets in RenderGraph.
-static constexpr U MAX_RENDER_GRAPH_BUFFERS = 64;
+constexpr U32 MAX_RENDER_GRAPH_PASSES = 128;
+constexpr U32 MAX_RENDER_GRAPH_RENDER_TARGETS = 64; ///< Max imported or not render targets in RenderGraph.
+constexpr U32 MAX_RENDER_GRAPH_BUFFERS = 64;
+constexpr U32 MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES = 32;
 /// @}
 
 /// Render target handle used in the RenderGraph.
-class RenderTargetHandle
+/// @memberof RenderGraphDescription
+class RenderGraphGrObjectHandle
 {
 	friend class RenderPassDependency;
 	friend class RenderGraphDescription;
@@ -43,12 +46,12 @@ class RenderTargetHandle
 	friend class RenderPassDescriptionBase;
 
 public:
-	Bool operator==(const RenderTargetHandle& b) const
+	Bool operator==(const RenderGraphGrObjectHandle& b) const
 	{
 		return m_idx == b.m_idx;
 	}
 
-	Bool operator!=(const RenderTargetHandle& b) const
+	Bool operator!=(const RenderGraphGrObjectHandle& b) const
 	{
 		return m_idx != b.m_idx;
 	}
@@ -60,44 +63,28 @@ public:
 
 private:
 	U32 m_idx = MAX_U32;
-
-	Bool valid() const
-	{
-		return m_idx != MAX_U32;
-	}
 };
 
-/// Buffer handle used in the RenderGraph.
-class RenderPassBufferHandle
+/// Render target (TexturePtr) handle.
+/// @memberof RenderGraphDescription
+class RenderTargetHandle : public RenderGraphGrObjectHandle
 {
-	friend class RenderPassDependency;
-	friend class RenderGraphDescription;
-	friend class RenderGraph;
-	friend class RenderPassDescriptionBase;
-
-public:
-	operator BufferPtr() const;
-
-	Bool operator==(const RenderPassBufferHandle& b) const
-	{
-		return m_idx == b.m_idx;
-	}
-
-	Bool operator!=(const RenderPassBufferHandle& b) const
-	{
-		return m_idx != b.m_idx;
-	}
+};
 
-private:
-	U32 m_idx = MAX_U32;
+/// BufferPtr handle.
+/// @memberof RenderGraphDescription
+class BufferHandle : public RenderGraphGrObjectHandle
+{
+};
 
-	Bool valid() const
-	{
-		return m_idx != MAX_U32;
-	}
+/// AccelerationStructurePtr handle.
+/// @memberof RenderGraphDescription
+class AccelerationStructureHandle : public RenderGraphGrObjectHandle
+{
 };
 
 /// Describes the render target.
+/// @memberof RenderGraphDescription
 class RenderTargetDescription : public TextureInitInfo
 {
 	friend class RenderGraphDescription;
@@ -125,6 +112,7 @@ private:
 };
 
 /// The only parameter of RenderPassWorkCallback.
+/// @memberof RenderGraph
 class RenderPassWorkContext
 {
 	friend class RenderGraph;
@@ -135,7 +123,7 @@ public:
 	U32 m_currentSecondLevelCommandBufferIndex ANKI_DEBUG_CODE(= 0);
 	U32 m_secondLevelCommandBufferCount ANKI_DEBUG_CODE(= 0);
 
-	void getBufferState(RenderPassBufferHandle handle, BufferPtr& buff) const;
+	void getBufferState(BufferHandle handle, BufferPtr& buff) const;
 
 	void getRenderTargetState(RenderTargetHandle handle, const TextureSubresourceInfo& subresource, TexturePtr& tex,
 							  TextureUsageBit& usage) const;
@@ -198,7 +186,7 @@ public:
 	}
 
 	/// Convenience method.
-	void bindStorageBuffer(U32 set, U32 binding, RenderPassBufferHandle handle)
+	void bindStorageBuffer(U32 set, U32 binding, BufferHandle handle)
 	{
 		BufferPtr buff;
 		getBufferState(handle, buff);
@@ -206,13 +194,16 @@ public:
 	}
 
 	/// Convenience method.
-	void bindUniformBuffer(U32 set, U32 binding, RenderPassBufferHandle handle)
+	void bindUniformBuffer(U32 set, U32 binding, BufferHandle handle)
 	{
 		BufferPtr buff;
 		getBufferState(handle, buff);
 		m_commandBuffer->bindUniformBuffer(set, binding, buff, 0, MAX_PTR_SIZE);
 	}
 
+	/// Convenience method.
+	void bindAccelerationStructure(U32 set, U32 binding, AccelerationStructureHandle handle);
+
 private:
 	const RenderGraph* m_rgraph ANKI_DEBUG_CODE(= nullptr);
 	U32 m_passIdx ANKI_DEBUG_CODE(= MAX_U32);
@@ -222,9 +213,11 @@ private:
 };
 
 /// Work callback for a RenderGraph pass.
+/// @memberof RenderGraphDescription
 using RenderPassWorkCallback = void (*)(RenderPassWorkContext& ctx);
 
 /// RenderGraph pass dependency.
+/// @memberof RenderGraphDescription
 class RenderPassDependency
 {
 	friend class RenderGraph;
@@ -234,27 +227,34 @@ public:
 	/// Dependency to a texture subresource.
 	RenderPassDependency(RenderTargetHandle handle, TextureUsageBit usage, const TextureSubresourceInfo& subresource)
 		: m_texture({handle, usage, subresource})
-		, m_isTexture(true)
+		, m_type(Type::TEXTURE)
 	{
-		ANKI_ASSERT(handle.valid());
+		ANKI_ASSERT(handle.isValid());
 	}
 
 	/// Dependency to the whole texture.
 	RenderPassDependency(RenderTargetHandle handle, TextureUsageBit usage,
 						 DepthStencilAspectBit aspect = DepthStencilAspectBit::NONE)
 		: m_texture({handle, usage, TextureSubresourceInfo()})
-		, m_isTexture(true)
+		, m_type(Type::TEXTURE)
 	{
-		ANKI_ASSERT(handle.valid());
+		ANKI_ASSERT(handle.isValid());
 		m_texture.m_subresource.m_mipmapCount = MAX_U32; // Mark it as "whole texture"
 		m_texture.m_subresource.m_depthStencilAspect = aspect;
 	}
 
-	RenderPassDependency(RenderPassBufferHandle handle, BufferUsageBit usage)
+	RenderPassDependency(BufferHandle handle, BufferUsageBit usage)
 		: m_buffer({handle, usage})
-		, m_isTexture(false)
+		, m_type(Type::BUFFER)
+	{
+		ANKI_ASSERT(handle.isValid());
+	}
+
+	RenderPassDependency(AccelerationStructureHandle handle, AccelerationStructureUsageBit usage)
+		: m_as({handle, usage})
+		, m_type(Type::ACCELERATION_STRUCTURE)
 	{
-		ANKI_ASSERT(handle.valid());
+		ANKI_ASSERT(handle.isValid());
 	}
 
 private:
@@ -266,22 +266,39 @@ private:
 		TextureSubresourceInfo m_subresource;
 	};
 
-	struct BufferInfo
+	class BufferInfo
 	{
-		RenderPassBufferHandle m_handle;
+	public:
+		BufferHandle m_handle;
 		BufferUsageBit m_usage;
 	};
 
+	class ASInfo
+	{
+	public:
+		AccelerationStructureHandle m_handle;
+		AccelerationStructureUsageBit m_usage;
+	};
+
 	union
 	{
 		TextureInfo m_texture;
 		BufferInfo m_buffer;
+		ASInfo m_as;
+	};
+
+	enum class Type : U8
+	{
+		BUFFER,
+		TEXTURE,
+		ACCELERATION_STRUCTURE
 	};
 
-	Bool m_isTexture;
+	Type m_type;
 };
 
 /// The base of compute/transfer and graphics renderpasses for RenderGraph.
+/// @memberof RenderGraphDescription
 class RenderPassDescriptionBase
 {
 	friend class RenderGraph;
@@ -293,6 +310,7 @@ public:
 		m_name.destroy(m_alloc); // To avoid the assertion
 		m_rtDeps.destroy(m_alloc);
 		m_buffDeps.destroy(m_alloc);
+		m_asDeps.destroy(m_alloc);
 	}
 
 	void setWork(RenderPassWorkCallback callback, void* userData, U32 secondLeveCmdbCount)
@@ -325,12 +343,14 @@ protected:
 
 	DynamicArray<RenderPassDependency> m_rtDeps;
 	DynamicArray<RenderPassDependency> m_buffDeps;
+	DynamicArray<RenderPassDependency> m_asDeps;
 
-	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> m_readRtMask = {false};
-	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> m_writeRtMask = {false};
-	BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> m_readBuffMask = {false};
-	BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> m_writeBuffMask = {false};
-	Bool m_hasBufferDeps = false; ///< Opt.
+	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> m_readRtMask{false};
+	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS, U64> m_writeRtMask{false};
+	BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> m_readBuffMask{false};
+	BitSet<MAX_RENDER_GRAPH_BUFFERS, U64> m_writeBuffMask{false};
+	BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> m_readAsMask{false};
+	BitSet<MAX_RENDER_GRAPH_ACCELERATION_STRUCTURES, U32> m_writeAsMask{false};
 
 	String m_name;
 
@@ -367,6 +387,7 @@ public:
 };
 
 /// Describes a framebuffer.
+/// @memberof RenderGraphDescription
 class FramebufferDescription
 {
 	friend class GraphicsRenderPassDescription;
@@ -390,6 +411,7 @@ private:
 };
 
 /// A graphics render pass for RenderGraph.
+/// @memberof RenderGraphDescription
 class GraphicsRenderPassDescription : public RenderPassDescriptionBase
 {
 	friend class RenderGraphDescription;
@@ -426,6 +448,7 @@ private:
 };
 
 /// A compute render pass for RenderGraph.
+/// @memberof RenderGraphDescription
 class ComputeRenderPassDescription : public RenderPassDescriptionBase
 {
 	friend class RenderGraphDescription;
@@ -440,6 +463,7 @@ private:
 };
 
 /// Builds the description of the frame's render passes and their interactions.
+/// @memberof RenderGraph
 class RenderGraphDescription
 {
 	friend class RenderGraph;
@@ -470,7 +494,11 @@ public:
 	RenderTargetHandle newRenderTarget(const RenderTargetDescription& initInf);
 
 	/// Import a buffer.
-	RenderPassBufferHandle importBuffer(BufferPtr buff, BufferUsageBit usage);
+	BufferHandle importBuffer(BufferPtr buff, BufferUsageBit usage);
+
+	/// Import an AS.
+	AccelerationStructureHandle importAccelerationStructure(AccelerationStructurePtr as,
+															AccelerationStructureUsageBit usage);
 
 	/// Gather statistics.
 	void setStatisticsEnabled(Bool gather)
@@ -510,14 +538,23 @@ private:
 		BufferPtr m_importedBuff;
 	};
 
+	class AS : public Resource
+	{
+	public:
+		AccelerationStructurePtr m_importedAs;
+		AccelerationStructureUsageBit m_usage;
+	};
+
 	StackAllocator<U8> m_alloc;
 	DynamicArray<RenderPassDescriptionBase*> m_passes;
 	DynamicArray<RT> m_renderTargets;
 	DynamicArray<Buffer> m_buffers;
+	DynamicArray<AS> m_as;
 	Bool m_gatherStatistics = false;
 };
 
 /// Statistics.
+/// @memberof RenderGraph
 class RenderGraphStatistics
 {
 public:
@@ -591,7 +628,10 @@ private:
 	class Batch;
 	class RT;
 	class Buffer;
-	class Barrier;
+	class AS;
+	class TextureBarrier;
+	class BufferBarrier;
+	class ASBarrier;
 
 	/// Render targets of the same type+size+format.
 	class RenderTargetCacheEntry
@@ -663,10 +703,12 @@ private:
 												CString path) const;
 	static StringAuto textureUsageToStr(StackAllocator<U8>& alloc, TextureUsageBit usage);
 	static StringAuto bufferUsageToStr(StackAllocator<U8>& alloc, BufferUsageBit usage);
+	static StringAuto asUsageToStr(StackAllocator<U8>& alloc, AccelerationStructureUsageBit usage);
 	/// @}
 
 	TexturePtr getTexture(RenderTargetHandle handle) const;
-	BufferPtr getBuffer(RenderPassBufferHandle handle) const;
+	BufferPtr getBuffer(BufferHandle handle) const;
+	AccelerationStructurePtr getAs(AccelerationStructureHandle handle) const;
 };
 /// @}
 

+ 66 - 15
src/anki/gr/RenderGraph.inl.h

@@ -8,7 +8,12 @@
 namespace anki
 {
 
-inline void RenderPassWorkContext::getBufferState(RenderPassBufferHandle handle, BufferPtr& buff) const
+inline void RenderPassWorkContext::bindAccelerationStructure(U32 set, U32 binding, AccelerationStructureHandle handle)
+{
+	m_commandBuffer->bindAccelerationStructure(set, binding, m_rgraph->getAs(handle));
+}
+
+inline void RenderPassWorkContext::getBufferState(BufferHandle handle, BufferPtr& buff) const
 {
 	buff = m_rgraph->getBuffer(handle);
 }
@@ -28,7 +33,7 @@ inline TexturePtr RenderPassWorkContext::getTexture(RenderTargetHandle handle) c
 
 inline void RenderPassDescriptionBase::fixSubresource(RenderPassDependency& dep) const
 {
-	ANKI_ASSERT(dep.m_isTexture);
+	ANKI_ASSERT(dep.m_type == RenderPassDependency::Type::TEXTURE);
 
 	TextureSubresourceInfo& subresource = dep.m_texture.m_subresource;
 	const Bool wholeTexture = subresource.m_mipmapCount == MAX_U32;
@@ -57,9 +62,9 @@ inline void RenderPassDescriptionBase::fixSubresource(RenderPassDependency& dep)
 inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& dep)
 {
 	// Validate dep
-	if(dep.m_isTexture)
+	if(dep.m_type == RenderPassDependency::Type::TEXTURE)
 	{
-		TextureUsageBit usage = dep.m_texture.m_usage;
+		const TextureUsageBit usage = dep.m_texture.m_usage;
 		(void)usage;
 		if(m_type == Type::GRAPHICS)
 		{
@@ -72,9 +77,9 @@ inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& d
 
 		ANKI_ASSERT(!!(usage & TextureUsageBit::ALL_READ) || !!(usage & TextureUsageBit::ALL_WRITE));
 	}
-	else
+	else if(dep.m_type == RenderPassDependency::Type::BUFFER)
 	{
-		BufferUsageBit usage = dep.m_buffer.m_usage;
+		const BufferUsageBit usage = dep.m_buffer.m_usage;
 		(void)usage;
 		if(m_type == Type::GRAPHICS)
 		{
@@ -87,18 +92,29 @@ inline void RenderPassDescriptionBase::validateDep(const RenderPassDependency& d
 
 		ANKI_ASSERT(!!(usage & BufferUsageBit::ALL_READ) || !!(usage & BufferUsageBit::ALL_WRITE));
 	}
+	else
+	{
+		ANKI_ASSERT(dep.m_type == RenderPassDependency::Type::ACCELERATION_STRUCTURE);
+		if(m_type == Type::GRAPHICS)
+		{
+			ANKI_ASSERT(!(dep.m_as.m_usage & AccelerationStructureUsageBit::ALL_GRAPHICS));
+		}
+		else
+		{
+			constexpr AccelerationStructureUsageBit usage = ~AccelerationStructureUsageBit::ALL_GRAPHICS;
+			ANKI_ASSERT(!(dep.m_as.m_usage & usage));
+		}
+	}
 }
 
 inline void RenderPassDescriptionBase::newDependency(const RenderPassDependency& dep)
 {
 	validateDep(dep);
 
-	DynamicArray<RenderPassDependency>& deps = (dep.m_isTexture) ? m_rtDeps : m_buffDeps;
-	deps.emplaceBack(m_alloc, dep);
-
-	if(dep.m_isTexture)
+	if(dep.m_type == RenderPassDependency::Type::TEXTURE)
 	{
-		fixSubresource(deps.getBack());
+		m_rtDeps.emplaceBack(m_alloc, dep);
+		fixSubresource(m_rtDeps.getBack());
 
 		if(!!(dep.m_texture.m_usage & TextureUsageBit::ALL_READ))
 		{
@@ -113,8 +129,10 @@ inline void RenderPassDescriptionBase::newDependency(const RenderPassDependency&
 		// Try to derive the usage by that dep
 		m_descr->m_renderTargets[dep.m_texture.m_handle.m_idx].m_usageDerivedByDeps |= dep.m_texture.m_usage;
 	}
-	else
+	else if(dep.m_type == RenderPassDependency::Type::BUFFER)
 	{
+		m_buffDeps.emplaceBack(m_alloc, dep);
+
 		if(!!(dep.m_buffer.m_usage & BufferUsageBit::ALL_READ))
 		{
 			m_readBuffMask.set(dep.m_buffer.m_handle.m_idx);
@@ -124,8 +142,21 @@ inline void RenderPassDescriptionBase::newDependency(const RenderPassDependency&
 		{
 			m_writeBuffMask.set(dep.m_buffer.m_handle.m_idx);
 		}
+	}
+	else
+	{
+		ANKI_ASSERT(dep.m_type == RenderPassDependency::Type::ACCELERATION_STRUCTURE);
+		m_asDeps.emplaceBack(m_alloc, dep);
+
+		if(!!(dep.m_as.m_usage & AccelerationStructureUsageBit::ALL_READ))
+		{
+			m_readAsMask.set(dep.m_as.m_handle.m_idx);
+		}
 
-		m_hasBufferDeps = true;
+		if(!!(dep.m_as.m_usage & AccelerationStructureUsageBit::ALL_WRITE))
+		{
+			m_writeAsMask.set(dep.m_as.m_handle.m_idx);
+		}
 	}
 }
 
@@ -186,6 +217,7 @@ inline RenderGraphDescription::~RenderGraphDescription()
 	m_passes.destroy(m_alloc);
 	m_renderTargets.destroy(m_alloc);
 	m_buffers.destroy(m_alloc);
+	m_as.destroy(m_alloc);
 }
 
 inline GraphicsRenderPassDescription& RenderGraphDescription::newGraphicsRenderPass(CString name)
@@ -248,7 +280,7 @@ inline RenderTargetHandle RenderGraphDescription::newRenderTarget(const RenderTa
 	return out;
 }
 
-inline RenderPassBufferHandle RenderGraphDescription::importBuffer(BufferPtr buff, BufferUsageBit usage)
+inline BufferHandle RenderGraphDescription::importBuffer(BufferPtr buff, BufferUsageBit usage)
 {
 	for(const Buffer& bb : m_buffers)
 	{
@@ -261,9 +293,28 @@ inline RenderPassBufferHandle RenderGraphDescription::importBuffer(BufferPtr buf
 	b.m_usage = usage;
 	b.m_importedBuff = buff;
 
-	RenderPassBufferHandle out;
+	BufferHandle out;
 	out.m_idx = m_buffers.getSize() - 1;
 	return out;
 }
 
+inline AccelerationStructureHandle
+RenderGraphDescription::importAccelerationStructure(AccelerationStructurePtr as, AccelerationStructureUsageBit usage)
+{
+	for(const AS& a : m_as)
+	{
+		(void)a;
+		ANKI_ASSERT(a.m_importedAs != as && "Already imported");
+	}
+
+	AS& a = *m_as.emplaceBack(m_alloc);
+	a.setName(as->getName());
+	a.m_importedAs = as;
+	a.m_usage = usage;
+
+	AccelerationStructureHandle handle;
+	handle.m_idx = m_as.getSize() - 1;
+	return handle;
+}
+
 } // end namespace anki

+ 3 - 2
src/anki/gr/vulkan/AccelerationStructureImpl.cpp

@@ -261,9 +261,10 @@ void AccelerationStructureImpl::computeBarrierInfo(AccelerationStructureUsageBit
 		dstAccesses |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
 	}
 
-	if(!!(after & AccelerationStructureUsageBit::VERTEX_READ))
+	if(!!(after & AccelerationStructureUsageBit::GEOMETRY_READ))
 	{
-		dstStages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+		dstStages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
+					 | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
 		dstAccesses |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
 	}
 

+ 2 - 2
src/anki/renderer/LensFlare.h

@@ -33,7 +33,7 @@ public:
 	void populateRenderGraph(RenderingContext& ctx);
 
 	/// Get it to set a dependency.
-	RenderPassBufferHandle getIndirectDrawBuffer() const
+	BufferHandle getIndirectDrawBuffer() const
 	{
 		return m_runCtx.m_indirectBuffHandle;
 	}
@@ -55,7 +55,7 @@ private:
 	{
 	public:
 		RenderingContext* m_ctx = nullptr;
-		RenderPassBufferHandle m_indirectBuffHandle;
+		BufferHandle m_indirectBuffHandle;
 	} m_runCtx;
 
 	ANKI_USE_RESULT Error initSprite(const ConfigSet& config);

+ 1 - 1
src/anki/renderer/ProbeReflections.h

@@ -126,7 +126,7 @@ private:
 		Array<RenderTargetHandle, GBUFFER_COLOR_ATTACHMENT_COUNT> m_gbufferColorRts;
 		RenderTargetHandle m_gbufferDepthRt;
 		RenderTargetHandle m_lightShadingRt;
-		RenderPassBufferHandle m_irradianceDiceValuesBuffHandle;
+		BufferHandle m_irradianceDiceValuesBuffHandle;
 		RenderTargetHandle m_shadowMapRt;
 
 		U32 m_gbufferRenderableCount = 0;

+ 2 - 2
src/anki/renderer/Tonemapping.h

@@ -29,7 +29,7 @@ public:
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 
-	RenderPassBufferHandle getAverageLuminanceBuffer() const
+	BufferHandle getAverageLuminanceBuffer() const
 	{
 		return m_runCtx.m_buffHandle;
 	}
@@ -44,7 +44,7 @@ private:
 	class
 	{
 	public:
-		RenderPassBufferHandle m_buffHandle;
+		BufferHandle m_buffHandle;
 	} m_runCtx;
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& cfg);