浏览代码

Vulkan: Bug fixes

Panagiotis Christopoulos Charitos 8 年之前
父节点
当前提交
b06f9774c4

+ 3 - 0
src/anki/gr/Common.h

@@ -178,6 +178,9 @@ const U MAX_DESCRIPTOR_SETS = 2; ///< Groups that can be bound at the same time.
 
 const U MAX_GR_OBJECT_NAME_LENGTH = 15;
 
+/// The number of commands in a command buffer that make it a small batch command buffer.
+const U COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS = 100;
+
 /// The base of all init infos for GR.
 class GrBaseInitInfo
 {

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

@@ -316,6 +316,8 @@ public:
 	}
 };
 
+static_assert(sizeof(PixelFormat) == 2, "Need it to be packed");
+
 /// Occlusion query result bit.
 enum class OcclusionQueryResultBit : U8
 {

+ 10 - 0
src/anki/gr/vulkan/BufferImpl.cpp

@@ -207,6 +207,11 @@ VkPipelineStageFlags BufferImpl::computePplineStage(BufferUsageBit usage)
 		stageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
 	}
 
+	if(!!(usage & (BufferUsageBit::QUERY_RESULT)))
+	{
+		stageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT;
+	}
+
 	ANKI_ASSERT(stageMask);
 	return stageMask;
 }
@@ -265,6 +270,11 @@ VkAccessFlags BufferImpl::computeAccessMask(BufferUsageBit usage)
 		mask |= VK_ACCESS_TRANSFER_READ_BIT;
 	}
 
+	if(!!(usage & BufferUsageBit::QUERY_RESULT))
+	{
+		mask |= VK_ACCESS_TRANSFER_WRITE_BIT;
+	}
+
 	ANKI_ASSERT(mask);
 	return mask;
 }

+ 19 - 6
src/anki/gr/vulkan/CommandBufferFactory.cpp

@@ -56,7 +56,7 @@ void CommandBufferThreadAllocator::destroyList(IntrusiveList<MicroCommandBuffer>
 	}
 }
 
-void CommandBufferThreadAllocator::destroy()
+void CommandBufferThreadAllocator::destroyLists()
 {
 	for(U i = 0; i < 2; ++i)
 	{
@@ -64,15 +64,19 @@ void CommandBufferThreadAllocator::destroy()
 		{
 			CmdbType& type = m_types[i][j];
 
+			destroyList(type.m_deletedCmdbs);
 			destroyList(type.m_readyCmdbs);
 			destroyList(type.m_inUseCmdbs);
-			destroyList(type.m_deletedCmdbs);
 		}
 	}
+}
 
+void CommandBufferThreadAllocator::destroy()
+{
 	if(m_pool)
 	{
 		vkDestroyCommandPool(m_factory->m_dev, m_pool, nullptr);
+		m_pool = {};
 	}
 }
 
@@ -168,7 +172,7 @@ Error CommandBufferThreadAllocator::newCommandBuffer(CommandBufferFlag cmdbFlags
 		MicroCommandBuffer* newCmdb = getAllocator().newInstance<MicroCommandBuffer>(this);
 		newCmdb->m_fastAlloc = StackAllocator<U8>(m_factory->m_alloc.getMemoryPool().getAllocationCallback(),
 			m_factory->m_alloc.getMemoryPool().getAllocationCallbackUserData(),
-			(smallBatch) ? (1 * 1024) : (10 * 1024),
+			(smallBatch) ? (1024 * 1024) : (1024 * 1024),
 			2.0f);
 
 		newCmdb->m_handle = cmdb;
@@ -213,10 +217,19 @@ Error CommandBufferFactory::init(GrAllocator<U8> alloc, VkDevice dev, uint32_t q
 
 void CommandBufferFactory::destroy()
 {
-	for(CommandBufferThreadAllocator* alloc : m_threadAllocs)
+	// Run 2 times because destroyLists() populates other allocators' lists
+	for(U i = 0; i < 2; ++i)
+	{
+		for(CommandBufferThreadAllocator* alloc : m_threadAllocs)
+		{
+			alloc->destroyLists();
+		}
+	}
+
+	for(CommandBufferThreadAllocator* talloc : m_threadAllocs)
 	{
-		alloc->destroy();
-		m_alloc.deleteInstance(alloc);
+		talloc->destroy();
+		m_alloc.deleteInstance(talloc);
 	}
 
 	m_threadAllocs.destroy(m_alloc);

+ 1 - 0
src/anki/gr/vulkan/CommandBufferFactory.h

@@ -142,6 +142,7 @@ private:
 	Array2d<CmdbType, 2, 2> m_types;
 
 	void destroyList(IntrusiveList<MicroCommandBuffer>& list);
+	void destroyLists();
 };
 
 /// Command bufffer object recycler.

+ 5 - 5
src/anki/gr/vulkan/CommandBufferImpl.cpp

@@ -31,20 +31,20 @@ CommandBufferImpl::~CommandBufferImpl()
 	{
 		ANKI_VK_LOGW("Command buffer was not flushed");
 	}
-	
+
 #if ANKI_EXTRA_CHECKS
 	if(!!(m_flags & CommandBufferFlag::SMALL_BATCH))
 	{
-		if(m_commandCount > 20)
+		if(m_commandCount > COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS * 2)
 		{
-			ANKI_VK_LOGW("Command buffer has too many commands");
+			ANKI_VK_LOGW("Command buffer has too many commands: %u", U(m_commandCount));
 		}
 	}
 	else
 	{
-		if(m_commandCount <= 20)
+		if(m_commandCount <= COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS / 2)
 		{
-			ANKI_VK_LOGW("Command buffer has too few commands");
+			ANKI_VK_LOGW("Command buffer has too few commands: %u", U(m_commandCount));
 		}
 	}
 #endif

+ 2 - 2
src/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -553,11 +553,11 @@ inline void CommandBufferImpl::commandCommon()
 
 	ANKI_ASSERT(!m_finalized);
 	ANKI_ASSERT(m_handle);
-	
+
 #if ANKI_EXTRA_CHECKS
 	++m_commandCount;
 #endif
-	
+
 	m_empty = false;
 
 	if(ANKI_UNLIKELY(!m_beganRecording))

+ 1 - 1
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -117,7 +117,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	ANKI_CHECK(m_pplineCache.init(m_device, m_physicalDevice, init.m_cacheDirectory, *init.m_config, getAllocator()));
 
 	ANKI_CHECK(initMemory(*init.m_config));
-	
+
 	ANKI_CHECK(m_cmdbFactory.init(getAllocator(), m_device, m_queueIdx));
 
 	for(PerFrame& f : m_perFrame)

+ 1 - 1
src/anki/gr/vulkan/Pipeline.cpp

@@ -316,7 +316,7 @@ const VkGraphicsPipelineCreateInfo& PipelineStateTracker::updatePipelineCreateIn
 		{
 			ANKI_ASSERT(m_shaderColorAttachmentWritemask.get(i) && "No gaps are allowed");
 			VkPipelineColorBlendAttachmentState& out = m_ci.m_colAttachments[i];
-			const ColorAttachmentStateInfo& in = m_state.m_color.m_attachments[i];
+			const PPColorAttachmentStateInfo& in = m_state.m_color.m_attachments[i];
 
 			out.blendEnable = !blendingDisabled(in.m_srcBlendFactorRgb,
 				in.m_dstBlendFactorRgb,

+ 40 - 36
src/anki/gr/vulkan/Pipeline.h

@@ -18,68 +18,69 @@ namespace anki
 /// @addtogroup vulkan
 /// @{
 
-class VertexBufferBinding
+/// @note Non copyable because that complicates the hashing.
+class PPVertexBufferBinding : public NonCopyable
 {
 public:
 	PtrSize m_stride = MAX_PTR_SIZE; ///< Vertex stride.
 	VertexStepRate m_stepRate = VertexStepRate::VERTEX;
 
-	Bool operator==(const VertexBufferBinding& b) const
+	Bool operator==(const PPVertexBufferBinding& b) const
 	{
 		return m_stride == b.m_stride && m_stepRate == b.m_stepRate;
 	}
 
-	Bool operator!=(const VertexBufferBinding& b) const
+	Bool operator!=(const PPVertexBufferBinding& b) const
 	{
 		return !(*this == b);
 	}
 };
 
-class VertexAttributeBinding
+class PPVertexAttributeBinding : public NonCopyable
 {
 public:
-	PixelFormat m_format;
 	PtrSize m_offset = 0;
+	PixelFormat m_format;
 	U8 m_binding = 0;
 
-	Bool operator==(const VertexAttributeBinding& b) const
+	Bool operator==(const PPVertexAttributeBinding& b) const
 	{
 		return m_format == b.m_format && m_offset == b.m_offset && m_binding == b.m_binding;
 	}
 
-	Bool operator!=(const VertexAttributeBinding& b) const
+	Bool operator!=(const PPVertexAttributeBinding& b) const
 	{
 		return !(*this == b);
 	}
 };
 
-class VertexStateInfo
+class PPVertexStateInfo : public NonCopyable
 {
 public:
-	Array<VertexBufferBinding, MAX_VERTEX_ATTRIBUTES> m_bindings;
-	Array<VertexAttributeBinding, MAX_VERTEX_ATTRIBUTES> m_attributes;
+	Array<PPVertexBufferBinding, MAX_VERTEX_ATTRIBUTES> m_bindings;
+	Array<PPVertexAttributeBinding, MAX_VERTEX_ATTRIBUTES> m_attributes;
 };
 
-class InputAssemblerStateInfo
+class PPInputAssemblerStateInfo : public NonCopyable
 {
 public:
 	PrimitiveTopology m_topology = PrimitiveTopology::TRIANGLES;
 	Bool8 m_primitiveRestartEnabled = false;
 };
 
-class TessellationStateInfo
+class PPTessellationStateInfo : public NonCopyable
 {
 public:
 	U32 m_patchControlPointCount = 3;
 };
 
-class ViewportStateInfo
+class PPViewportStateInfo : public NonCopyable
 {
 public:
 	Bool8 m_scissorEnabled = false;
 };
 
-class RasterizerStateInfo
+class PPRasterizerStateInfo : public NonCopyable
 {
 public:
 	FillMode m_fillMode = FillMode::SOLID;
@@ -88,17 +89,17 @@ public:
 	F32 m_depthBiasSlopeFactor = 0.0;
 };
 
-class DepthStateInfo
+class PPDepthStateInfo : public NonCopyable
 {
 public:
 	Bool8 m_depthWriteEnabled = true;
 	CompareOperation m_depthCompareFunction = CompareOperation::LESS;
 };
 
-class StencilStateInfo
+class PPStencilStateInfo : public NonCopyable
 {
 public:
-	class S
+	class S : public NonCopyable
 	{
 	public:
 		StencilOperation m_stencilFailOperation = StencilOperation::KEEP;
@@ -110,7 +111,7 @@ public:
 	Array<S, 2> m_face;
 };
 
-class ColorAttachmentStateInfo
+class PPColorAttachmentStateInfo : public NonCopyable
 {
 public:
 	BlendFactor m_srcBlendFactorRgb = BlendFactor::ONE;
@@ -122,14 +123,14 @@ public:
 	ColorBit m_channelWriteMask = ColorBit::ALL;
 };
 
-class ColorStateInfo
+class PPColorStateInfo : public NonCopyable
 {
 public:
 	Bool8 m_alphaToCoverageEnabled = false;
-	Array<ColorAttachmentStateInfo, MAX_COLOR_ATTACHMENTS> m_attachments;
+	Array<PPColorAttachmentStateInfo, MAX_COLOR_ATTACHMENTS> m_attachments;
 };
 
-class PipelineInfoState
+class PipelineInfoState : public NonCopyable
 {
 public:
 	PipelineInfoState()
@@ -154,18 +155,18 @@ public:
 	}
 
 	ShaderProgramPtr m_prog;
-	VertexStateInfo m_vertex;
-	InputAssemblerStateInfo m_inputAssembler;
-	TessellationStateInfo m_tessellation;
-	ViewportStateInfo m_viewport;
-	RasterizerStateInfo m_rasterizer;
-	DepthStateInfo m_depth;
-	StencilStateInfo m_stencil;
-	ColorStateInfo m_color;
+	PPVertexStateInfo m_vertex;
+	PPInputAssemblerStateInfo m_inputAssembler;
+	PPTessellationStateInfo m_tessellation;
+	PPViewportStateInfo m_viewport;
+	PPRasterizerStateInfo m_rasterizer;
+	PPDepthStateInfo m_depth;
+	PPStencilStateInfo m_stencil;
+	PPColorStateInfo m_color;
 };
 
 /// Track changes in the static state.
-class PipelineStateTracker
+class PipelineStateTracker : public NonCopyable
 {
 public:
 	PipelineStateTracker()
@@ -174,12 +175,13 @@ public:
 
 	void bindVertexBuffer(U32 binding, PtrSize stride, VertexStepRate stepRate)
 	{
-		VertexBufferBinding b;
+		PPVertexBufferBinding b;
 		b.m_stride = stride;
 		b.m_stepRate = stepRate;
 		if(m_state.m_vertex.m_bindings[binding] != b)
 		{
-			m_state.m_vertex.m_bindings[binding] = b;
+			m_state.m_vertex.m_bindings[binding].m_stride = b.m_stride;
+			m_state.m_vertex.m_bindings[binding].m_stepRate = b.m_stepRate;
 			m_dirty.m_vertBindings.set(binding);
 		}
 		m_set.m_vertBindings.set(binding);
@@ -187,13 +189,15 @@ public:
 
 	void setVertexAttribute(U32 location, U32 buffBinding, const PixelFormat& fmt, PtrSize relativeOffset)
 	{
-		VertexAttributeBinding b;
+		PPVertexAttributeBinding b;
 		b.m_binding = buffBinding;
 		b.m_format = fmt;
 		b.m_offset = relativeOffset;
 		if(m_state.m_vertex.m_attributes[location] != b)
 		{
-			m_state.m_vertex.m_attributes[location] = b;
+			m_state.m_vertex.m_attributes[location].m_binding = buffBinding;
+			m_state.m_vertex.m_attributes[location].m_format = fmt;
+			m_state.m_vertex.m_attributes[location].m_offset = relativeOffset;
 			m_dirty.m_attribs.set(location);
 		}
 		m_set.m_attribs.set(location);
@@ -318,7 +322,7 @@ public:
 
 	void setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
 	{
-		ColorAttachmentStateInfo& c = m_state.m_color.m_attachments[attachment];
+		PPColorAttachmentStateInfo& c = m_state.m_color.m_attachments[attachment];
 		if(c.m_srcBlendFactorRgb != srcRgb || c.m_dstBlendFactorRgb != dstRgb || c.m_srcBlendFactorA != srcA
 			|| c.m_dstBlendFactorA != dstA)
 		{
@@ -332,7 +336,7 @@ public:
 
 	void setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
 	{
-		ColorAttachmentStateInfo& c = m_state.m_color.m_attachments[attachment];
+		PPColorAttachmentStateInfo& c = m_state.m_color.m_attachments[attachment];
 		if(c.m_blendFunctionRgb != funcRgb || c.m_blendFunctionA != funcA)
 		{
 			c.m_blendFunctionRgb = funcRgb;

+ 4 - 0
src/anki/renderer/Fs.cpp

@@ -125,6 +125,10 @@ Error Fs::buildCommandBuffers(RenderingContext& ctx, U threadId, U threadCount)
 	// Create the command buffer and set some state
 	CommandBufferInitInfo cinf;
 	cinf.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
+	if(end - start < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
+	{
+		cinf.m_flags |= CommandBufferFlag::SMALL_BATCH;
+	}
 	cinf.m_framebuffer = m_fb;
 	CommandBufferPtr cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 	ctx.m_fs.m_commandBuffers[threadId] = cmdb;

+ 4 - 0
src/anki/renderer/Ms.cpp

@@ -116,6 +116,10 @@ Error Ms::buildCommandBuffers(RenderingContext& ctx, U threadId, U threadCount)
 		// Create the command buffer
 		CommandBufferInitInfo cinf;
 		cinf.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
+		if(end - start < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
+		{
+			cinf.m_flags |= CommandBufferFlag::SMALL_BATCH;
+		}
 		cinf.m_framebuffer = m_fb;
 		CommandBufferPtr cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 		ctx.m_ms.m_commandBuffers[threadId] = cmdb;

+ 6 - 2
src/anki/renderer/Renderer.cpp

@@ -441,16 +441,20 @@ TexturePtr Renderer::createAndClearRenderTarget(const TextureInitInfo& inf)
 {
 	ANKI_ASSERT(!!(inf.m_usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 
+	const U faceCount = (inf.m_type == TextureType::CUBE || inf.m_type == TextureType::CUBE_ARRAY) ? 6 : 1;
+
 	// Create tex
 	TexturePtr tex = m_gr->newInstance<Texture>(inf);
 
 	// Clear all surfaces
 	CommandBufferInitInfo cmdbinit;
 	cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::GRAPHICS_WORK;
+	if((inf.m_mipmapsCount * faceCount * inf.m_layerCount * 4) < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
+	{
+		cmdbinit.m_flags |= CommandBufferFlag::SMALL_BATCH;
+	}
 	CommandBufferPtr cmdb = m_gr->newInstance<CommandBuffer>(cmdbinit);
 
-	const U faceCount = (inf.m_type == TextureType::CUBE || inf.m_type == TextureType::CUBE_ARRAY) ? 6 : 1;
-
 	for(U mip = 0; mip < inf.m_mipmapsCount; ++mip)
 	{
 		for(U face = 0; face < faceCount; ++face)

+ 8 - 0
src/anki/renderer/Sm.cpp

@@ -271,6 +271,10 @@ Error Sm::doSpotLight(SceneNode& light, CommandBufferPtr& cmdb, FramebufferPtr&
 	CommandBufferInitInfo cinf;
 	cinf.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
 	cinf.m_framebuffer = fb;
+	if(end - start < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
+	{
+		cinf.m_flags |= CommandBufferFlag::SMALL_BATCH;
+	}
 	cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 
 	// Inform on Rts
@@ -309,6 +313,10 @@ Error Sm::doOmniLight(
 		{
 			CommandBufferInitInfo cinf;
 			cinf.m_flags = CommandBufferFlag::SECOND_LEVEL | CommandBufferFlag::GRAPHICS_WORK;
+			if(end - start < COMMAND_BUFFER_SMALL_BATCH_MAX_COMMANDS)
+			{
+				cinf.m_flags |= CommandBufferFlag::SMALL_BATCH;
+			}
 			cinf.m_framebuffer = fbs[frCount];
 			cmdbs[frCount] = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 

+ 6 - 2
src/anki/resource/Mesh.cpp

@@ -47,7 +47,9 @@ Error MeshLoadTask::operator()(AsyncLoaderTaskContext& ctx)
 		if(data)
 		{
 			memcpy(data, m_loader.getVertexData(), m_loader.getVertexDataSize());
-			cmdb = gr.newInstance<CommandBuffer>(CommandBufferInitInfo());
+			CommandBufferInitInfo cmdbinit;
+			cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH;
+			cmdb = gr.newInstance<CommandBuffer>(cmdbinit);
 
 			cmdb->setBufferBarrier(
 				m_vertBuff, BufferUsageBit::VERTEX, BufferUsageBit::BUFFER_UPLOAD_DESTINATION, 0, MAX_PTR_SIZE);
@@ -78,7 +80,9 @@ Error MeshLoadTask::operator()(AsyncLoaderTaskContext& ctx)
 
 			if(!cmdb)
 			{
-				cmdb = gr.newInstance<CommandBuffer>(CommandBufferInitInfo());
+				CommandBufferInitInfo cmdbinit;
+				cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH;
+				cmdb = gr.newInstance<CommandBuffer>(cmdbinit);
 			}
 
 			cmdb->setBufferBarrier(