From 65c721dce6512b458b40149a883690156d7b8742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Dec 2022 19:18:20 +0100 Subject: [PATCH 1/2] Rename Save/LoadCache to Save/LoadPipelineCache --- GPU/Vulkan/GPU_Vulkan.cpp | 6 +++--- GPU/Vulkan/PipelineManagerVulkan.cpp | 4 ++-- GPU/Vulkan/PipelineManagerVulkan.h | 4 ++-- GPU/Vulkan/ShaderManagerVulkan.cpp | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index c6ad8ca43c..16e4b32cd8 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -139,8 +139,8 @@ void GPU_Vulkan::LoadCache(const Path &filename) { WARN_LOG(G3D, "ShaderManagerVulkan failed to load cache."); } if (result) { - // WARNING: See comment in LoadCache if you are tempted to flip the second parameter to true. - result = pipelineManager_->LoadCache(f, false, shaderManagerVulkan_, draw_, drawEngine_.GetPipelineLayout()); + // WARNING: See comment in LoadPipelineCache if you are tempted to flip the second parameter to true. + result = pipelineManager_->LoadPipelineCache(f, false, shaderManagerVulkan_, draw_, drawEngine_.GetPipelineLayout()); } fclose(f); if (!result) { @@ -169,7 +169,7 @@ void GPU_Vulkan::SaveCache(const Path &filename) { return; shaderManagerVulkan_->SaveCache(f); // WARNING: See comment in LoadCache if you are tempted to flip the second parameter to true. - pipelineManager_->SaveCache(f, false, shaderManagerVulkan_, draw_); + pipelineManager_->SavePipelineCache(f, false, shaderManagerVulkan_, draw_); INFO_LOG(G3D, "Saved Vulkan pipeline cache"); fclose(f); } diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 401056f786..8fe15d88a1 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -578,7 +578,7 @@ struct StoredVulkanPipelineKey { // If you're looking for how to invalidate the cache, it's done in ShaderManagerVulkan, look for CACHE_VERSION and increment it. // (Header of the same file this is stored in). -void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext) { +void PipelineManagerVulkan::SavePipelineCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext) { VulkanRenderManager *rm = (VulkanRenderManager *)drawContext->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); VulkanQueueRunner *queueRunner = rm->GetQueueRunner(); @@ -667,7 +667,7 @@ void PipelineManagerVulkan::SaveCache(FILE *file, bool saveRawPipelineCache, Sha } } -bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout) { +bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout) { VulkanRenderManager *rm = (VulkanRenderManager *)drawContext->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); VulkanQueueRunner *queueRunner = rm->GetQueueRunner(); diff --git a/GPU/Vulkan/PipelineManagerVulkan.h b/GPU/Vulkan/PipelineManagerVulkan.h index 5b5400ff1b..6f5866fbfb 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.h +++ b/GPU/Vulkan/PipelineManagerVulkan.h @@ -98,8 +98,8 @@ public: std::vector DebugGetObjectIDs(DebugShaderType type); // 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 SavePipelineCache(FILE *file, bool saveRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext); + bool LoadPipelineCache(FILE *file, bool loadRawPipelineCache, ShaderManagerVulkan *shaderManager, Draw::DrawContext *drawContext, VkPipelineLayout layout); void CancelCache(); private: diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 327392ad7c..11f27f362b 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -515,6 +515,7 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { WARN_LOG(G3D, "Shader cache version mismatch, %d, expected %d", header.version, CACHE_VERSION); return false; } + if (header.useFlags != gstate_c.GetUseFlags()) { WARN_LOG(G3D, "Shader cache useFlags mismatch, %08x, expected %08x", header.useFlags, gstate_c.GetUseFlags()); return false; From 00ebf4957fec4134122a7a538926f3187e073246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Dec 2022 23:06:57 +0100 Subject: [PATCH 2/2] Make shader cache loading a bit more lenient. --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 21 +++++++++--------- GPU/Vulkan/PipelineManagerVulkan.cpp | 26 ++++++++++++++++++----- GPU/Vulkan/ShaderManagerVulkan.cpp | 19 ++++++++++++----- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 0bc5341f12..25edb75682 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -546,17 +546,18 @@ VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipe RenderPassType rpType = (RenderPassType)i; // Sanity check - don't compile incompatible types (could be caused by corrupt caches, changes in data structures, etc). - if (pipelineFlags & PipelineFlags::USES_DEPTH_STENCIL) { - if (!RenderPassTypeHasDepth(rpType)) { - WARN_LOG(G3D, "Not compiling pipeline that requires depth, for non depth renderpass type"); - continue; - } + if ((pipelineFlags & PipelineFlags::USES_DEPTH_STENCIL) && !RenderPassTypeHasDepth(rpType)) { + WARN_LOG(G3D, "Not compiling pipeline that requires depth, for non depth renderpass type"); + continue; } - if (pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) { - if (!RenderPassTypeHasInput(rpType)) { - WARN_LOG(G3D, "Not compiling pipeline that requires input attachment, for non input renderpass type"); - continue; - } + if ((pipelineFlags & PipelineFlags::USES_INPUT_ATTACHMENT) && !RenderPassTypeHasInput(rpType)) { + WARN_LOG(G3D, "Not compiling pipeline that requires input attachment, for non input renderpass type"); + continue; + } + // Shouldn't hit this, these should have been filtered elsewhere. However, still a good check to do. + if (sampleCount == VK_SAMPLE_COUNT_1_BIT && RenderPassTypeHasMultisample(rpType)) { + WARN_LOG(G3D, "Not compiling single sample pipeline for a multisampled render pass type"); + continue; } pipeline->pipeline[i] = Promise::CreateEmpty(); diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index 8fe15d88a1..44cff72b84 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -671,6 +671,8 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa VulkanRenderManager *rm = (VulkanRenderManager *)drawContext->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); VulkanQueueRunner *queueRunner = rm->GetQueueRunner(); + cancelCache_ = false; + uint32_t size = 0; if (loadRawPipelineCache) { NOTICE_LOG(G3D, "WARNING: Using the badly tested raw pipeline cache path!!!!"); @@ -727,6 +729,7 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa NOTICE_LOG(G3D, "Creating %d pipelines from cache...", size); int pipelineCreateFailCount = 0; + int shaderFailCount = 0; for (uint32_t i = 0; i < size; i++) { if (failed || cancelCache_) { break; @@ -734,21 +737,33 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa StoredVulkanPipelineKey key; failed = failed || fread(&key, sizeof(key), 1, file) != 1; if (failed) { - ERROR_LOG(G3D, "Truncated Vulkan pipeline cache file"); - continue; + ERROR_LOG(G3D, "Truncated Vulkan pipeline cache file, stopping."); + break; } VulkanVertexShader *vs = shaderManager->GetVertexShaderFromID(key.vShaderID); VulkanFragmentShader *fs = shaderManager->GetFragmentShaderFromID(key.fShaderID); VulkanGeometryShader *gs = shaderManager->GetGeometryShaderFromID(key.gShaderID); if (!vs || !fs || (!gs && key.gShaderID.Bit(GS_BIT_ENABLED))) { - failed = true; - ERROR_LOG(G3D, "Failed to find vs or fs in of pipeline %d in cache", (int)i); + // We just ignore this one, it'll get created later if needed. + // Probably some useFlags mismatch. + WARN_LOG(G3D, "Failed to find vs or fs in pipeline %d in cache, skipping pipeline", (int)i); continue; } + // Avoid creating multisampled shaders if it's not enabled, as that results in an invalid combination. + u32 variantsToBuild = key.variants; + if (g_Config.iMultiSampleLevel == 0) { + for (u32 i = 0; i < (int)RenderPassType::TYPE_COUNT; i++) { + if (RenderPassTypeHasMultisample((RenderPassType)i)) { + variantsToBuild &= ~(1 << i); + } + } + } + DecVtxFormat fmt; fmt.InitializeFromID(key.vtxFmtId); - VulkanPipeline *pipeline = GetOrCreatePipeline(rm, layout, key.raster, key.useHWTransform ? &fmt : 0, vs, fs, gs, key.useHWTransform, key.variants); + VulkanPipeline *pipeline = GetOrCreatePipeline( + rm, layout, key.raster, key.useHWTransform ? &fmt : 0, vs, fs, gs, key.useHWTransform, variantsToBuild); if (!pipeline) { pipelineCreateFailCount += 1; } @@ -757,6 +772,7 @@ bool PipelineManagerVulkan::LoadPipelineCache(FILE *file, bool loadRawPipelineCa rm->NudgeCompilerThread(); NOTICE_LOG(G3D, "Recreated Vulkan pipeline cache (%d pipelines, %d failed).", (int)size, pipelineCreateFailCount); + // We just ignore any failures. return true; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 11f27f362b..bec74abcff 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -517,10 +517,13 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { } if (header.useFlags != gstate_c.GetUseFlags()) { + // This can simply be a result of sawExactEqualDepth_ having been flipped to true in the previous run. + // Let's just keep going. WARN_LOG(G3D, "Shader cache useFlags mismatch, %08x, expected %08x", header.useFlags, gstate_c.GetUseFlags()); - return false; } + int failCount = 0; + VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); for (int i = 0; i < header.numVertexShaders; i++) { VShaderID id; @@ -535,7 +538,9 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { VertexShaderFlags flags; if (!GenerateVertexShader(id, codeBuffer_, compat_, draw_->GetBugs(), &attributeMask, &uniformMask, &flags, &genErrorString)) { WARN_LOG(G3D, "Failed to generate vertex shader during cache load"); - return false; + // We just ignore this one and carry on. + failCount++; + continue; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "VS length error: %d", (int)strlen(codeBuffer_)); VulkanVertexShader *vs = new VulkanVertexShader(vulkan, id, flags, codeBuffer_, useHWTransform); @@ -554,7 +559,9 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { FragmentShaderFlags flags; if (!GenerateFragmentShader(id, codeBuffer_, compat_, draw_->GetBugs(), &uniformMask, &flags, &genErrorString)) { WARN_LOG(G3D, "Failed to generate fragment shader during cache load"); - return false; + // We just ignore this one and carry on. + failCount++; + continue; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "FS length error: %d", (int)strlen(codeBuffer_)); VulkanFragmentShader *fs = new VulkanFragmentShader(vulkan, id, flags, codeBuffer_); @@ -570,14 +577,16 @@ bool ShaderManagerVulkan::LoadCache(FILE *f) { std::string genErrorString; if (!GenerateGeometryShader(id, codeBuffer_, compat_, draw_->GetBugs(), &genErrorString)) { WARN_LOG(G3D, "Failed to generate geometry shader during cache load"); - return false; + // We just ignore this one and carry on. + failCount++; + continue; } _assert_msg_(strlen(codeBuffer_) < CODE_BUFFER_SIZE, "GS length error: %d", (int)strlen(codeBuffer_)); VulkanGeometryShader *gs = new VulkanGeometryShader(vulkan, id, codeBuffer_); gsCache_.Insert(id, gs); } - NOTICE_LOG(G3D, "ShaderCache: Loaded %d vertex, %d fragment shaders and %d geometry shaders", header.numVertexShaders, header.numFragmentShaders, header.numGeometryShaders); + NOTICE_LOG(G3D, "ShaderCache: Loaded %d vertex, %d fragment shaders and %d geometry shaders (failed %d)", header.numVertexShaders, header.numFragmentShaders, header.numGeometryShaders, failCount); return true; }