From 1bcdade83e960860fe6f4a57024a6e361676987d Mon Sep 17 00:00:00 2001 From: Samuliak Date: Wed, 7 Aug 2024 20:59:05 +0200 Subject: [PATCH] set stencil state --- .../LatteDecompilerEmitMSL.cpp | 2 +- .../LatteDecompilerEmitMSLHeader.hpp | 6 ++ .../HW/Latte/Renderer/Metal/CachedFBOMtl.cpp | 9 +++ .../HW/Latte/Renderer/Metal/LatteToMtl.cpp | 17 ++++ src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h | 2 + .../Renderer/Metal/MetalDepthStencilCache.cpp | 81 +++++++++---------- .../Renderer/Metal/MetalPipelineCache.cpp | 5 +- .../HW/Latte/Renderer/Metal/MetalRenderer.h | 1 + 8 files changed, 79 insertions(+), 44 deletions(-) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp index 84cba909..56253a71 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp @@ -3215,7 +3215,7 @@ static void _emitExportCode(LatteDecompilerShaderContext* shaderContext, LatteDe cemu_assert_unimplemented(); // ukn } - src->add("gl_FragDepth = "); + src->add("out.depth = "); _emitExportGPRReadCode(shaderContext, cfInstruction, LATTE_DECOMPILER_DTYPE_FLOAT, 0); src->add(".x"); src->add(";" _CRLF); diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp index 5384f0d4..c3d63eac 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp @@ -271,6 +271,12 @@ namespace LatteDecompiler } } + // generate depth output for pixel shader + if (decompilerContext->shader->pixelDepthOutputMask) + { + src->add("float passDepth [[depth(any)]];" _CRLF); + } + src->add("};" _CRLF _CRLF); } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp index f3b98f15..1c02f7b4 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.cpp @@ -28,6 +28,15 @@ void CachedFBOMtl::CreateRenderPass() depthAttachment->setTexture(textureView->GetRGBAView()); depthAttachment->setLoadAction(MTL::LoadActionLoad); depthAttachment->setStoreAction(MTL::StoreActionStore); + + // setup stencil attachment + if (depthBuffer.hasStencil) + { + auto stencilAttachment = m_renderPassDescriptor->stencilAttachment(); + stencilAttachment->setTexture(textureView->GetRGBAView()); + stencilAttachment->setLoadAction(MTL::LoadActionLoad); + stencilAttachment->setStoreAction(MTL::StoreActionStore); + } } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index 44cb1f3b..d03be2de 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -452,3 +452,20 @@ MTL::TextureSwizzle GetMtlTextureSwizzle(uint32 swizzle) cemu_assert_debug(swizzle < std::size(MTL_TEXTURE_SWIZZLES)); return MTL_TEXTURE_SWIZZLES[swizzle]; } + +const MTL::StencilOperation MTL_STENCIL_OPERATIONS[8] = { + MTL::StencilOperationKeep, + MTL::StencilOperationZero, + MTL::StencilOperationReplace, + MTL::StencilOperationIncrementClamp, + MTL::StencilOperationDecrementClamp, + MTL::StencilOperationInvert, + MTL::StencilOperationIncrementWrap, + MTL::StencilOperationDecrementWrap +}; + +MTL::StencilOperation GetMtlStencilOp(Latte::LATTE_DB_DEPTH_CONTROL::E_STENCILACTION action) +{ + cemu_assert_debug((uint32)action < std::size(MTL_STENCIL_OPERATIONS)); + return MTL_STENCIL_OPERATIONS[(uint32)action]; +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h index 6b3ae2af..5fd23186 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h @@ -53,3 +53,5 @@ MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func); MTL::SamplerAddressMode GetMtlSamplerAddressMode(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_CLAMP clamp); MTL::TextureSwizzle GetMtlTextureSwizzle(uint32 swizzle); + +MTL::StencilOperation GetMtlStencilOp(Latte::LATTE_DB_DEPTH_CONTROL::E_STENCILACTION action); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp index 87968ec3..8f50c44c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp @@ -37,8 +37,6 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte } desc->setDepthCompareFunction(depthCompareFunc); - // TODO: stencil state - /* // get stencil control parameters bool stencilEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ENABLE(); bool backStencilEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_BACK_STENCIL_ENABLE(); @@ -58,48 +56,47 @@ MTL::DepthStencilState* MetalDepthStencilCache::GetDepthStencilState(const Latte uint32 stencilWriteMaskBack = LatteGPUState.contextNew.DB_STENCILREFMASK_BF.get_STENCILWRITEMASK_B(); uint32 stencilRefBack = LatteGPUState.contextNew.DB_STENCILREFMASK_BF.get_STENCILREF_B(); - static const VkStencilOp stencilOpTable[8] = { - VK_STENCIL_OP_KEEP, - VK_STENCIL_OP_ZERO, - VK_STENCIL_OP_REPLACE, - VK_STENCIL_OP_INCREMENT_AND_CLAMP, - VK_STENCIL_OP_DECREMENT_AND_CLAMP, - VK_STENCIL_OP_INVERT, - VK_STENCIL_OP_INCREMENT_AND_WRAP, - VK_STENCIL_OP_DECREMENT_AND_WRAP - }; - - depthStencilState.stencilTestEnable = stencilEnable ? VK_TRUE : VK_FALSE; - - depthStencilState.front.reference = stencilRefFront; - depthStencilState.front.compareMask = stencilCompareMaskFront; - depthStencilState.front.writeMask = stencilWriteMaskBack; - depthStencilState.front.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc]; - depthStencilState.front.depthFailOp = stencilOpTable[(size_t)frontStencilZFail]; - depthStencilState.front.failOp = stencilOpTable[(size_t)frontStencilFail]; - depthStencilState.front.passOp = stencilOpTable[(size_t)frontStencilZPass]; - - if (backStencilEnable) + if (stencilEnable) { - depthStencilState.back.reference = stencilRefBack; - depthStencilState.back.compareMask = stencilCompareMaskBack; - depthStencilState.back.writeMask = stencilWriteMaskBack; - depthStencilState.back.compareOp = vkDepthCompareTable[(size_t)backStencilFunc]; - depthStencilState.back.depthFailOp = stencilOpTable[(size_t)backStencilZFail]; - depthStencilState.back.failOp = stencilOpTable[(size_t)backStencilFail]; - depthStencilState.back.passOp = stencilOpTable[(size_t)backStencilZPass]; + MTL::StencilDescriptor* frontStencil = MTL::StencilDescriptor::alloc()->init(); + // TODO: set reference + //depthStencilState.front.reference = stencilRefFront; + frontStencil->setReadMask(stencilCompareMaskFront); + frontStencil->setWriteMask(stencilWriteMaskFront); + frontStencil->setStencilCompareFunction(GetMtlCompareFunc(frontStencilFunc)); + frontStencil->setDepthFailureOperation(GetMtlStencilOp(frontStencilZFail)); + frontStencil->setStencilFailureOperation(GetMtlStencilOp(frontStencilFail)); + frontStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass)); + desc->setFrontFaceStencil(frontStencil); + + MTL::StencilDescriptor* backStencil = MTL::StencilDescriptor::alloc()->init(); + if (backStencilEnable) + { + // TODO: set reference + //depthStencilState.back.reference = stencilRefBack; + backStencil->setReadMask(stencilCompareMaskBack); + backStencil->setWriteMask(stencilWriteMaskBack); + backStencil->setStencilCompareFunction(GetMtlCompareFunc(backStencilFunc)); + backStencil->setDepthFailureOperation(GetMtlStencilOp(backStencilZFail)); + backStencil->setStencilFailureOperation(GetMtlStencilOp(backStencilFail)); + backStencil->setDepthStencilPassOperation(GetMtlStencilOp(backStencilZPass)); + } + else + { + // TODO: set reference + //depthStencilState.back.reference = stencilRefFront; + backStencil->setReadMask(stencilCompareMaskFront); + backStencil->setWriteMask(stencilWriteMaskFront); + backStencil->setStencilCompareFunction(GetMtlCompareFunc(frontStencilFunc)); + backStencil->setDepthFailureOperation(GetMtlStencilOp(frontStencilZFail)); + backStencil->setStencilFailureOperation(GetMtlStencilOp(frontStencilFail)); + backStencil->setDepthStencilPassOperation(GetMtlStencilOp(frontStencilZPass)); + } + desc->setBackFaceStencil(backStencil); + + frontStencil->release(); + backStencil->release(); } - else - { - depthStencilState.back.reference = stencilRefFront; - depthStencilState.back.compareMask = stencilCompareMaskFront; - depthStencilState.back.writeMask = stencilWriteMaskFront; - depthStencilState.back.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc]; - depthStencilState.back.depthFailOp = stencilOpTable[(size_t)frontStencilZFail]; - depthStencilState.back.failOp = stencilOpTable[(size_t)frontStencilFail]; - depthStencilState.back.passOp = stencilOpTable[(size_t)frontStencilZPass]; - } - */ depthStencilState = m_mtlr->GetDevice()->newDepthStencilState(desc); desc->release(); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp index b76cd8f8..2462f370 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp @@ -143,7 +143,10 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS { auto texture = static_cast(activeFBO->depthBuffer.texture); desc->setDepthAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat()); - // TODO: stencil pixel format + if (activeFBO->depthBuffer.hasStencil) + { + desc->setStencilAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat()); + } } NS::Error* error = nullptr; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 26ab52f1..c770017b 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -49,6 +49,7 @@ enum class MetalEncoderType Blit, }; +// HACK: Dummy occlusion query object for Metal class LatteQueryObjectMtl : public LatteQueryObject { public: