From b220c163e325f8cb3444aa29c782a0f72ccbe5d3 Mon Sep 17 00:00:00 2001
From: Samuliak <samuliak77@gmail.com>
Date: Wed, 3 Jul 2024 15:01:37 +0200
Subject: [PATCH] support stencil attachments

---
 include/renderer_mtl/renderer_mtl.hpp  |  2 +-
 src/core/renderer_mtl/renderer_mtl.cpp | 40 +++++++++++++++-----------
 2 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp
index 8ac3f2c2..531d6e90 100644
--- a/include/renderer_mtl/renderer_mtl.hpp
+++ b/include/renderer_mtl/renderer_mtl.hpp
@@ -71,7 +71,7 @@ class RendererMTL final : public Renderer {
         }
 	}
 
-	void beginRenderPassIfNeeded(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorTexture, MTL::Texture* depthTexture) {
+	void beginRenderPassIfNeeded(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* colorTexture, MTL::Texture* depthTexture = nullptr) {
 		createCommandBufferIfNeeded();
 
 		if (!renderCommandEncoder || colorTexture != lastColorTexture || depthTexture != lastDepthTexture) {
diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp
index 01a40f0a..ea466663 100644
--- a/src/core/renderer_mtl/renderer_mtl.cpp
+++ b/src/core/renderer_mtl/renderer_mtl.cpp
@@ -42,7 +42,7 @@ void RendererMTL::display() {
 	colorAttachment->setClearColor(MTL::ClearColor{0.0f, 0.0f, 0.0f, 1.0f});
 	colorAttachment->setStoreAction(MTL::StoreActionStore);
 
-	beginRenderPassIfNeeded(renderPassDescriptor, drawable->texture(), nullptr);
+	beginRenderPassIfNeeded(renderPassDescriptor, drawable->texture());
 	renderCommandEncoder->setRenderPipelineState(displayPipeline);
 	renderCommandEncoder->setFragmentSamplerState(basicSampler, 0);
 
@@ -214,7 +214,7 @@ void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 c
 		colorAttachment->setLoadAction(MTL::LoadActionClear);
 		colorAttachment->setStoreAction(MTL::StoreActionStore);
 
-		beginRenderPassIfNeeded(renderPassDescriptor, color->get().texture, nullptr);
+		beginRenderPassIfNeeded(renderPassDescriptor, color->get().texture);
 
 		return;
 	}
@@ -229,23 +229,23 @@ void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 c
 			depthVal = (value & 0xffffff) / 16777215.0f;
 		}
 
-		if (false/*format == DepthFmt::Depth24Stencil8*/) {
-		    // TODO: clear stencil
-			//const u8 stencil = (value >> 24);
-			//gl.setStencilMask(0xff);
-			//OpenGL::setClearStencil(stencil);
-			//OpenGL::clearDepthAndStencil();
-		} else {
-    		MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
-    		MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = renderPassDescriptor->depthAttachment();
-            depthAttachment->setTexture(depth->get().texture);
-            depthAttachment->setClearDepth(depthVal);
-            depthAttachment->setLoadAction(MTL::LoadActionClear);
-            depthAttachment->setStoreAction(MTL::StoreActionStore);
+		MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
+  		MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = renderPassDescriptor->depthAttachment();
+        depthAttachment->setTexture(depth->get().texture);
+        depthAttachment->setClearDepth(depthVal);
+        depthAttachment->setLoadAction(MTL::LoadActionClear);
+        depthAttachment->setStoreAction(MTL::StoreActionStore);
 
-            beginRenderPassIfNeeded(renderPassDescriptor, nullptr, depth->get().texture);
+		if (format == DepthFmt::Depth24Stencil8) {
+		    MTL::RenderPassStencilAttachmentDescriptor* stencilAttachment = renderPassDescriptor->stencilAttachment();
+			stencilAttachment->setTexture(depth->get().texture);
+			stencilAttachment->setClearStencil((value >> 24) & 0xff);
+			stencilAttachment->setLoadAction(MTL::LoadActionClear);
+			stencilAttachment->setStoreAction(MTL::StoreActionStore);
 		}
 
+		beginRenderPassIfNeeded(renderPassDescriptor, nullptr, depth->get().texture);
+
 		return;
 	}
 
@@ -298,7 +298,7 @@ void RendererMTL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize,
 	Metal::PipelineHash hash{destFramebuffer->format, DepthFmt::Unknown1};
 	auto blitPipeline = blitPipelineCache.get(hash);
 
-	beginRenderPassIfNeeded(renderPassDescriptor, destFramebuffer->texture, nullptr);
+	beginRenderPassIfNeeded(renderPassDescriptor, destFramebuffer->texture);
 	renderCommandEncoder->setRenderPipelineState(blitPipeline);
 	renderCommandEncoder->setFragmentTexture(srcFramebuffer->texture, 0);
 	renderCommandEncoder->setFragmentSamplerState(basicSampler, 0);
@@ -379,6 +379,12 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
         depthAttachment->setTexture(depthStencilRenderTarget->texture);
         depthAttachment->setLoadAction(MTL::LoadActionLoad);
         depthAttachment->setStoreAction(MTL::StoreActionStore);
+        if (depthStencilRenderTarget->format == DepthFmt::Depth24Stencil8) {
+            MTL::RenderPassStencilAttachmentDescriptor* stencilAttachment = renderPassDescriptor->stencilAttachment();
+            stencilAttachment->setTexture(depthStencilRenderTarget->texture);
+            stencilAttachment->setLoadAction(MTL::LoadActionLoad);
+            stencilAttachment->setStoreAction(MTL::StoreActionStore);
+        }
     }
 
 	beginRenderPassIfNeeded(renderPassDescriptor, colorRenderTarget->texture, (depthStencilRenderTarget ? depthStencilRenderTarget->texture : nullptr));