From 00857b233b6c92dc3ecb5c4b0341d960f4a1665a Mon Sep 17 00:00:00 2001 From: Samuliak Date: Fri, 22 Nov 2024 20:03:41 +0100 Subject: [PATCH] support arbitrary pixel formats for state 5 --- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 45 +++++++++++-------- .../HW/Latte/Renderer/Metal/MetalRenderer.h | 3 +- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index cfb63fc5..a29a2356 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -134,22 +134,12 @@ MetalRenderer::MetalRenderer() MTL::Function* vertexFullscreenFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen")); MTL::Function* fragmentCopyDepthToColorFunction = utilityLibrary->newFunction(ToNSString("fragmentCopyDepthToColor")); - MTL::RenderPipelineDescriptor* rpd = MTL::RenderPipelineDescriptor::alloc()->init(); - rpd->setVertexFunction(vertexFullscreenFunction); - rpd->setFragmentFunction(fragmentCopyDepthToColorFunction); - // TODO: don't hardcode the format - rpd->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatR16Unorm); - + m_copyDepthToColorDesc = MTL::RenderPipelineDescriptor::alloc()->init(); + m_copyDepthToColorDesc->setVertexFunction(vertexFullscreenFunction); + m_copyDepthToColorDesc->setFragmentFunction(fragmentCopyDepthToColorFunction); vertexFullscreenFunction->release(); fragmentCopyDepthToColorFunction->release(); - error = nullptr; - m_copyDepthToColorPipeline = m_device->newRenderPipelineState(rpd, &error); - if (error) - { - cemuLog_log(LogType::Force, "failed to create copy depth to color pipeline (error: {})", error->localizedDescription()->utf8String()); - } - // Void vertex pipelines if (m_isAppleGPU) m_copyBufferToBufferPipeline = new MetalVoidVertexPipeline(this, utilityLibrary, "vertexCopyBufferToBuffer"); @@ -164,7 +154,9 @@ MetalRenderer::~MetalRenderer() //delete m_copyTextureToTexturePipeline; //delete m_restrideBufferPipeline; - m_copyDepthToColorPipeline->release(); + m_copyDepthToColorDesc->release(); + for (const auto [pixelFormat, pipeline] : m_copyDepthToColorPipelines) + pipeline->release(); delete m_outputShaderCache; delete m_pipelineCache; @@ -1369,22 +1361,39 @@ void MetalRenderer::draw_handleSpecialState5() LatteTextureView* colorBuffer = LatteMRT::GetColorAttachment(0); LatteTextureView* depthBuffer = LatteMRT::GetDepthAttachment(); - auto mtlDepthTexture = static_cast(depthBuffer)->GetRGBAView(); + auto colorTextureMtl = static_cast(colorBuffer); + auto depthTextureMtl = static_cast(depthBuffer); sint32 vpWidth, vpHeight; LatteMRT::GetVirtualViewportDimensions(vpWidth, vpHeight); + // Get the pipeline + MTL::PixelFormat colorPixelFormat = colorTextureMtl->GetRGBAView()->pixelFormat(); + auto& pipeline = m_copyDepthToColorPipelines[colorPixelFormat]; + if (!pipeline) + { + m_copyDepthToColorDesc->colorAttachments()->object(0)->setPixelFormat(colorPixelFormat); + + NS::Error* error = nullptr; + pipeline = m_device->newRenderPipelineState(m_copyDepthToColorDesc, &error); + if (error) + { + cemuLog_log(LogType::Force, "failed to create copy depth to color pipeline (error: {})", error->localizedDescription()->utf8String()); + } + } + // Sadly, we need to end encoding to ensure that the depth data is up-to-date + EndEncoding(); // Copy depth to color auto renderCommandEncoder = GetRenderCommandEncoder(); auto& encoderState = m_state.m_encoderState; - renderCommandEncoder->setRenderPipelineState(m_copyDepthToColorPipeline); + renderCommandEncoder->setRenderPipelineState(pipeline); // TODO: make a helper function for this - encoderState.m_renderPipelineState = m_copyDepthToColorPipeline; - SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_FRAGMENT, mtlDepthTexture, GET_HELPER_TEXTURE_BINDING(0)); + encoderState.m_renderPipelineState = pipeline; + SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_FRAGMENT, depthTextureMtl->GetRGBAView(), GET_HELPER_TEXTURE_BINDING(0)); // TODO: make a helper function for this renderCommandEncoder->setFragmentBytes(&vpWidth, sizeof(sint32), GET_HELPER_BUFFER_BINDING(0)); encoderState.m_buffers[METAL_SHADER_TYPE_FRAGMENT][GET_HELPER_BUFFER_BINDING(0)] = {nullptr}; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 6d5bea6c..010f3f92 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -473,7 +473,8 @@ private: class MetalSamplerCache* m_samplerCache; // Pipelines - MTL::RenderPipelineState* m_copyDepthToColorPipeline; + MTL::RenderPipelineDescriptor* m_copyDepthToColorDesc; + std::map m_copyDepthToColorPipelines; // Void vertex pipelines class MetalVoidVertexPipeline* m_copyBufferToBufferPipeline;