From 008c11ce71ade8a5f0759d3f38c7817dac287b06 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Sat, 14 Sep 2024 17:12:02 +0200 Subject: [PATCH] allocate special buffers only when needed --- .../Renderer/Metal/MetalBufferAllocator.h | 15 +++++++--- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 23 ++++++--------- .../HW/Latte/Renderer/Metal/MetalRenderer.h | 28 +++++++++++++++++-- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h index ef65c458..9998ac89 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h @@ -248,10 +248,17 @@ public: void SetActiveCommandBuffer(MTL::CommandBuffer* commandBuffer) { m_activeCommandBuffer = commandBuffer; - auto result = m_executingCommandBuffers.emplace(std::make_pair(m_activeCommandBuffer, std::vector{})); - cemu_assert_debug(result.second); - m_activeCommandBufferIt = result.first; - commandBuffer->retain(); + if (commandBuffer) + { + auto result = m_executingCommandBuffers.emplace(std::make_pair(m_activeCommandBuffer, std::vector{})); + cemu_assert_debug(result.second); + m_activeCommandBufferIt = result.first; + commandBuffer->retain(); + } + else + { + m_activeCommandBufferIt = m_executingCommandBuffers.end(); + } } void CheckForCompletedCommandBuffers(/*MTL::CommandBuffer* commandBuffer, bool erase = true*/) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index f33e527f..8e4d4bc5 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -83,19 +83,6 @@ MetalRenderer::MetalRenderer() m_depthStencilCache = new MetalDepthStencilCache(this); m_samplerCache = new MetalSamplerCache(this); - // Texture readback - m_readbackBuffer = m_device->newBuffer(TEXTURE_READBACK_SIZE, MTL::ResourceStorageModeShared); -#ifdef CEMU_DEBUG_ASSERT - m_readbackBuffer->setLabel(GetLabel("Texture readback buffer", m_readbackBuffer)); -#endif - - // Transform feedback - // HACK: using just LatteStreamout_GetRingBufferSize will cause page faults - m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize() * 4, MTL::ResourceStorageModePrivate); -#ifdef CEMU_DEBUG_ASSERT - m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer)); -#endif - // Occlusion queries m_occlusionQuery.m_resultBuffer = m_device->newBuffer(OCCLUSION_QUERY_POOL_SIZE * sizeof(uint64), MTL::ResourceStorageModeShared); #ifdef CEMU_DEBUG_ASSERT @@ -196,7 +183,13 @@ MetalRenderer::~MetalRenderer() m_nearestSampler->release(); m_linearSampler->release(); - m_readbackBuffer->release(); + if (m_readbackBuffer) + m_readbackBuffer->release(); + + if (m_xfbRingBuffer) + m_xfbRingBuffer->release(); + + m_occlusionQuery.m_resultBuffer->release(); m_commandQueue->release(); m_device->release(); @@ -794,7 +787,7 @@ void MetalRenderer::bufferCache_copy(uint32 srcOffset, uint32 dstOffset, uint32 void MetalRenderer::bufferCache_copyStreamoutToMainBuffer(uint32 srcOffset, uint32 dstOffset, uint32 size) { - CopyBufferToBuffer(m_xfbRingBuffer, srcOffset, m_memoryManager->GetBufferCache(), dstOffset, size, MTL::RenderStageVertex, ALL_MTL_RENDER_STAGES); + CopyBufferToBuffer(GetXfbRingBuffer(), srcOffset, m_memoryManager->GetBufferCache(), dstOffset, size, MTL::RenderStageVertex, ALL_MTL_RENDER_STAGES); } void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, uint32 size) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 3217d09d..abb7f7e5 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -380,11 +380,33 @@ public: return (m_hasUnifiedMemory ? MTL::ResourceStorageModeShared : MTL::ResourceStorageModeManaged); } - MTL::Buffer* GetTextureReadbackBuffer() const + MTL::Buffer* GetTextureReadbackBuffer() { + if (!m_readbackBuffer) + { + m_readbackBuffer = m_device->newBuffer(TEXTURE_READBACK_SIZE, MTL::ResourceStorageModeShared); +#ifdef CEMU_DEBUG_ASSERT + m_readbackBuffer->setLabel(GetLabel("Texture readback buffer", m_readbackBuffer)); +#endif + } + return m_readbackBuffer; } + MTL::Buffer* GetXfbRingBuffer() + { + if (!m_xfbRingBuffer) + { + // HACK: using just LatteStreamout_GetRingBufferSize will cause page faults + m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize() * 4, MTL::ResourceStorageModePrivate); +#ifdef CEMU_DEBUG_ASSERT + m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer)); +#endif + } + + return m_xfbRingBuffer; + } + MTL::Buffer* GetOcclusionQueryResultBuffer() const { return m_occlusionQuery.m_resultBuffer; @@ -460,11 +482,11 @@ private: MTL::Texture* m_nullTexture2D; // Texture readback - MTL::Buffer* m_readbackBuffer; + MTL::Buffer* m_readbackBuffer = nullptr; uint32 m_readbackBufferWriteOffset = 0; // Transform feedback - MTL::Buffer* m_xfbRingBuffer; + MTL::Buffer* m_xfbRingBuffer = nullptr; // Occlusion queries struct