ソースを参照

Vulkan: Offscreen rendering

Panagiotis Christopoulos Charitos 9 年 前
コミット
b2df14e93e

+ 1 - 1
include/anki/gr/CommandBuffer.h

@@ -152,7 +152,7 @@ public:
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy);
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy);
 
 
 	/// Set depth offset and units.
 	/// Set depth offset and units.
-	void setPolygonOffset(F32 offset, F32 units);
+	void setPolygonOffset(F32 factor, F32 units);
 
 
 	/// Bind pipeline.
 	/// Bind pipeline.
 	void bindPipeline(PipelinePtr ppline);
 	void bindPipeline(PipelinePtr ppline);

+ 5 - 1
include/anki/gr/vulkan/CommandBufferImpl.h

@@ -54,6 +54,8 @@ public:
 
 
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy);
 	void setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy);
 
 
+	void setPolygonOffset(F32 factor, F32 units);
+
 	void bindPipeline(PipelinePtr ppline);
 	void bindPipeline(PipelinePtr ppline);
 
 
 	void beginRenderPass(FramebufferPtr fb);
 	void beginRenderPass(FramebufferPtr fb);
@@ -120,7 +122,7 @@ private:
 	Bool8 m_empty = true;
 	Bool8 m_empty = true;
 	Thread::Id m_tid = 0;
 	Thread::Id m_tid = 0;
 
 
-	Bool m_firstRpassDrawcall = true; ///< First drawcall in a renderpass.
+	U m_rpDrawcallCount = 0; ///< Number of drawcalls in renderpass.
 	FramebufferPtr m_activeFb;
 	FramebufferPtr m_activeFb;
 
 
 	/// @name cleanup_references
 	/// @name cleanup_references
@@ -147,6 +149,8 @@ private:
 	{
 	{
 		return m_activeFb.isCreated();
 		return m_activeFb.isCreated();
 	}
 	}
+
+	void beginRenderPassInternal();
 };
 };
 /// @}
 /// @}
 
 

+ 7 - 0
include/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -33,6 +33,13 @@ inline void CommandBufferImpl::setViewport(
 	vkCmdSetScissor(m_handle, 0, 1, &scissor);
 	vkCmdSetScissor(m_handle, 0, 1, &scissor);
 }
 }
 
 
+//==============================================================================
+inline void CommandBufferImpl::setPolygonOffset(F32 factor, F32 units)
+{
+	commandCommon();
+	vkCmdSetDepthBias(m_handle, units, 0.0, factor);
+}
+
 //==============================================================================
 //==============================================================================
 inline void CommandBufferImpl::setImageBarrier(VkPipelineStageFlags srcStage,
 inline void CommandBufferImpl::setImageBarrier(VkPipelineStageFlags srcStage,
 	VkAccessFlags srcAccess,
 	VkAccessFlags srcAccess,

+ 8 - 0
include/anki/gr/vulkan/FramebufferImpl.h

@@ -57,6 +57,12 @@ public:
 		return &m_clearVals[0];
 		return &m_clearVals[0];
 	}
 	}
 
 
+	void getAttachmentsSize(U32& width, U32& height) const
+	{
+		width = m_width;
+		height = m_height;
+	}
+
 private:
 private:
 	Array<VkFramebuffer, MAX_FRAMES_IN_FLIGHT> m_framebuffers = {{
 	Array<VkFramebuffer, MAX_FRAMES_IN_FLIGHT> m_framebuffers = {{
 		0,
 		0,
@@ -65,6 +71,8 @@ private:
 	Array<VkClearValue, MAX_COLOR_ATTACHMENTS + 1> m_clearVals;
 	Array<VkClearValue, MAX_COLOR_ATTACHMENTS + 1> m_clearVals;
 	Bool8 m_defaultFramebuffer = false;
 	Bool8 m_defaultFramebuffer = false;
 	U8 m_attachmentCount = 0;
 	U8 m_attachmentCount = 0;
+	Array<TexturePtr, MAX_COLOR_ATTACHMENTS + 1> m_refs;
+	U32 m_width = 0, m_height = 0;
 
 
 	ANKI_USE_RESULT Error initRenderPass(const FramebufferInitInfo& init);
 	ANKI_USE_RESULT Error initRenderPass(const FramebufferInitInfo& init);
 
 

+ 7 - 7
src/gr/gl/CommandBuffer.cpp

@@ -123,37 +123,37 @@ void CommandBuffer::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 class SetPolygonOffsetCommand final : public GlCommand
 class SetPolygonOffsetCommand final : public GlCommand
 {
 {
 public:
 public:
-	F32 m_offset;
+	F32 m_factor;
 	F32 m_units;
 	F32 m_units;
 
 
-	SetPolygonOffsetCommand(F32 offset, F32 units)
-		: m_offset(offset)
+	SetPolygonOffsetCommand(F32 factor, F32 units)
+		: m_factor(factor)
 		, m_units(units)
 		, m_units(units)
 	{
 	{
 	}
 	}
 
 
 	Error operator()(GlState& state)
 	Error operator()(GlState& state)
 	{
 	{
-		if(m_offset == 0.0 && m_units == 0.0)
+		if(m_factor == 0.0 && m_units == 0.0)
 		{
 		{
 			glDisable(GL_POLYGON_OFFSET_FILL);
 			glDisable(GL_POLYGON_OFFSET_FILL);
 		}
 		}
 		else
 		else
 		{
 		{
 			glEnable(GL_POLYGON_OFFSET_FILL);
 			glEnable(GL_POLYGON_OFFSET_FILL);
-			glPolygonOffset(m_offset, m_units);
+			glPolygonOffset(m_factor, m_units);
 		}
 		}
 
 
 		return ErrorCode::NONE;
 		return ErrorCode::NONE;
 	}
 	}
 };
 };
 
 
-void CommandBuffer::setPolygonOffset(F32 offset, F32 units)
+void CommandBuffer::setPolygonOffset(F32 factor, F32 units)
 {
 {
 #if ANKI_ASSERTS_ENABLED
 #if ANKI_ASSERTS_ENABLED
 	m_impl->m_dbg.m_polygonOffset = true;
 	m_impl->m_dbg.m_polygonOffset = true;
 #endif
 #endif
-	m_impl->pushBackNewCommand<SetPolygonOffsetCommand>(offset, units);
+	m_impl->pushBackNewCommand<SetPolygonOffsetCommand>(factor, units);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 2 - 1
src/gr/vulkan/CommandBuffer.cpp

@@ -65,8 +65,9 @@ void CommandBuffer::setViewport(U16 minx, U16 miny, U16 maxx, U16 maxy)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void CommandBuffer::setPolygonOffset(F32 offset, F32 units)
+void CommandBuffer::setPolygonOffset(F32 factor, F32 units)
 {
 {
+	m_impl->setPolygonOffset(factor, units);
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 42 - 34
src/gr/vulkan/CommandBufferImpl.cpp

@@ -133,7 +133,7 @@ void CommandBufferImpl::beginRenderPass(FramebufferPtr fb)
 	commandCommon();
 	commandCommon();
 	ANKI_ASSERT(!insideRenderPass());
 	ANKI_ASSERT(!insideRenderPass());
 
 
-	m_firstRpassDrawcall = true;
+	m_rpDrawcallCount = 0;
 	m_activeFb = fb;
 	m_activeFb = fb;
 
 
 	m_fbList.pushBack(m_alloc, fb);
 	m_fbList.pushBack(m_alloc, fb);
@@ -148,11 +148,48 @@ void CommandBufferImpl::endRenderPass()
 {
 {
 	commandCommon();
 	commandCommon();
 	ANKI_ASSERT(insideRenderPass());
 	ANKI_ASSERT(insideRenderPass());
+	ANKI_ASSERT(m_rpDrawcallCount > 0);
 
 
 	vkCmdEndRenderPass(m_handle);
 	vkCmdEndRenderPass(m_handle);
 	m_activeFb.reset(nullptr);
 	m_activeFb.reset(nullptr);
 }
 }
 
 
+//==============================================================================
+void CommandBufferImpl::beginRenderPassInternal()
+{
+	VkRenderPassBeginInfo bi = {};
+	bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+	FramebufferImpl& impl = m_activeFb->getImplementation();
+	bi.renderPass = impl.getRenderPassHandle();
+	bi.clearValueCount = impl.getAttachmentCount();
+	bi.pClearValues = impl.getClearValues();
+
+	if(!impl.isDefaultFramebuffer())
+	{
+		// Bind a non-default FB
+
+		bi.framebuffer = impl.getFramebufferHandle(0);
+
+		impl.getAttachmentsSize(
+			bi.renderArea.extent.width, bi.renderArea.extent.height);
+	}
+	else
+	{
+		// Bind the default FB
+		m_renderedToDefaultFb = true;
+
+		bi.framebuffer = impl.getFramebufferHandle(
+			getGrManagerImpl().getFrame() % MAX_FRAMES_IN_FLIGHT);
+
+		bi.renderArea.extent.width =
+			getGrManagerImpl().getDefaultSurfaceWidth();
+		bi.renderArea.extent.height =
+			getGrManagerImpl().getDefaultSurfaceHeight();
+	}
+
+	vkCmdBeginRenderPass(m_handle, &bi, VK_SUBPASS_CONTENTS_INLINE);
+}
+
 //==============================================================================
 //==============================================================================
 void CommandBufferImpl::drawcallCommon()
 void CommandBufferImpl::drawcallCommon()
 {
 {
@@ -165,41 +202,12 @@ void CommandBufferImpl::drawcallCommon()
 	m_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
 	m_subpassContents = VK_SUBPASS_CONTENTS_INLINE;
 #endif
 #endif
 
 
-	if(ANKI_UNLIKELY(m_firstRpassDrawcall))
+	if(ANKI_UNLIKELY(m_rpDrawcallCount == 0))
 	{
 	{
-		m_firstRpassDrawcall = false;
-
-		// Bind the framebuffer
-		VkRenderPassBeginInfo bi = {};
-		bi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
-		FramebufferImpl& impl = m_activeFb->getImplementation();
-		bi.renderPass = impl.getRenderPassHandle();
-		bi.clearValueCount = impl.getAttachmentCount();
-		bi.pClearValues = impl.getClearValues();
-
-		if(!impl.isDefaultFramebuffer())
-		{
-			bi.framebuffer = impl.getFramebufferHandle(0);
-
-			ANKI_ASSERT(0);
-			// TODO Get the render area from one of the attachments
-		}
-		else
-		{
-			// Bind the default FB
-			m_renderedToDefaultFb = true;
-
-			bi.framebuffer = impl.getFramebufferHandle(
-				getGrManagerImpl().getFrame() % MAX_FRAMES_IN_FLIGHT);
-
-			bi.renderArea.extent.width =
-				getGrManagerImpl().getDefaultSurfaceWidth();
-			bi.renderArea.extent.height =
-				getGrManagerImpl().getDefaultSurfaceHeight();
-		}
-
-		vkCmdBeginRenderPass(m_handle, &bi, VK_SUBPASS_CONTENTS_INLINE);
+		beginRenderPassInternal();
 	}
 	}
+
+	++m_rpDrawcallCount;
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 35 - 3
src/gr/vulkan/FramebufferImpl.cpp

@@ -178,8 +178,10 @@ Error FramebufferImpl::initFramebuffer(const FramebufferInitInfo& init)
 			VkImageView view = getGrManagerImpl().getDefaultSurfaceImageView(i);
 			VkImageView view = getGrManagerImpl().getDefaultSurfaceImageView(i);
 			ci.pAttachments = &view;
 			ci.pAttachments = &view;
 
 
-			ci.width = getGrManagerImpl().getDefaultSurfaceWidth();
-			ci.height = getGrManagerImpl().getDefaultSurfaceHeight();
+			m_width = getGrManagerImpl().getDefaultSurfaceWidth();
+			m_height = getGrManagerImpl().getDefaultSurfaceHeight();
+			ci.width = m_width;
+			ci.height = m_height;
 
 
 			ANKI_VK_CHECK(vkCreateFramebuffer(
 			ANKI_VK_CHECK(vkCreateFramebuffer(
 				getDevice(), &ci, nullptr, &m_framebuffers[i]));
 				getDevice(), &ci, nullptr, &m_framebuffers[i]));
@@ -187,7 +189,37 @@ Error FramebufferImpl::initFramebuffer(const FramebufferInitInfo& init)
 	}
 	}
 	else
 	else
 	{
 	{
-		ANKI_ASSERT(0 && "TODO");
+		Array<VkImageView, MAX_COLOR_ATTACHMENTS + 1> attachments;
+		U count = 0;
+
+		for(U i = 0; i < init.m_colorAttachmentCount; ++i)
+		{
+			attachments[count] = init.m_colorAttachments[i]
+									 .m_texture->getImplementation()
+									 .m_viewHandle;
+
+			m_refs[count++] = init.m_colorAttachments[i].m_texture;
+		}
+
+		if(hasDepthStencil)
+		{
+			attachments[count] =
+				init.m_depthStencilAttachment.m_texture->getImplementation()
+					.m_viewHandle;
+
+			m_refs[count++] = init.m_depthStencilAttachment.m_texture;
+		}
+
+		m_width = m_refs[0]->getImplementation().m_width;
+		m_height = m_refs[0]->getImplementation().m_height;
+		ci.width = m_width;
+		ci.height = m_height;
+
+		ci.pAttachments = &attachments[0];
+		ANKI_ASSERT(count == ci.attachmentCount);
+
+		ANKI_VK_CHECK(
+			vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_framebuffers[0]));
 	}
 	}
 
 
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;

+ 1 - 1
tests/gr/Gr.cpp

@@ -1006,7 +1006,7 @@ ANKI_TEST(Gr, DrawOffscreen)
 		const PixelFormat COL_FORMAT =
 		const PixelFormat COL_FORMAT =
 			PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 			PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM);
 		const PixelFormat DS_FORMAT =
 		const PixelFormat DS_FORMAT =
-			PixelFormat(ComponentFormat::D24, TransformFormat::FLOAT);
+			PixelFormat(ComponentFormat::D24, TransformFormat::UNORM);
 		const U TEX_SIZE = 256;
 		const U TEX_SIZE = 256;
 
 
 		TextureInitInfo init;
 		TextureInitInfo init;