Przeglądaj źródła

Gr: Some work on the render graph

Panagiotis Christopoulos Charitos 8 lat temu
rodzic
commit
be9faf6f2f
4 zmienionych plików z 124 dodań i 98 usunięć
  1. 1 9
      src/anki/gr/Common.h
  2. 66 56
      src/anki/gr/RenderGraph.cpp
  3. 22 16
      src/anki/gr/RenderGraph.h
  4. 35 17
      tests/gr/Gr.cpp

+ 1 - 9
src/anki/gr/Common.h

@@ -157,15 +157,7 @@ public:
 
 	U64 computeHash() const
 	{
-		ANKI_ASSERT(m_level < MAX_U16 && m_depth < MAX_U16 && m_face < MAX_U16 && m_layer < MAX_U16);
-		U64 hash = m_level;
-		hash <<= 16;
-		hash |= m_depth;
-		hash <<= 16;
-		hash |= m_face + 1; // Add one so we won't end up with zero hash
-		hash <<= 16;
-		hash |= m_layer;
-		return hash;
+		return anki::computeHash(this, sizeof(*this), 0x1234567);
 	}
 
 	U32 m_level = 0;

+ 66 - 56
src/anki/gr/RenderGraph.cpp

@@ -18,12 +18,13 @@ namespace anki
 class RenderGraph::RT
 {
 public:
-	HashMap<TextureSurfaceInfo, TextureUsageBit> m_surfUsageMap;
-
-	RT()
-		: m_surfUsageMap(8, 4)
+	struct Usage
 	{
-	}
+		TextureUsageBit m_usage;
+		TextureSurfaceInfo m_surf;
+	};
+
+	DynamicArray<Usage> m_surfUsages;
 };
 
 /// Pipeline barrier of texture or buffer.
@@ -84,12 +85,10 @@ class RenderGraph::Batch
 public:
 	DynamicArrayAuto<U32> m_passes;
 	DynamicArrayAuto<Barrier> m_barriersBefore;
-	DynamicArrayAuto<Barrier> m_barriersAfter;
 
 	Batch(const StackAllocator<U8>& alloc)
 		: m_passes(alloc)
 		, m_barriersBefore(alloc)
-		, m_barriersAfter(alloc)
 	{
 	}
 };
@@ -186,15 +185,12 @@ TexturePtr RenderGraph::getOrCreateRenderTarget(const TextureInitInfo& initInf)
 
 Bool RenderGraph::passADependsOnB(BakeContext& ctx, const RenderPassBase& a, const RenderPassBase& b)
 {
-	Bool depends = false;
-
 	/// Compute the 3 types of dependencies
 	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS> aReadBWrite = a.m_consumerRtMask & b.m_producerRtMask;
 	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS> aWriteBRead = a.m_producerRtMask & b.m_consumerRtMask;
 	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS> aWriteBWrite = a.m_producerRtMask & b.m_producerRtMask;
 
 	BitSet<MAX_RENDER_GRAPH_RENDER_TARGETS> fullDep = aReadBWrite | aWriteBRead | aWriteBWrite;
-	// fullDep &= ~ctx.m_satisfiedRts;
 
 	if(fullDep.getAny())
 	{
@@ -209,9 +205,7 @@ Bool RenderGraph::passADependsOnB(BakeContext& ctx, const RenderPassBase& a, con
 					if(producer.m_isTexture && producer.m_texture.m_handle == consumer.m_texture.m_handle
 						&& producer.m_texture.m_surface == consumer.m_texture.m_surface)
 					{
-						depends = true;
-						// ANKI_ASSERT(!ctx.m_satisfiedRts.get(dep.m_texture.m_handle));
-						// ctx.m_satisfiedRts.set(dep.m_texture.m_handle);
+						return true;
 					}
 				}
 			}
@@ -236,7 +230,7 @@ Bool RenderGraph::passADependsOnB(BakeContext& ctx, const RenderPassBase& a, con
 	}
 #endif
 
-	return depends;
+	return false;
 }
 
 Bool RenderGraph::passHasUnmetDependencies(const BakeContext& ctx, U32 passIdx)
@@ -334,6 +328,13 @@ void RenderGraph::compileNewGraph(const RenderGraphDescription& descr)
 		ANKI_LOGF("Won't recover on debug code");
 	}
 #endif
+
+#if ANKI_EXTRA_CHECKS
+	for(RT& rt : ctx.m_rts)
+	{
+		rt.m_surfUsages.destroy(ctx.m_alloc);
+	}
+#endif
 }
 
 void RenderGraph::setBatchBarriers(BakeContext& ctx) const
@@ -356,52 +357,41 @@ void RenderGraph::setBatchBarriers(BakeContext& ctx) const
 					const U32 rtIdx = consumer.m_texture.m_handle;
 					const TextureUsageBit consumerUsage = consumer.m_texture.m_usage;
 
-					// Get current suage
-					TextureUsageBit crntUsage;
-					auto it = ctx.m_rts[rtIdx].m_surfUsageMap.find(consumer.m_texture.m_surface);
-					if(it != ctx.m_rts[rtIdx].m_surfUsageMap.getEnd())
+					Bool anySurfaceFound = false;
+					const Bool wholeTex = consumer.m_texture.m_wholeTex;
+					for(RT::Usage& u : ctx.m_rts[rtIdx].m_surfUsages)
 					{
-						crntUsage = *it;
-						*it = consumerUsage;
-					}
-					else
-					{
-						crntUsage = ctx.m_descr->m_renderTargets[rtIdx].m_usage;
-						ctx.m_rts[rtIdx].m_surfUsageMap.emplace(alloc, consumer.m_texture.m_surface, consumerUsage);
+						if(wholeTex || u.m_surf == consumer.m_texture.m_surface)
+						{
+							if(u.m_usage != consumerUsage)
+							{
+								batch.m_barriersBefore.emplaceBack(consumer.m_texture.m_handle,
+									u.m_usage,
+									consumerUsage,
+									consumer.m_texture.m_surface);
+
+								u.m_usage = consumer.m_texture.m_usage;
+								anySurfaceFound = true;
+							}
+						}
 					}
 
-					if(crntUsage != consumerUsage)
+					if(!anySurfaceFound && ctx.m_descr->m_renderTargets[rtIdx].m_usage != consumerUsage)
 					{
-						batch.m_barriersBefore.emplaceBack(
-							consumer.m_texture.m_handle, crntUsage, consumerUsage, consumer.m_texture.m_surface);
-					}
-				}
-				else
-				{
-					// TODO
-				}
-			}
-
-// For all producers, just check some stuff
-#if ANKI_EXTRA_CHECKS
-			for(const RenderPassDependency& producer : pass.m_producers)
-			{
-				if(producer.m_isTexture)
-				{
-					const U32 rtIdx = producer.m_texture.m_handle;
+						batch.m_barriersBefore.emplaceBack(consumer.m_texture.m_handle,
+							ctx.m_descr->m_renderTargets[rtIdx].m_usage,
+							consumerUsage,
+							consumer.m_texture.m_surface);
 
-					auto it = ctx.m_rts[rtIdx].m_surfUsageMap.find(producer.m_texture.m_surface);
-					ANKI_ASSERT(it != ctx.m_rts[rtIdx].m_surfUsageMap.getEnd()
-						&& "There should have been a consumer that added a map entry");
-
-					ANKI_ASSERT(*it == producer.m_texture.m_usage && "The consumer should have set that");
+						RT::Usage usage{consumerUsage, consumer.m_texture.m_surface};
+						ctx.m_rts[rtIdx].m_surfUsages.emplaceBack(alloc, usage);
+					}
 				}
 				else
 				{
 					// TODO
 				}
 			}
-#endif
 		}
 	}
 }
@@ -479,7 +469,17 @@ Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) c
 		}
 	}
 
+	// Color the resources
+	slist.pushBackSprintf("subgraph cluster_0 {\n");
+	for(U rtIdx = 0; rtIdx < ctx.m_descr->m_renderTargets.getSize(); ++rtIdx)
+	{
+		slist.pushBackSprintf(
+			"\t\"%s\"[color=%s];\n", &ctx.m_descr->m_renderTargets[rtIdx].m_name[0], COLORS[rtIdx % 6]);
+	}
+	slist.pushBackSprintf("}\n");
+
 	// Barriers
+	slist.pushBackSprintf("subgraph cluster_1 {\n");
 	StringAuto prevBubble(ctx.m_alloc);
 	prevBubble.create("START");
 	for(U batchIdx = 0; batchIdx < ctx.m_batches.getSize(); ++batchIdx)
@@ -495,9 +495,14 @@ Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) c
 			StringAuto barrierName(ctx.m_alloc);
 			if(barrier.m_isTexture)
 			{
-				barrierName.sprintf("%s barrier%u\n%s -> %s",
+				barrierName.sprintf("%s barrier%u\n%s (mip,dp,f,l)=(%u,%u,%u,%u)\n%s -> %s",
 					&batchName[0],
 					barrierIdx,
+					&ctx.m_descr->m_renderTargets[barrier.m_tex.m_idx].m_name[0],
+					barrier.m_tex.m_surf.m_level,
+					barrier.m_tex.m_surf.m_depth,
+					barrier.m_tex.m_surf.m_face,
+					barrier.m_tex.m_surf.m_layer,
 					&textureUsageToStr(ctx, barrier.m_tex.m_usageBefore).toCString()[0],
 					&textureUsageToStr(ctx, barrier.m_tex.m_usageAfter).toCString()[0]);
 			}
@@ -509,23 +514,27 @@ Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) c
 			slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold,shape=box];\n", &barrierName[0], COLORS[batchIdx % 6]);
 			slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", &prevBubble[0], &barrierName[0]);
 
-			// Print render target dep
+#if 0
+			// Print dep
 			if(barrier.m_isTexture)
 			{
 				StringAuto rtName(ctx.m_alloc);
-				rtName.sprintf("%s\n(mip:%u dp:%u f:%u l:%u)",
-					&ctx.m_descr->m_renderTargets[barrier.m_tex.m_idx].m_name[0],
+				rtName.sprintf("%s", &ctx.m_descr->m_renderTargets[barrier.m_tex.m_idx].m_name[0]);
+
+				slist.pushBackSprintf("\t\"%s\":w->\"%s\":e[label=\"(mip,dp,f,l)=(%u,%u,%u,%u)\";color=%s];\n",
+					&rtName[0],
+					&barrierName[0],
 					barrier.m_tex.m_surf.m_level,
 					barrier.m_tex.m_surf.m_depth,
 					barrier.m_tex.m_surf.m_face,
-					barrier.m_tex.m_surf.m_layer);
-
-				slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", &rtName[0], &barrierName[0]);
+					barrier.m_tex.m_surf.m_layer,
+					COLORS[barrier.m_tex.m_idx % 6]);
 			}
 			else
 			{
 				// TODO
 			}
+#endif
 
 			prevBubble = barrierName;
 		}
@@ -534,6 +543,7 @@ Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) c
 		slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", &prevBubble[0], &batchName[0]);
 		prevBubble = batchName;
 	}
+	slist.pushBackSprintf("}\n");
 
 	slist.pushBackSprintf("}");
 

+ 22 - 16
src/anki/gr/RenderGraph.h

@@ -41,11 +41,33 @@ class RenderPassDependency
 	friend class RenderPassBase;
 
 public:
+	/// Dependency to an individual surface.
+	RenderPassDependency(RenderTargetHandle handle, TextureUsageBit usage, const TextureSurfaceInfo& surface)
+		: m_texture({handle, usage, surface, false})
+		, m_isTexture(true)
+	{
+	}
+
+	/// Dependency to the whole texture.
+	RenderPassDependency(RenderTargetHandle handle, TextureUsageBit usage)
+		: m_texture({handle, usage, TextureSurfaceInfo(0, 0, 0, 0), true})
+		, m_isTexture(true)
+	{
+	}
+
+	RenderPassDependency(RenderPassBufferHandle handle, BufferUsageBit usage, PtrSize offset, PtrSize range)
+		: m_buffer({handle, usage, offset, range})
+		, m_isTexture(false)
+	{
+	}
+
+private:
 	struct TextureInfo
 	{
 		RenderTargetHandle m_handle;
 		TextureUsageBit m_usage;
 		TextureSurfaceInfo m_surface;
+		Bool8 m_wholeTex;
 	};
 
 	struct BufferInfo
@@ -62,22 +84,6 @@ public:
 		BufferInfo m_buffer;
 	};
 
-	RenderPassDependency(RenderTargetHandle handle,
-		TextureUsageBit usage,
-		const TextureSurfaceInfo& surface = TextureSurfaceInfo(0, 0, 0, 0))
-		: m_texture({handle, usage, surface})
-		, m_isTexture(true)
-	{
-	}
-
-	RenderPassDependency(
-		RenderPassBufferHandle handle, BufferUsageBit usage, PtrSize offset = 0, PtrSize range = MAX_PTR_SIZE)
-		: m_buffer({handle, usage, offset, range})
-		, m_isTexture(false)
-	{
-	}
-
-private:
 	Bool8 m_isTexture;
 };
 

+ 35 - 17
tests/gr/Gr.cpp

@@ -1541,13 +1541,13 @@ ANKI_TEST(Gr, RenderGraph)
 
 	const U GI_MIP_COUNT = 4;
 
-	TextureInitInfo texInf("sm_scratch");
+	TextureInitInfo texInf("SM scratch");
 	texInf.m_width = texInf.m_height = 16;
 	texInf.m_usage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE | TextureUsageBit::SAMPLED_FRAGMENT;
 	texInf.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 
 	// SM
-	RenderTargetHandle smScratchRt = descr.newRenderTarget("sm_scratch", texInf);
+	RenderTargetHandle smScratchRt = descr.newRenderTarget("SM", texInf);
 	{
 		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("SM");
 		pass.newConsumer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
@@ -1555,7 +1555,7 @@ ANKI_TEST(Gr, RenderGraph)
 	}
 
 	// SM to exponential SM
-	RenderTargetHandle smExpRt = descr.newRenderTarget("sm_exp", texInf);
+	RenderTargetHandle smExpRt = descr.newRenderTarget("ESM", texInf);
 	{
 		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("ESM");
 		pass.newConsumer({smScratchRt, TextureUsageBit::SAMPLED_FRAGMENT});
@@ -1564,9 +1564,9 @@ ANKI_TEST(Gr, RenderGraph)
 	}
 
 	// GI gbuff
-	RenderTargetHandle giGbuffNormRt = descr.newRenderTarget("GI gbuff norm", texInf);
-	RenderTargetHandle giGbuffDiffRt = descr.newRenderTarget("GI gbuff diff", texInf);
-	RenderTargetHandle giGbuffDepthRt = descr.newRenderTarget("GI gbuff depth", texInf);
+	RenderTargetHandle giGbuffNormRt = descr.newRenderTarget("GI GBuff norm", texInf);
+	RenderTargetHandle giGbuffDiffRt = descr.newRenderTarget("GI GBuff diff", texInf);
+	RenderTargetHandle giGbuffDepthRt = descr.newRenderTarget("GI GBuff depth", texInf);
 	{
 		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("GI gbuff");
 		pass.newConsumer({giGbuffNormRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
@@ -1583,7 +1583,7 @@ ANKI_TEST(Gr, RenderGraph)
 	for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
 	{
 		GraphicsRenderPassInfo& pass =
-			descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI li%u", faceIdx).toCString());
+			descr.newGraphicsRenderPass(StringAuto(alloc).sprintf("GI lp%u", faceIdx).toCString());
 		pass.newConsumer(
 			{giGiLightRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, TextureSurfaceInfo(0, 0, faceIdx, 0)});
 		pass.newConsumer({giGbuffNormRt, TextureUsageBit::SAMPLED_FRAGMENT});
@@ -1610,18 +1610,17 @@ ANKI_TEST(Gr, RenderGraph)
 		}
 	}
 
-#if 0
 	// Gbuffer
-	RenderTargetHandle gbuffRt0 = descr.newRenderTarget("Gbuff rt0", texInf);
-	RenderTargetHandle gbuffRt1 = descr.newRenderTarget("Gbuff rt1", texInf);
-	RenderTargetHandle gbuffRt2 = descr.newRenderTarget("Gbuff rt2", texInf);
-	RenderTargetHandle gbuffDepth = descr.newRenderTarget("Gbuff rt2", texInf);
+	RenderTargetHandle gbuffRt0 = descr.newRenderTarget("GBuff RT0", texInf);
+	RenderTargetHandle gbuffRt1 = descr.newRenderTarget("GBuff RT1", texInf);
+	RenderTargetHandle gbuffRt2 = descr.newRenderTarget("GBuff RT2", texInf);
+	RenderTargetHandle gbuffDepth = descr.newRenderTarget("GBuff RT2", texInf);
 	{
-		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("G-buffer");
-		pass.newConsumer({gbuffRt0, TextureUsageBit::NONE});
-		pass.newConsumer({gbuffRt1, TextureUsageBit::NONE});
-		pass.newConsumer({gbuffRt2, TextureUsageBit::NONE});
-		pass.newConsumer({gbuffDepth, TextureUsageBit::NONE});
+		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("G-Buffer");
+		pass.newConsumer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		pass.newConsumer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		pass.newConsumer({gbuffRt2, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		pass.newConsumer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
 
 		pass.newProducer({gbuffRt0, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
 		pass.newProducer({gbuffRt1, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
@@ -1629,6 +1628,25 @@ ANKI_TEST(Gr, RenderGraph)
 		pass.newProducer({gbuffDepth, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
 	}
 
+	// Half depth
+	RenderTargetHandle halfDepthRt = descr.newRenderTarget("Depth/2", texInf);
+	{
+		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("HalfDepth");
+		pass.newConsumer({gbuffDepth, TextureUsageBit::SAMPLED_FRAGMENT});
+		pass.newConsumer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		pass.newProducer({halfDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+	}
+
+	// Quarter depth
+	RenderTargetHandle quarterDepthRt = descr.newRenderTarget("Depth/4", texInf);
+	{
+		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("QuarterDepth");
+		pass.newConsumer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+		pass.newConsumer({halfDepthRt, TextureUsageBit::SAMPLED_FRAGMENT});
+		pass.newProducer({quarterDepthRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
+	}
+
+#if 0
 	// Light
 	RenderTargetHandle lightRt = descr.newRenderTarget("Light", texInf);
 	{