diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 7ceb14afd7..47e04f12a0 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -312,6 +312,10 @@ bool GPU_GLES::IsReady() { return shaderManagerGL_->ContinuePrecompile(); } +void GPU_GLES::CancelReady() { + shaderManagerGL_->CancelPrecompile(); +} + void GPU_GLES::BuildReportingInfo() { GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); @@ -341,6 +345,7 @@ void GPU_GLES::DeviceLost() { // Simply drop all caches and textures. // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. + CancelReady(); shaderManagerGL_->DeviceLost(); textureCacheGL_->DeviceLost(); fragmentTestCache_.DeviceLost(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 9f70cbec16..9aa78825c1 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -39,6 +39,7 @@ public: void CheckGPUFeatures() override; bool IsReady() override; + void CancelReady() override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index bee0fad708..5a7aa94dbd 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -990,6 +990,10 @@ bool ShaderManagerGLES::ContinuePrecompile(float sliceTime) { return true; } +void ShaderManagerGLES::CancelPrecompile() { + diskCachePending_.Clear(); +} + void ShaderManagerGLES::Save(const std::string &filename) { if (!diskCacheDirty_) { return; diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 5dbfe43b4e..f5b9fa640b 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -179,6 +179,7 @@ public: void Load(const std::string &filename); bool ContinuePrecompile(float sliceTime = 1.0f / 60.0f); + void CancelPrecompile(); void Save(const std::string &filename); private: diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index d8b01f51a8..e7026973b4 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -107,9 +107,11 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { void GPU_Shutdown() { // Wait for IsReady, since it might be running on a thread. - // Potentially we could set a flag to try to early quit. - while (gpu && !gpu->IsReady()) { - sleep_ms(10); + if (gpu) { + gpu->CancelReady(); + while (!gpu->IsReady()) { + sleep_ms(10); + } } delete gpu; gpu = nullptr; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 63f6661594..ff7236fb91 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -77,6 +77,8 @@ public: bool IsReady() override { return true; } + void CancelReady() override { + } void Reinitialize() override; void BeginHostFrame() override; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 543f757a99..2cddc01055 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -169,6 +169,7 @@ public: // Initialization virtual bool IsReady() = 0; + virtual void CancelReady() = 0; virtual void InitClear() = 0; virtual void Reinitialize() = 0; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 9a94a6da18..6b81da93d1 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -18,6 +18,7 @@ #include #include "base/logging.h" +#include "base/timeutil.h" #include "profiler/profiler.h" #include "Common/ChunkFile.h" @@ -119,6 +120,10 @@ bool GPU_Vulkan::IsReady() { return shaderCacheLoaded_; } +void GPU_Vulkan::CancelReady() { + pipelineManager_->CancelCache(); +} + void GPU_Vulkan::LoadCache(std::string filename) { PSP_SetLoading("Loading shader cache..."); // Actually precompiled by IsReady() since we're single-threaded. @@ -492,6 +497,10 @@ void GPU_Vulkan::DestroyDeviceObjects() { } void GPU_Vulkan::DeviceLost() { + CancelReady(); + while (!IsReady()) { + sleep_ms(10); + } if (!shaderCachePath_.empty()) { SaveCache(shaderCachePath_); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index d4ce2151a2..42de6916c7 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -39,6 +39,7 @@ public: void CheckGPUFeatures() override; bool IsReady() override; + void CancelReady() override; // These are where we can reset command buffers etc. void BeginHostFrame() override; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 83cdf0ee28..837aec7ffe 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -709,7 +709,7 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha NOTICE_LOG(G3D, "Creating %d pipelines...", size); for (uint32_t i = 0; i < size; i++) { - if (failed) { + if (failed || cancelCache_) { break; } StoredVulkanPipelineKey key; @@ -742,3 +742,7 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha NOTICE_LOG(G3D, "Recreated Vulkan pipeline cache (%d pipelines).", (int)size); return true; } + +void PipelineManagerVulkan::CancelCache() { + cancelCache_ = true; +} diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 410e3f34ba..0cdb4a855a 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -98,10 +98,12 @@ public: // Saves data for faster creation next time. void SaveCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext); bool LoadCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout); + void CancelCache(); private: DenseHashMap pipelines_; VkPipelineCache pipelineCache_ = VK_NULL_HANDLE; VulkanContext *vulkan_; float lineWidth_ = 1.0f; + bool cancelCache_ = false; };