Browse Source

Add a global lock on vkCreateGraphicsPipeline due to driver bug in qualcomm GPUs

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
cd8d0306d0

+ 13 - 0
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -97,6 +97,10 @@ GrManagerImpl::~GrManagerImpl()
 	}
 
 	m_vkHandleToName.destroy(getAllocator());
+
+#if ANKI_PLATFORM_MOBILE
+	m_alloc.deleteInstance(m_globalCreatePipelineMtx);
+#endif
 }
 
 Error GrManagerImpl::init(const GrManagerInitInfo& init)
@@ -522,6 +526,15 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 	m_capabilities.m_shaderGroupHandleSize = m_rtPipelineProps.shaderGroupHandleSize;
 	m_capabilities.m_sbtRecordAlignment = m_rtPipelineProps.shaderGroupBaseAlignment;
 
+#if ANKI_PLATFORM_MOBILE
+	if(m_capabilities.m_gpuVendor == GpuVendor::QUALCOMM)
+	{
+		// Calling vkCreateGraphicsPipeline from multiple threads crashes qualcomm's compiler
+		ANKI_VK_LOGI("Enabling workaround for vkCreateGraphicsPipeline crashing when called from multiple threads");
+		m_globalCreatePipelineMtx = m_alloc.newInstance<Mutex>();
+	}
+#endif
+
 	return Error::NONE;
 }
 

+ 11 - 0
AnKi/Gr/Vulkan/GrManagerImpl.h

@@ -219,6 +219,13 @@ public:
 		return m_frameGarbageCollector;
 	}
 
+#if ANKI_PLATFORM_MOBILE
+	Mutex* getGlobalCreatePipelineMutex() const
+	{
+		return m_globalCreatePipelineMtx;
+	}
+#endif
+
 private:
 	U64 m_frame = 0;
 
@@ -323,6 +330,10 @@ private:
 
 	FrameGarbageCollector m_frameGarbageCollector;
 
+#if ANKI_PLATFORM_MOBILE
+	Mutex* m_globalCreatePipelineMtx = nullptr;
+#endif
+
 	ANKI_USE_RESULT Error initInternal(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initInstance(const GrManagerInitInfo& init);
 	ANKI_USE_RESULT Error initSurface(const GrManagerInitInfo& init);

+ 15 - 0
AnKi/Gr/Vulkan/Pipeline.cpp

@@ -469,7 +469,22 @@ void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline&
 
 	{
 		ANKI_TRACE_SCOPED_EVENT(VK_PIPELINE_CREATE);
+
+#if ANKI_PLATFORM_MOBILE
+		if(m_globalCreatePipelineMtx)
+		{
+			m_globalCreatePipelineMtx->lock();
+		}
+#endif
+
 		ANKI_VK_CHECKF(vkCreateGraphicsPipelines(m_dev, m_pplineCache, 1, &ci, nullptr, &pp.m_handle));
+
+#if ANKI_PLATFORM_MOBILE
+		if(m_globalCreatePipelineMtx)
+		{
+			m_globalCreatePipelineMtx->unlock();
+		}
+#endif
 	}
 
 	ANKI_TRACE_INC_COUNTER(VK_PIPELINES_CACHE_MISS, 1);

+ 12 - 1
AnKi/Gr/Vulkan/Pipeline.h

@@ -549,11 +549,19 @@ public:
 	{
 	}
 
-	void init(GrAllocator<U8> alloc, VkDevice dev, VkPipelineCache pplineCache)
+	void init(GrAllocator<U8> alloc, VkDevice dev, VkPipelineCache pplineCache
+#if ANKI_PLATFORM_MOBILE
+			  ,
+			  Mutex* globalCreatePipelineMtx
+#endif
+	)
 	{
 		m_alloc = alloc;
 		m_dev = dev;
 		m_pplineCache = pplineCache;
+#if ANKI_PLATFORM_MOBILE
+		m_globalCreatePipelineMtx = globalCreatePipelineMtx;
+#endif
 	}
 
 	void destroy();
@@ -571,6 +579,9 @@ private:
 
 	HashMap<U64, PipelineInternal, Hasher> m_pplines;
 	RWMutex m_pplinesMtx;
+#if ANKI_PLATFORM_MOBILE
+	Mutex* m_globalCreatePipelineMtx = nullptr;
+#endif
 };
 /// @}
 

+ 6 - 1
AnKi/Gr/Vulkan/ShaderProgramImpl.cpp

@@ -222,7 +222,12 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	{
 		m_graphics.m_pplineFactory = getAllocator().newInstance<PipelineFactory>();
 		m_graphics.m_pplineFactory->init(getGrManagerImpl().getAllocator(), getGrManagerImpl().getDevice(),
-										 getGrManagerImpl().getPipelineCache());
+										 getGrManagerImpl().getPipelineCache()
+#if ANKI_PLATFORM_MOBILE
+											 ,
+										 getGrManagerImpl().getGlobalCreatePipelineMutex()
+#endif
+		);
 	}
 
 	// Create the pipeline if compute