Просмотр исходного кода

GR: Some work on the render graph

Panagiotis Christopoulos Charitos 8 лет назад
Родитель
Сommit
5d5d360e81
3 измененных файлов с 205 добавлено и 83 удалено
  1. 181 77
      src/anki/gr/RenderGraph.cpp
  2. 22 4
      src/anki/gr/RenderGraph.h
  3. 2 2
      tests/gr/Gr.cpp

+ 181 - 77
src/anki/gr/RenderGraph.cpp

@@ -9,6 +9,7 @@
 #include <anki/gr/Framebuffer.h>
 #include <anki/util/BitSet.h>
 #include <anki/util/File.h>
+#include <anki/util/StringList.h>
 
 namespace anki
 {
@@ -20,19 +21,42 @@ public:
 	TextureUsageBit m_usage;
 };
 
-class RenderGraph::RTBarrier
+/// Pipeline barrier of texture or buffer.
+class RenderGraph::Barrier
 {
 public:
-	U32 m_rtIdx;
-	TextureUsageBit m_usageBefore;
-	TextureUsageBit m_usageAfter;
-	TextureSurfaceInfo m_surf;
-
-	RTBarrier(U32 rtIdx, TextureUsageBit usageBefore, TextureUsageBit usageAfter, const TextureSurfaceInfo& surf)
-		: m_rtIdx(rtIdx)
-		, m_usageBefore(usageBefore)
-		, m_usageAfter(usageAfter)
-		, m_surf(surf)
+	struct TextureInfo
+	{
+		U32 m_idx;
+		TextureUsageBit m_usageBefore;
+		TextureUsageBit m_usageAfter;
+		TextureSurfaceInfo m_surf;
+	};
+
+	struct BufferInfo
+	{
+		U32 m_idx;
+		BufferUsageBit m_usageBefore;
+		BufferUsageBit m_usageAfter;
+	};
+
+	union
+	{
+		TextureInfo m_tex;
+		BufferInfo m_buff;
+	};
+
+	Bool8 m_isTexture;
+
+	Barrier(U32 rtIdx, TextureUsageBit usageBefore, TextureUsageBit usageAfter, const TextureSurfaceInfo& surf)
+		: m_tex({rtIdx, usageBefore, usageAfter, surf})
+		, m_isTexture(true)
+	{
+	}
+
+	Barrier(U32 buffIdx, BufferUsageBit usageBefore, BufferUsageBit usageAfter)
+		: m_buff({buffIdx, usageBefore, usageAfter})
+		, m_isTexture(false)
 	{
 	}
 };
@@ -54,13 +78,13 @@ class RenderGraph::Batch
 {
 public:
 	DynamicArrayAuto<U32> m_passes;
-	DynamicArrayAuto<RTBarrier> m_rtBarriersBefore;
-	DynamicArrayAuto<RTBarrier> m_rtBarriersAfter;
+	DynamicArrayAuto<Barrier> m_barriersBefore;
+	DynamicArrayAuto<Barrier> m_barriersAfter;
 
 	Batch(const StackAllocator<U8>& alloc)
 		: m_passes(alloc)
-		, m_rtBarriersBefore(alloc)
-		, m_rtBarriersAfter(alloc)
+		, m_barriersBefore(alloc)
+		, m_barriersAfter(alloc)
 	{
 	}
 };
@@ -111,66 +135,6 @@ void RenderGraph::reset()
 	// TODO
 }
 
-Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) const
-{
-	File file;
-	ANKI_CHECK(file.open(StringAuto(ctx.m_alloc).sprintf("%s/rgraph.dot", &path[0]).toCString(), FileOpenFlag::WRITE));
-
-	ANKI_CHECK(file.writeText("digraph {\n"));
-	ANKI_CHECK(file.writeText("splines = ortho;\nconcentrate = true;\n"));
-
-	for(U batchIdx = 0; batchIdx < ctx.m_batches.getSize(); ++batchIdx)
-	{
-		ANKI_CHECK(file.writeText("\t{rank=\"same\";"));
-		for(U32 passIdx : ctx.m_batches[batchIdx].m_passes)
-		{
-			ANKI_CHECK(file.writeText("\"%s\";", &ctx.m_descr->m_passes[passIdx]->m_name[0]));
-		}
-		ANKI_CHECK(file.writeText("}\n"));
-
-		for(U32 passIdx : ctx.m_batches[batchIdx].m_passes)
-		{
-			for(U32 depIdx : ctx.m_passes[passIdx].m_dependsOn)
-			{
-				ANKI_CHECK(file.writeText("\t\"%s\"->\"%s\";\n",
-					&ctx.m_descr->m_passes[depIdx]->m_name[0],
-					&ctx.m_descr->m_passes[passIdx]->m_name[0]));
-			}
-
-			if(ctx.m_passes[passIdx].m_dependsOn.getSize() == 0)
-			{
-				ANKI_CHECK(file.writeText("\tNONE->\"%s\";\n", &ctx.m_descr->m_passes[passIdx]->m_name[0]));
-			}
-		}
-	}
-
-	ANKI_CHECK(file.writeText("}"));
-
-// Barriers
-#if 0
-	ANKI_CHECK(file.writeText("digraph {\n"));
-	ANKI_CHECK(file.writeText("splines = ortho;\nconcentrate = true;\n"));
-
-	for(U batchIdx = 0; batchIdx < ctx.m_batches.getSize(); ++batchIdx)
-	{
-		const Batch& batch = ctx.m_batches[batchIdx];
-		StringAuto prevBatchName(ctx.m_alloc);
-		if(batchIdx == 0)
-		{
-			prevBatchName.sprintf("%s", "NONE");
-		}
-		else
-		{
-			prevBatchName.sprintf("batch_%u", batchIdx - 1);
-		}
-	}
-
-	ANKI_CHECK(file.writeText("}"));
-#endif
-
-	return Error::NONE;
-}
-
 TexturePtr RenderGraph::getOrCreateRenderTarget(const TextureInitInfo& initInf)
 {
 	auto alloc = getManager().getAllocator();
@@ -391,7 +355,7 @@ void RenderGraph::setBatchBarriers(BakeContext& ctx) const
 
 					if(crntUsage != consumerUsage)
 					{
-						batch.m_rtBarriersBefore.emplaceBack(
+						batch.m_barriersBefore.emplaceBack(
 							consumer.m_texture.m_handle, crntUsage, consumerUsage, consumer.m_texture.m_surface);
 
 						crntUsage = consumerUsage;
@@ -413,7 +377,7 @@ void RenderGraph::setBatchBarriers(BakeContext& ctx) const
 
 					if(crntUsage != producerUsage)
 					{
-						batch.m_rtBarriersAfter.emplaceBack(
+						batch.m_barriersAfter.emplaceBack(
 							producer.m_texture.m_handle, producerUsage, crntUsage, producer.m_texture.m_surface);
 
 						crntUsage = producerUsage;
@@ -428,4 +392,144 @@ void RenderGraph::setBatchBarriers(BakeContext& ctx) const
 	}
 }
 
+StringAuto RenderGraph::textureUsageToStr(const BakeContext& ctx, TextureUsageBit usage)
+{
+	StringListAuto slist(ctx.m_alloc);
+
+#define ANKI_TEX_USAGE(u)                \
+	if(!!(usage & TextureUsageBit::u))   \
+	{                                    \
+		slist.pushBackSprintf("%s", #u); \
+	}
+
+	ANKI_TEX_USAGE(SAMPLED_VERTEX);
+	ANKI_TEX_USAGE(SAMPLED_TESSELLATION_CONTROL);
+	ANKI_TEX_USAGE(SAMPLED_TESSELLATION_EVALUATION);
+	ANKI_TEX_USAGE(SAMPLED_GEOMETRY);
+	ANKI_TEX_USAGE(SAMPLED_FRAGMENT);
+	ANKI_TEX_USAGE(IMAGE_COMPUTE_READ);
+	ANKI_TEX_USAGE(IMAGE_COMPUTE_WRITE);
+	ANKI_TEX_USAGE(FRAMEBUFFER_ATTACHMENT_READ);
+	ANKI_TEX_USAGE(FRAMEBUFFER_ATTACHMENT_WRITE);
+	ANKI_TEX_USAGE(TRANSFER_DESTINATION);
+	ANKI_TEX_USAGE(GENERATE_MIPMAPS);
+	ANKI_TEX_USAGE(CLEAR);
+
+	if(!usage)
+	{
+		slist.pushBackSprintf("NONE");
+	}
+
+#undef ANKI_TEX_USAGE
+
+	StringAuto str(ctx.m_alloc);
+	slist.join(" | ", str);
+	return str;
+}
+
+Error RenderGraph::dumpDependencyDotFile(const BakeContext& ctx, CString path) const
+{
+	static const Array<const char*, 6> COLORS = {{"red", "green", "blue", "magenta", "yellow", "cyan"}};
+	auto alloc = ctx.m_alloc;
+	StringListAuto slist(alloc);
+
+	slist.pushBackSprintf("digraph {\n");
+	slist.pushBackSprintf("\t//splines = ortho;\nconcentrate = true;\n");
+
+	for(U batchIdx = 0; batchIdx < ctx.m_batches.getSize(); ++batchIdx)
+	{
+		// Set same rank
+		slist.pushBackSprintf("\t{rank=\"same\";");
+		for(U32 passIdx : ctx.m_batches[batchIdx].m_passes)
+		{
+			slist.pushBackSprintf("\"%s\";", &ctx.m_descr->m_passes[passIdx]->m_name[0]);
+		}
+		slist.pushBackSprintf("}\n");
+
+		// Print passes
+		for(U32 passIdx : ctx.m_batches[batchIdx].m_passes)
+		{
+			CString passName = ctx.m_descr->m_passes[passIdx]->m_name.toCString();
+
+			slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold,shape=box];\n", &passName[0], COLORS[batchIdx % 6]);
+
+			for(U32 depIdx : ctx.m_passes[passIdx].m_dependsOn)
+			{
+				slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", &ctx.m_descr->m_passes[depIdx]->m_name[0], &passName[0]);
+			}
+
+			if(ctx.m_passes[passIdx].m_dependsOn.getSize() == 0)
+			{
+				slist.pushBackSprintf("\tNONE->\"%s\";\n", &ctx.m_descr->m_passes[passIdx]->m_name[0]);
+			}
+		}
+	}
+
+	// Barriers
+	StringAuto prevBubble(ctx.m_alloc);
+	prevBubble.create("START");
+	for(U batchIdx = 0; batchIdx < ctx.m_batches.getSize(); ++batchIdx)
+	{
+		const Batch& batch = ctx.m_batches[batchIdx];
+
+		StringAuto batchName(ctx.m_alloc);
+		batchName.sprintf("batch%u", batchIdx);
+
+		for(U barrierIdx = 0; barrierIdx < batch.m_barriersBefore.getSize(); ++barrierIdx)
+		{
+			const Barrier& barrier = batch.m_barriersBefore[barrierIdx];
+			StringAuto barrierName(ctx.m_alloc);
+			if(barrier.m_isTexture)
+			{
+				barrierName.sprintf("%s barrier%u\n%s -> %s",
+					&batchName[0],
+					barrierIdx,
+					&textureUsageToStr(ctx, barrier.m_tex.m_usageBefore).toCString()[0],
+					&textureUsageToStr(ctx, barrier.m_tex.m_usageAfter).toCString()[0]);
+			}
+			else
+			{
+				// TODO
+			}
+
+			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(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],
+					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]);
+			}
+			else
+			{
+				// TODO
+			}
+
+			prevBubble = barrierName;
+		}
+
+		slist.pushBackSprintf("\t\"%s\"[color=%s,style=bold];\n", &batchName[0], COLORS[batchIdx % 6]);
+		slist.pushBackSprintf("\t\"%s\"->\"%s\";\n", &prevBubble[0], &batchName[0]);
+		prevBubble = batchName;
+	}
+
+	slist.pushBackSprintf("}");
+
+	File file;
+	ANKI_CHECK(file.open(StringAuto(alloc).sprintf("%s/rgraph.dot", &path[0]).toCString(), FileOpenFlag::WRITE));
+	StringAuto final(alloc);
+	slist.join("\n", final);
+	ANKI_CHECK(file.writeText("%s", &final[0]));
+
+	return Error::NONE;
+}
+
 } // end namespace anki

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

@@ -233,6 +233,7 @@ private:
 	TextureInitInfo m_initInfo;
 	TexturePtr m_importedTex;
 	TextureUsageBit m_usage;
+	Array<char, MAX_GR_OBJECT_NAME_LENGTH + 1> m_name;
 };
 
 /// XXX
@@ -273,6 +274,14 @@ public:
 		RenderTarget rt;
 		rt.m_importedTex = tex;
 		rt.m_usage = usage;
+		const U len = name.getLength();
+		if(len)
+		{
+			ANKI_ASSERT(len <= MAX_GR_OBJECT_NAME_LENGTH);
+			memcpy(&rt.m_name[0], &name[0], len);
+		}
+		rt.m_name[len] = '\0';
+
 		m_renderTargets.emplaceBack(m_alloc, rt);
 		return m_renderTargets.getSize() - 1;
 	}
@@ -283,6 +292,13 @@ public:
 		RenderTarget rt;
 		rt.m_initInfo = initInf;
 		rt.m_usage = TextureUsageBit::NONE;
+		const U len = name.getLength();
+		if(len)
+		{
+			ANKI_ASSERT(len <= MAX_GR_OBJECT_NAME_LENGTH);
+			memcpy(&rt.m_name[0], &name[0], len);
+		}
+		rt.m_name[len] = '\0';
 		m_renderTargets.emplaceBack(m_alloc, rt);
 		return m_renderTargets.getSize() - 1;
 	}
@@ -365,17 +381,19 @@ private:
 	class Pass;
 	class Batch;
 	class RT;
-	class RTBarrier;
+	class Barrier;
 
 	TexturePtr getOrCreateRenderTarget(const TextureInitInfo& initInf);
 
-	/// Dump the dependency graph into a file.
-	ANKI_USE_RESULT Error dumpDependencyDotFile(const BakeContext& ctx, CString path) const;
-
 	static Bool passADependsOnB(BakeContext& ctx, const RenderPassBase& a, const RenderPassBase& b);
 	static Bool passHasUnmetDependencies(const BakeContext& ctx, U32 passIdx);
 
 	void setBatchBarriers(BakeContext& ctx) const;
+
+	/// Dump the dependency graph into a file.
+	ANKI_USE_RESULT Error dumpDependencyDotFile(const BakeContext& ctx, CString path) const;
+
+	static StringAuto textureUsageToStr(const BakeContext& ctx, TextureUsageBit usage);
 };
 /// @}
 

+ 2 - 2
tests/gr/Gr.cpp

@@ -1535,7 +1535,7 @@ ANKI_TEST(Gr, RenderGraph)
 {
 	COMMON_BEGIN()
 
-	StackAllocator<U8> alloc(allocAligned, nullptr, 2_KB);
+	StackAllocator<U8> alloc(allocAligned, nullptr, 1_MB);
 	RenderGraphDescription descr(alloc);
 	RenderGraphPtr rgraph = gr->newInstance<RenderGraph>();
 
@@ -1550,7 +1550,7 @@ ANKI_TEST(Gr, RenderGraph)
 	RenderTargetHandle smScratchRt = descr.newRenderTarget("sm_scratch", texInf);
 	{
 		GraphicsRenderPassInfo& pass = descr.newGraphicsRenderPass("SM");
-		pass.newConsumer({smScratchRt, TextureUsageBit::NONE});
+		pass.newConsumer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
 		pass.newProducer({smScratchRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE});
 	}