From c6ab45a098b8ab03e7f4cd32558c3e0245747c96 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Sun, 11 Aug 2024 14:17:40 +0200 Subject: [PATCH] fix: vertex buffer leaks --- .../HW/Latte/Renderer/Metal/MetalCommon.h | 4 +++ .../Renderer/Metal/MetalMemoryManager.cpp | 27 ++++++++++--------- .../Latte/Renderer/Metal/MetalMemoryManager.h | 21 +++++++-------- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 3 ++- .../HW/Latte/Renderer/Metal/MetalRenderer.h | 2 -- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h index 2a2713e5..aa71731e 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h @@ -1,5 +1,9 @@ #pragma once +#include + +constexpr size_t INVALID_OFFSET = std::numeric_limits::max(); + inline size_t Align(size_t size, size_t alignment) { return (size + alignment - 1) & ~(alignment - 1); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp index 40832aa3..09e07cd9 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp @@ -70,11 +70,11 @@ MetalVertexBufferCache::~MetalVertexBufferCache() for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++) { auto vertexBufferRange = m_bufferRanges[i]; - if (vertexBufferRange) + if (vertexBufferRange.offset != INVALID_OFFSET) { - if (vertexBufferRange->restrideInfo.buffer) + if (vertexBufferRange.restrideInfo->buffer) { - vertexBufferRange->restrideInfo.buffer->release(); + vertexBufferRange.restrideInfo->buffer->release(); } } } @@ -83,29 +83,30 @@ MetalVertexBufferCache::~MetalVertexBufferCache() MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride) { auto vertexBufferRange = m_bufferRanges[bufferIndex]; - auto& restrideInfo = vertexBufferRange->restrideInfo; + auto& restrideInfo = *vertexBufferRange.restrideInfo; if (stride % 4 == 0) { // No restride needed - return {bufferCache, vertexBufferRange->offset}; + return {bufferCache, vertexBufferRange.offset}; } if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride) { // TODO: use compute/void vertex function instead size_t newStride = Align(stride, 4); - size_t newSize = vertexBufferRange->size / stride * newStride; + size_t newSize = vertexBufferRange.size / stride * newStride; restrideInfo.buffer = m_mtlr->GetDevice()->newBuffer(newSize, MTL::StorageModeShared); - uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange->offset; + uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange.offset; uint8* newPtr = (uint8*)restrideInfo.buffer->contents(); - for (size_t elem = 0; elem < vertexBufferRange->size / stride; elem++) + for (size_t elem = 0; elem < vertexBufferRange.size / stride; elem++) { memcpy(newPtr + elem * newStride, oldPtr + elem * stride, stride); } - debug_printf("Restrided vertex buffer (old stride: %zu, new stride: %zu, old size: %zu, new size: %zu)\n", stride, newStride, vertexBufferRange->size, newSize); + // TODO: remove + debug_printf("Restrided vertex buffer (old stride: %zu, new stride: %zu, old size: %zu, new size: %zu)\n", stride, newStride, vertexBufferRange.size, newSize); restrideInfo.memoryInvalidated = false; restrideInfo.lastStride = newStride; @@ -119,15 +120,15 @@ void MetalVertexBufferCache::MemoryRangeChanged(size_t offset, size_t size) for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++) { auto vertexBufferRange = m_bufferRanges[i]; - if (vertexBufferRange) + if (vertexBufferRange.offset != INVALID_OFFSET) { - if ((offset < vertexBufferRange->offset && (offset + size) < (vertexBufferRange->offset + vertexBufferRange->size)) || - (offset > vertexBufferRange->offset && (offset + size) > (vertexBufferRange->offset + vertexBufferRange->size))) + if ((offset < vertexBufferRange.offset && (offset + size) < (vertexBufferRange.offset + vertexBufferRange.size)) || + (offset > vertexBufferRange.offset && (offset + size) > (vertexBufferRange.offset + vertexBufferRange.size))) { continue; } - vertexBufferRange->restrideInfo.memoryInvalidated = true; + vertexBufferRange.restrideInfo->memoryInvalidated = true; } } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h index 93011ae3..4f875687 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h @@ -1,9 +1,8 @@ #pragma once -#include - #include "Cafe/HW/Latte/ISA/LatteReg.h" #include "Cafe/HW/Latte/Core/LatteConst.h" +#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" //const uint32 bufferAllocatorIndexShift = 24; @@ -68,9 +67,9 @@ struct MetalRestrideInfo struct MetalVertexBufferRange { - size_t offset; + size_t offset = INVALID_OFFSET; size_t size; - MetalRestrideInfo& restrideInfo; + MetalRestrideInfo* restrideInfo; }; class MetalVertexBufferCache @@ -82,19 +81,19 @@ public: ~MetalVertexBufferCache(); // Vertex buffer cache - void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo& restrideInfo) + void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo* restrideInfo) { - m_bufferRanges[bufferIndex] = new MetalVertexBufferRange{offset, size, restrideInfo}; + m_bufferRanges[bufferIndex] = MetalVertexBufferRange{offset, size, restrideInfo}; } void UntrackVertexBuffer(uint32 bufferIndex) { auto& range = m_bufferRanges[bufferIndex]; - if (range->restrideInfo.buffer) + if (range.restrideInfo->buffer) { - range->restrideInfo.buffer->release(); + range.restrideInfo->buffer->release(); } - range = nullptr; + range.offset = INVALID_OFFSET; } MetalRestridedBufferRange RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride); @@ -102,7 +101,7 @@ public: private: class MetalRenderer* m_mtlr; - MetalVertexBufferRange* m_bufferRanges[LATTE_MAX_VERTEX_BUFFERS] = {nullptr}; + MetalVertexBufferRange m_bufferRanges[LATTE_MAX_VERTEX_BUFFERS] = {}; void MemoryRangeChanged(size_t offset, size_t size); }; @@ -147,7 +146,7 @@ public: void CopyBufferCache(size_t srcOffset, size_t dstOffset, size_t size); // Vertex buffer cache - void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo& restrideInfo) + void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo* restrideInfo) { m_vertexBufferCache.TrackVertexBuffer(bufferIndex, offset, size, restrideInfo); } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 3bef372b..c3d27865 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -77,6 +77,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow) m_metalLayer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle); m_metalLayer->setDevice(m_device); + // TODO: don't always force sRGB // TODO: shouldn't this be handled differently? m_metalLayer->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB); @@ -476,7 +477,7 @@ void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, u buffer.size = size; buffer.restrideInfo = {}; - m_memoryManager->TrackVertexBuffer(bufferIndex, offset, size, buffer.restrideInfo); + m_memoryManager->TrackVertexBuffer(bufferIndex, offset, size, &buffer.restrideInfo); } void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, 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 f70eec2c..6bba8c74 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -16,8 +16,6 @@ #define MAX_MTL_TEXTURES 31 #define MAX_MTL_SAMPLERS 16 -constexpr size_t INVALID_OFFSET = std::numeric_limits::max(); - struct MetalBoundBuffer { bool needsRebind = false;