GPU: Cancel shader preload on shutdown/lost.

Otherwise, we could've ended up with shaders loading after or during the
lost event, and dense hash map corruption.
This commit is contained in:
Unknown W. Brackets 2018-10-30 20:32:12 -07:00
parent dcf71fc43f
commit 40ca49d0e3
11 changed files with 36 additions and 4 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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;

View File

@ -77,6 +77,8 @@ public:
bool IsReady() override {
return true;
}
void CancelReady() override {
}
void Reinitialize() override;
void BeginHostFrame() override;

View File

@ -169,6 +169,7 @@ public:
// Initialization
virtual bool IsReady() = 0;
virtual void CancelReady() = 0;
virtual void InitClear() = 0;
virtual void Reinitialize() = 0;

View File

@ -18,6 +18,7 @@
#include <thread>
#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_);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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<VulkanPipelineKey, VulkanPipeline *, nullptr> pipelines_;
VkPipelineCache pipelineCache_ = VK_NULL_HANDLE;
VulkanContext *vulkan_;
float lineWidth_ = 1.0f;
bool cancelCache_ = false;
};