diff --git a/include/renderer_mtl/renderer_mtl.hpp b/include/renderer_mtl/renderer_mtl.hpp index 58ec6bae..2221f151 100644 --- a/include/renderer_mtl/renderer_mtl.hpp +++ b/include/renderer_mtl/renderer_mtl.hpp @@ -13,25 +13,10 @@ class GPU; -namespace Metal { - -struct ColorClearOp { - MTL::Texture* texture; +struct Color4 { float r, g, b, a; }; -struct DepthClearOp { - MTL::Texture* texture; - float depth; -}; - -struct StencilClearOp { - MTL::Texture* texture; - u8 stencil; -}; - -} // namespace Metal - class RendererMTL final : public Renderer { public: RendererMTL(GPU& gpu, const std::array& internalRegs, const std::array& externalRegs); @@ -77,9 +62,9 @@ class RendererMTL final : public Renderer { MTL::RenderPipelineState* copyToLutTexturePipeline; // Clears - std::vector colorClearOps; - std::vector depthClearOps; - std::vector stencilClearOps; + std::map colorClearOps; + std::map depthClearOps; + std::map stencilClearOps; // Active state MTL::CommandBuffer* commandBuffer = nullptr; @@ -124,32 +109,34 @@ class RendererMTL final : public Renderer { } } - template - inline void clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, ClearOpT clearOp, GetAttachmentT getAttachment, SetClearDataT setClearData) { + template + inline void clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, ClearDataT clearData, GetAttachmentT getAttachment, SetClearDataT setClearData) { bool beginRenderPass = (renderPassDescriptor == nullptr); if (!renderPassDescriptor) { renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); } AttachmentT* attachment = getAttachment(); - attachment->setTexture(clearOp.texture); - setClearData(attachment, clearOp); + attachment->setTexture(texture); + setClearData(attachment, clearData); attachment->setLoadAction(MTL::LoadActionClear); attachment->setStoreAction(MTL::StoreActionStore); if (beginRenderPass) { - beginRenderPassIfNeeded(renderPassDescriptor, true, clearOp.texture); + if (std::is_same::value) + beginRenderPassIfNeeded(renderPassDescriptor, true, texture); + else + beginRenderPassIfNeeded(renderPassDescriptor, true, nullptr, texture); } } - template - inline bool clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, std::vector& clearOps, GetAttachmentT getAttachment, SetClearDataT setClearData) { - for (int32_t i = clearOps.size() - 1; i >= 0; i--) { - if (clearOps[i].texture == texture) { - clearAttachment(renderPassDescriptor, clearOps[i], getAttachment, setClearData); - clearOps.erase(clearOps.begin() + i); - return true; - } + template + inline bool clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, std::map& clearOps, GetAttachmentT getAttachment, SetClearDataT setClearData) { + auto it = clearOps.find(texture); + if (it != clearOps.end()) { + clearAttachment(renderPassDescriptor, texture, it->second, getAttachment, setClearData); + clearOps.erase(it); + return true; } if (renderPassDescriptor) { @@ -163,20 +150,20 @@ class RendererMTL final : public Renderer { } bool clearColor(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { - return clearAttachment(renderPassDescriptor, texture, colorClearOps, [&]() { return renderPassDescriptor->colorAttachments()->object(0); }, [&](auto attachment, auto& clearOp) { - attachment->setClearColor(MTL::ClearColor(clearOp.r, clearOp.g, clearOp.b, clearOp.a)); + return clearAttachment(renderPassDescriptor, texture, colorClearOps, [&]() { return renderPassDescriptor->colorAttachments()->object(0); }, [&](auto attachment, auto& color) { + attachment->setClearColor(MTL::ClearColor(color.r, color.g, color.b, color.a)); }); } bool clearDepth(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { - return clearAttachment(renderPassDescriptor, texture, depthClearOps, [&]() { return renderPassDescriptor->depthAttachment(); }, [&](auto attachment, auto& clearOp) { - attachment->setClearDepth(clearOp.depth); + return clearAttachment(renderPassDescriptor, texture, depthClearOps, [&]() { return renderPassDescriptor->depthAttachment(); }, [&](auto attachment, auto& depth) { + attachment->setClearDepth(depth); }); } bool clearStencil(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { - return clearAttachment(renderPassDescriptor, texture, stencilClearOps, [&]() { return renderPassDescriptor->stencilAttachment(); }, [&](auto attachment, auto& clearOp) { - attachment->setClearStencil(clearOp.stencil); + return clearAttachment(renderPassDescriptor, texture, stencilClearOps, [&]() { return renderPassDescriptor->stencilAttachment(); }, [&](auto attachment, auto& stencil) { + attachment->setClearStencil(stencil); }); } diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 0fb38d7c..bf34ad81 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -266,7 +266,7 @@ void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 c const float b = Helpers::getBits<8, 8>(value) / 255.0f; const float a = (value & 0xff) / 255.0f; - colorClearOps.push_back({color->get().texture, r, g, b, a}); + colorClearOps[color->get().texture] = {r, g, b, a}; return; } @@ -281,11 +281,11 @@ void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 c depthVal = (value & 0xffffff) / 16777215.0f; } - depthClearOps.push_back({depth->get().texture, depthVal}); + depthClearOps[depth->get().texture] = depthVal; if (format == DepthFmt::Depth24Stencil8) { const u8 stencilVal = value >> 24; - stencilClearOps.push_back({depth->get().texture, stencilVal}); + stencilClearOps[depth->get().texture] = stencilVal; } return;