From 15eb6bb37f0011257d040791dac9b549baecbf4f Mon Sep 17 00:00:00 2001 From: Samuliak Date: Sat, 19 Oct 2024 09:29:14 +0200 Subject: [PATCH] fix: pipeline cache with mesh shaders --- .../Renderer/Metal/MetalPipelineCache.cpp | 13 +++-- .../Renderer/Metal/MetalPipelineCompiler.cpp | 48 ++++++++++--------- .../Renderer/Metal/MetalPipelineCompiler.h | 1 + 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp index 476417d3..214c822f 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp @@ -43,19 +43,21 @@ MetalPipelineCache::~MetalPipelineCache() MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr) { uint64 hash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr); - auto& pipeline = m_pipelineCache[hash]; - if (pipeline) - return pipeline; + auto it = m_pipelineCache.find(hash); + if (it != m_pipelineCache.end()) + return it->second; MetalPipelineCompiler compiler(m_mtlr); bool fbosMatch; compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr, fbosMatch); - pipeline = compiler.Compile(false, true, true); + MTL::RenderPipelineState* pipeline = compiler.Compile(false, true, true); // If FBOs don't match, it wouldn't be possible to reconstruct the pipeline from the cache if (fbosMatch) AddCurrentStateToCache(hash); + m_pipelineCache.insert({hash, pipeline}); + return pipeline; } @@ -355,6 +357,9 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span fileData) MetalAttachmentsInfo attachmentsInfo(*lcr, pixelShader); + // TODO: this shouldn't probably be called directly + LatteShader_UpdatePSInputs(lcr->GetRawView()); + MTL::RenderPipelineState* pipeline = nullptr; // compile { diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp index 910b354b..d4635885 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp @@ -10,8 +10,7 @@ #include "Cafe/HW/Latte/ISA/RegDefines.h" #include "Cafe/HW/Latte/Core/LatteConst.h" #include "Cafe/HW/Latte/Core/LatteShader.h" -#include "HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h" -#include "HW/Latte/Renderer/RendererShader.h" + #include extern std::atomic_int g_compiling_pipelines; @@ -196,23 +195,8 @@ extern std::atomic_int g_compiled_shaders_total; extern std::atomic_int g_compiled_shaders_async; template -void SetFragmentState(T* desc, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr, bool& fbosMatch) +void SetFragmentState(T* desc, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, bool rasterizationEnabled, const LatteContextRegister& lcr, bool& fbosMatch) { - // Rasterization - bool rasterizationEnabled = !lcr.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL(); - - // HACK - // TODO: include this in the hash? - if (!lcr.PA_CL_VTE_CNTL.get_VPORT_X_OFFSET_ENA()) - rasterizationEnabled = true; - - // Culling both front and back faces effectively disables rasterization - const auto& polygonControlReg = lcr.PA_SU_SC_MODE_CNTL; - uint32 cullFront = polygonControlReg.get_CULL_FRONT(); - uint32 cullBack = polygonControlReg.get_CULL_BACK(); - if (cullFront && cullBack) - rasterizationEnabled = false; - // TODO: check if the pixel shader is valid as well? if (!rasterizationEnabled/* || !pixelShaderMtl*/) { @@ -317,6 +301,21 @@ void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, c m_usesGeometryShader = (geometryShader != nullptr || isPrimitiveRect); + // Rasterization + m_rasterizationEnabled = !lcr.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL(); + + // HACK + // TODO: include this in the hash? + if (!lcr.PA_CL_VTE_CNTL.get_VPORT_X_OFFSET_ENA()) + m_rasterizationEnabled = true; + + // Culling both front and back faces effectively disables rasterization + const auto& polygonControlReg = lcr.PA_SU_SC_MODE_CNTL; + uint32 cullFront = polygonControlReg.get_CULL_FRONT(); + uint32 cullBack = polygonControlReg.get_CULL_BACK(); + if (cullFront && cullBack) + m_rasterizationEnabled = false; + // Shaders m_vertexShaderMtl = static_cast(vertexShader->shader); if (geometryShader) @@ -368,7 +367,8 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool // Shaders desc->setObjectFunction(m_vertexShaderMtl->GetFunction()); desc->setMeshFunction(m_geometryShaderMtl->GetFunction()); - desc->setFragmentFunction(m_pixelShaderMtl->GetFunction()); + if (m_rasterizationEnabled) + desc->setFragmentFunction(m_pixelShaderMtl->GetFunction()); #ifdef CEMU_DEBUG_ASSERT desc->setLabel(GetLabel("Mesh render pipeline state", desc)); @@ -381,7 +381,8 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool // Shaders desc->setVertexFunction(m_vertexShaderMtl->GetFunction()); - desc->setFragmentFunction(m_pixelShaderMtl->GetFunction()); + if (m_rasterizationEnabled) + desc->setFragmentFunction(m_pixelShaderMtl->GetFunction()); #ifdef CEMU_DEBUG_ASSERT desc->setLabel(GetLabel("Render pipeline state", desc)); @@ -397,7 +398,8 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool cemuLog_log(LogType::Force, "error creating render pipeline state: {}", error->localizedDescription()->utf8String()); error->release(); } - else if (showInOverlay) + + if (showInOverlay) { if (isRenderThread) g_compiling_pipelines_syncTimeSum += creationDuration; @@ -484,7 +486,7 @@ void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchSha vertexDescriptor->release(); } - SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr, fbosMatch); + SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, m_rasterizationEnabled, lcr, fbosMatch); m_pipelineDescriptor = desc; @@ -550,7 +552,7 @@ void MetalPipelineCompiler::InitFromStateMesh(const LatteFetchShader* fetchShade // Render pipeline state MTL::MeshRenderPipelineDescriptor* desc = MTL::MeshRenderPipelineDescriptor::alloc()->init(); - SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr, fbosMatch); + SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, m_rasterizationEnabled, lcr, fbosMatch); m_pipelineDescriptor = desc; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h index 3b9731a3..5965c764 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h @@ -22,6 +22,7 @@ private: class RendererShaderMtl* m_geometryShaderMtl; class RendererShaderMtl* m_pixelShaderMtl; bool m_usesGeometryShader; + bool m_rasterizationEnabled; /* std::map m_pipelineCache;