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

Add a compute clear in the renderer

Panagiotis Christopoulos Charitos 7 лет назад
Родитель
Сommit
e87c12d74f

+ 26 - 0
shaders/ClearTextureCompute.glslp

@@ -0,0 +1,26 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+// A slow compute program to clear an image with a contant color
+
+#pragma anki start comp
+#include <shaders/Common.glsl>
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+
+struct PushConsts
+{
+	Vec4 m_clearColor;
+};
+ANKI_PUSH_CONSTANTS(PushConsts, u_regs);
+
+layout(ANKI_IMAGE_BINDING(0, 0)) uniform writeonly image2D u_img;
+
+void main()
+{
+	imageStore(u_img, IVec2(gl_GlobalInvocationID.xy), u_regs.m_clearColor);
+}
+
+#pragma anki end

+ 4 - 1
src/anki/gr/GrObject.cpp

@@ -22,7 +22,10 @@ GrObject::GrObject(GrManager* manager, GrObjectType type, CString name)
 	}
 	else
 	{
-		m_name[0] = '\0';
+		m_name[0] = 'N';
+		m_name[1] = '/';
+		m_name[2] = 'A';
+		m_name[3] = '\0';
 	}
 }
 

+ 7 - 0
src/anki/gr/vulkan/TextureImpl.cpp

@@ -16,6 +16,13 @@ namespace anki
 
 TextureImpl::~TextureImpl()
 {
+#if ANKI_ASSERTS_ENABLED
+	if(m_usage != m_usedFor)
+	{
+		ANKI_VK_LOGW("Texture %s hasn't been used in all types of usages", getName().cstr());
+	}
+#endif
+
 	for(auto it : m_viewsMap)
 	{
 		if(it != VK_NULL_HANDLE)

+ 9 - 0
src/anki/gr/vulkan/TextureImpl.h

@@ -93,6 +93,10 @@ public:
 
 	Bool usageValid(TextureUsageBit usage) const
 	{
+#if ANKI_ASSERTS_ENABLED
+		LockGuard<SpinLock> lock(m_usedForMtx);
+		m_usedFor |= usage;
+#endif
 		return (usage & m_usage) == usage;
 	}
 
@@ -146,6 +150,11 @@ private:
 
 	VkDeviceMemory m_dedicatedMem = VK_NULL_HANDLE;
 
+#if ANKI_ASSERTS_ENABLED
+	mutable TextureUsageBit m_usedFor = TextureUsageBit::NONE;
+	mutable SpinLock m_usedForMtx;
+#endif
+
 	ANKI_USE_RESULT static VkFormatFeatureFlags calcFeatures(const TextureInitInfo& init);
 
 	ANKI_USE_RESULT static VkImageCreateFlags calcCreateFlags(const TextureInitInfo& init);

+ 78 - 34
src/anki/renderer/Renderer.cpp

@@ -178,6 +178,8 @@ Error Renderer::initInternal(const ConfigSet& config)
 
 	initJitteredMats();
 
+	ANKI_CHECK(m_resources->loadResource("shaders/ClearTextureCompute.glslp", m_clearTexComputeProg));
+
 	return Error::NONE;
 }
 
@@ -372,12 +374,26 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, cons
 
 	const U faceCount = (inf.m_type == TextureType::CUBE || inf.m_type == TextureType::CUBE_ARRAY) ? 6 : 1;
 
+	Bool useCompute = false;
+	if(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE))
+	{
+		useCompute = false;
+	}
+	else if(!!(inf.m_usage & TextureUsageBit::IMAGE_COMPUTE_WRITE))
+	{
+		useCompute = true;
+	}
+	else
+	{
+		ANKI_ASSERT(!"Can't handle that");
+	}
+
 	// Create tex
 	TexturePtr tex = m_gr->newTexture(inf);
 
 	// Clear all surfaces
 	CommandBufferInitInfo cmdbinit;
-	cmdbinit.m_flags = CommandBufferFlag::GRAPHICS_WORK;
+	cmdbinit.m_flags = (useCompute) ? CommandBufferFlag::COMPUTE_WORK : CommandBufferFlag::GRAPHICS_WORK;
 	if((inf.m_mipmapCount * faceCount * inf.m_layerCount * 4) < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
 	{
 		cmdbinit.m_flags |= CommandBufferFlag::SMALL_BATCH;
@@ -392,55 +408,83 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf, cons
 			{
 				TextureSurfaceInfo surf(mip, 0, face, layer);
 
-				FramebufferInitInfo fbInit("RendererClearRT");
-				Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> colUsage = {};
-				TextureUsageBit dsUsage = TextureUsageBit::NONE;
-
-				if(formatIsDepthStencil(inf.m_format))
+				if(!useCompute)
 				{
-					DepthStencilAspectBit aspect = DepthStencilAspectBit::NONE;
-					if(formatIsDepth(inf.m_format))
+					FramebufferInitInfo fbInit("RendererClearRT");
+					Array<TextureUsageBit, MAX_COLOR_ATTACHMENTS> colUsage = {};
+					TextureUsageBit dsUsage = TextureUsageBit::NONE;
+
+					if(formatIsDepthStencil(inf.m_format))
 					{
-						aspect |= DepthStencilAspectBit::DEPTH;
-					}
+						DepthStencilAspectBit aspect = DepthStencilAspectBit::NONE;
+						if(formatIsDepth(inf.m_format))
+						{
+							aspect |= DepthStencilAspectBit::DEPTH;
+						}
+
+						if(formatIsStencil(inf.m_format))
+						{
+							aspect |= DepthStencilAspectBit::STENCIL;
+						}
+
+						TextureViewPtr view = getGrManager().newTextureView(TextureViewInitInfo(tex, surf, aspect));
+
+						fbInit.m_depthStencilAttachment.m_textureView = view;
+						fbInit.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
+						fbInit.m_depthStencilAttachment.m_stencilLoadOperation = AttachmentLoadOperation::CLEAR;
+						fbInit.m_depthStencilAttachment.m_clearValue = clearVal;
 
-					if(formatIsStencil(inf.m_format))
+						dsUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
+					}
+					else
 					{
-						aspect |= DepthStencilAspectBit::STENCIL;
+						TextureViewPtr view = getGrManager().newTextureView(TextureViewInitInfo(tex, surf));
+
+						fbInit.m_colorAttachmentCount = 1;
+						fbInit.m_colorAttachments[0].m_textureView = view;
+						fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
+						fbInit.m_colorAttachments[0].m_clearValue = clearVal;
+
+						colUsage[0] = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 					}
+					FramebufferPtr fb = m_gr->newFramebuffer(fbInit);
 
-					TextureViewPtr view = getGrManager().newTextureView(TextureViewInitInfo(tex, surf, aspect));
+					cmdb->setTextureSurfaceBarrier(
+						tex, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, surf);
 
-					fbInit.m_depthStencilAttachment.m_textureView = view;
-					fbInit.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
-					fbInit.m_depthStencilAttachment.m_stencilLoadOperation = AttachmentLoadOperation::CLEAR;
-					fbInit.m_depthStencilAttachment.m_clearValue = clearVal;
+					cmdb->beginRenderPass(fb, colUsage, dsUsage);
+					cmdb->endRenderPass();
 
-					dsUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
+					if(!!inf.m_initialUsage)
+					{
+						cmdb->setTextureSurfaceBarrier(
+							tex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, inf.m_initialUsage, surf);
+					}
 				}
 				else
 				{
-					TextureViewPtr view = getGrManager().newTextureView(TextureViewInitInfo(tex, surf));
+					// Compute
+					const ShaderProgramResourceVariant* variant;
+					m_clearTexComputeProg->getOrCreateVariant(variant);
 
-					fbInit.m_colorAttachmentCount = 1;
-					fbInit.m_colorAttachments[0].m_textureView = view;
-					fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
-					fbInit.m_colorAttachments[0].m_clearValue = clearVal;
+					cmdb->bindShaderProgram(variant->getProgram());
 
-					colUsage[0] = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
-				}
-				FramebufferPtr fb = m_gr->newFramebuffer(fbInit);
+					Vec4 clearColorUni(&clearVal.m_colorf[0]);
+					cmdb->setPushConstants(&clearColorUni, sizeof(clearColorUni));
 
-				cmdb->setTextureSurfaceBarrier(
-					tex, TextureUsageBit::NONE, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, surf);
-
-				cmdb->beginRenderPass(fb, colUsage, dsUsage);
-				cmdb->endRenderPass();
+					TextureViewPtr view = getGrManager().newTextureView(TextureViewInitInfo(tex, surf));
+					cmdb->bindImage(0, 0, view);
 
-				if(!!inf.m_initialUsage)
-				{
 					cmdb->setTextureSurfaceBarrier(
-						tex, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, inf.m_initialUsage, surf);
+						tex, TextureUsageBit::NONE, TextureUsageBit::IMAGE_COMPUTE_WRITE, surf);
+
+					cmdb->dispatchCompute(tex->getWidth() >> mip, tex->getHeight() >> mip, 1);
+
+					if(!!inf.m_initialUsage)
+					{
+						cmdb->setTextureSurfaceBarrier(
+							tex, TextureUsageBit::IMAGE_COMPUTE_WRITE, inf.m_initialUsage, surf);
+					}
 				}
 			}
 		}

+ 2 - 0
src/anki/renderer/Renderer.h

@@ -394,6 +394,8 @@ private:
 	SamplerPtr m_trilinearRepeatSampler;
 	SamplerPtr m_nearesetNearestSampler;
 
+	ShaderProgramResourcePtr m_clearTexComputeProg;
+
 	RendererStats m_stats;
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);