use map instead of vector for clear ops

This commit is contained in:
Samuliak 2024-07-06 22:08:15 +02:00
parent e33339b655
commit a9b4f64ca7
2 changed files with 28 additions and 41 deletions

View file

@ -13,25 +13,10 @@
class GPU; class GPU;
namespace Metal { struct Color4 {
struct ColorClearOp {
MTL::Texture* texture;
float r, g, b, a; 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 { class RendererMTL final : public Renderer {
public: public:
RendererMTL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs); RendererMTL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs);
@ -77,9 +62,9 @@ class RendererMTL final : public Renderer {
MTL::RenderPipelineState* copyToLutTexturePipeline; MTL::RenderPipelineState* copyToLutTexturePipeline;
// Clears // Clears
std::vector<Metal::ColorClearOp> colorClearOps; std::map<MTL::Texture*, Color4> colorClearOps;
std::vector<Metal::DepthClearOp> depthClearOps; std::map<MTL::Texture*, float> depthClearOps;
std::vector<Metal::StencilClearOp> stencilClearOps; std::map<MTL::Texture*, u8> stencilClearOps;
// Active state // Active state
MTL::CommandBuffer* commandBuffer = nullptr; MTL::CommandBuffer* commandBuffer = nullptr;
@ -124,32 +109,34 @@ class RendererMTL final : public Renderer {
} }
} }
template<typename AttachmentT, typename ClearOpT, typename GetAttachmentT, typename SetClearDataT> template<typename AttachmentT, typename ClearDataT, typename GetAttachmentT, typename SetClearDataT>
inline void clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, ClearOpT clearOp, GetAttachmentT getAttachment, SetClearDataT setClearData) { inline void clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, ClearDataT clearData, GetAttachmentT getAttachment, SetClearDataT setClearData) {
bool beginRenderPass = (renderPassDescriptor == nullptr); bool beginRenderPass = (renderPassDescriptor == nullptr);
if (!renderPassDescriptor) { if (!renderPassDescriptor) {
renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
} }
AttachmentT* attachment = getAttachment(); AttachmentT* attachment = getAttachment();
attachment->setTexture(clearOp.texture); attachment->setTexture(texture);
setClearData(attachment, clearOp); setClearData(attachment, clearData);
attachment->setLoadAction(MTL::LoadActionClear); attachment->setLoadAction(MTL::LoadActionClear);
attachment->setStoreAction(MTL::StoreActionStore); attachment->setStoreAction(MTL::StoreActionStore);
if (beginRenderPass) { if (beginRenderPass) {
beginRenderPassIfNeeded(renderPassDescriptor, true, clearOp.texture); if (std::is_same<AttachmentT, MTL::RenderPassColorAttachmentDescriptor>::value)
beginRenderPassIfNeeded(renderPassDescriptor, true, texture);
else
beginRenderPassIfNeeded(renderPassDescriptor, true, nullptr, texture);
} }
} }
template<typename AttachmentT, typename ClearOpT, typename GetAttachmentT, typename SetClearDataT> template<typename AttachmentT, typename ClearDataT, typename GetAttachmentT, typename SetClearDataT>
inline bool clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, std::vector<ClearOpT>& clearOps, GetAttachmentT getAttachment, SetClearDataT setClearData) { inline bool clearAttachment(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture, std::map<MTL::Texture*, ClearDataT>& clearOps, GetAttachmentT getAttachment, SetClearDataT setClearData) {
for (int32_t i = clearOps.size() - 1; i >= 0; i--) { auto it = clearOps.find(texture);
if (clearOps[i].texture == texture) { if (it != clearOps.end()) {
clearAttachment<AttachmentT>(renderPassDescriptor, clearOps[i], getAttachment, setClearData); clearAttachment<AttachmentT>(renderPassDescriptor, texture, it->second, getAttachment, setClearData);
clearOps.erase(clearOps.begin() + i); clearOps.erase(it);
return true; return true;
}
} }
if (renderPassDescriptor) { if (renderPassDescriptor) {
@ -163,20 +150,20 @@ class RendererMTL final : public Renderer {
} }
bool clearColor(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { bool clearColor(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) {
return clearAttachment<MTL::RenderPassColorAttachmentDescriptor, Metal::ColorClearOp>(renderPassDescriptor, texture, colorClearOps, [&]() { return renderPassDescriptor->colorAttachments()->object(0); }, [&](auto attachment, auto& clearOp) { return clearAttachment<MTL::RenderPassColorAttachmentDescriptor, Color4>(renderPassDescriptor, texture, colorClearOps, [&]() { return renderPassDescriptor->colorAttachments()->object(0); }, [&](auto attachment, auto& color) {
attachment->setClearColor(MTL::ClearColor(clearOp.r, clearOp.g, clearOp.b, clearOp.a)); attachment->setClearColor(MTL::ClearColor(color.r, color.g, color.b, color.a));
}); });
} }
bool clearDepth(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { bool clearDepth(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) {
return clearAttachment<MTL::RenderPassDepthAttachmentDescriptor, Metal::DepthClearOp>(renderPassDescriptor, texture, depthClearOps, [&]() { return renderPassDescriptor->depthAttachment(); }, [&](auto attachment, auto& clearOp) { return clearAttachment<MTL::RenderPassDepthAttachmentDescriptor, float>(renderPassDescriptor, texture, depthClearOps, [&]() { return renderPassDescriptor->depthAttachment(); }, [&](auto attachment, auto& depth) {
attachment->setClearDepth(clearOp.depth); attachment->setClearDepth(depth);
}); });
} }
bool clearStencil(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) { bool clearStencil(MTL::RenderPassDescriptor* renderPassDescriptor, MTL::Texture* texture) {
return clearAttachment<MTL::RenderPassStencilAttachmentDescriptor, Metal::StencilClearOp>(renderPassDescriptor, texture, stencilClearOps, [&]() { return renderPassDescriptor->stencilAttachment(); }, [&](auto attachment, auto& clearOp) { return clearAttachment<MTL::RenderPassStencilAttachmentDescriptor, u8>(renderPassDescriptor, texture, stencilClearOps, [&]() { return renderPassDescriptor->stencilAttachment(); }, [&](auto attachment, auto& stencil) {
attachment->setClearStencil(clearOp.stencil); attachment->setClearStencil(stencil);
}); });
} }

View file

@ -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 b = Helpers::getBits<8, 8>(value) / 255.0f;
const float a = (value & 0xff) / 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; return;
} }
@ -281,11 +281,11 @@ void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 c
depthVal = (value & 0xffffff) / 16777215.0f; depthVal = (value & 0xffffff) / 16777215.0f;
} }
depthClearOps.push_back({depth->get().texture, depthVal}); depthClearOps[depth->get().texture] = depthVal;
if (format == DepthFmt::Depth24Stencil8) { if (format == DepthFmt::Depth24Stencil8) {
const u8 stencilVal = value >> 24; const u8 stencilVal = value >> 24;
stencilClearOps.push_back({depth->get().texture, stencilVal}); stencilClearOps[depth->get().texture] = stencilVal;
} }
return; return;