Try to prevent a weird shutdown race condition that I'm not sure can happen - but crash logs show it

This commit is contained in:
Henrik Rydgård 2023-09-18 16:42:22 +02:00
parent f4b0cddda3
commit 0bfd166200
3 changed files with 27 additions and 11 deletions

View File

@ -500,14 +500,20 @@ void VulkanRenderManager::CompileThreadFunc() {
}
}
void VulkanRenderManager::DrainCompileQueue() {
void VulkanRenderManager::DrainAndBlockCompileQueue() {
std::unique_lock<std::mutex> lock(compileMutex_);
compileBlocked_ = true;
compileCond_.notify_all();
while (!compileQueue_.empty()) {
queueRunner_.WaitForCompileNotification();
}
}
void VulkanRenderManager::ReleaseCompileQueue() {
std::unique_lock<std::mutex> lock(compileMutex_);
compileBlocked_ = false;
}
void VulkanRenderManager::ThreadFunc() {
SetCurrentThreadName("RenderMan");
while (true) {
@ -709,14 +715,12 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() {
}
VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, PipelineFlags pipelineFlags, uint32_t variantBitmask, VkSampleCountFlagBits sampleCount, bool cacheLoad, const char *tag) {
VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline(pipelineFlags, tag);
if (!desc->vertexShader || !desc->fragmentShader) {
ERROR_LOG(G3D, "Can't create graphics pipeline with missing vs/ps: %p %p", desc->vertexShader, desc->fragmentShader);
delete pipeline;
return nullptr;
}
VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline(pipelineFlags, tag);
pipeline->desc = desc;
pipeline->desc->AddRef();
if (curRenderStep_ && !cacheLoad) {
@ -733,7 +737,11 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe
VKRRenderPassStoreAction::STORE, VKRRenderPassStoreAction::DONT_CARE, VKRRenderPassStoreAction::DONT_CARE,
};
VKRRenderPass *compatibleRenderPass = queueRunner_.GetRenderPass(key);
compileMutex_.lock();
std::lock_guard<std::mutex> lock(compileMutex_);
if (compileBlocked_) {
delete pipeline;
return nullptr;
}
bool needsCompile = false;
for (size_t i = 0; i < (size_t)RenderPassType::TYPE_COUNT; i++) {
if (!(variantBitmask & (1 << i)))
@ -757,18 +765,19 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe
}
if (needsCompile)
compileCond_.notify_one();
compileMutex_.unlock();
}
return pipeline;
}
VKRComputePipeline *VulkanRenderManager::CreateComputePipeline(VKRComputePipelineDesc *desc) {
std::lock_guard<std::mutex> lock(compileMutex_);
if (compileBlocked_) {
return nullptr;
}
VKRComputePipeline *pipeline = new VKRComputePipeline();
pipeline->desc = desc;
compileMutex_.lock();
compileQueue_.push_back(CompileQueueEntry(pipeline));
compileCond_.notify_one();
compileMutex_.unlock();
return pipeline;
}
@ -814,7 +823,7 @@ void VulkanRenderManager::EndCurRenderStep() {
compileMutex_.lock();
bool needsCompile = false;
for (VKRGraphicsPipeline *pipeline : pipelinesToCheck_) {
if (!pipeline) {
if (!pipeline || compileBlocked_) {
// Not good, but let's try not to crash.
continue;
}

View File

@ -455,7 +455,8 @@ public:
}
void ResetStats();
void DrainCompileQueue();
void DrainAndBlockCompileQueue();
void ReleaseCompileQueue();
private:
void EndCurRenderStep();
@ -527,6 +528,7 @@ private:
std::condition_variable compileCond_;
std::mutex compileMutex_;
std::vector<CompileQueueEntry> compileQueue_;
bool compileBlocked_ = false;
// Thread for measuring presentation delay.
std::thread presentWaitThread_;

View File

@ -182,7 +182,7 @@ void GPU_Vulkan::SaveCache(const Path &filename) {
GPU_Vulkan::~GPU_Vulkan() {
if (draw_) {
VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
rm->DrainCompileQueue();
rm->DrainAndBlockCompileQueue();
}
SaveCache(shaderCachePath_);
@ -193,6 +193,11 @@ GPU_Vulkan::~GPU_Vulkan() {
delete pipelineManager_;
// other managers are deleted in ~GPUCommonHW.
if (draw_) {
VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
rm->ReleaseCompileQueue();
}
}
u32 GPU_Vulkan::CheckGPUFeatures() const {