Skip to content

Commit c6ab45a

Browse files
committed
fix: vertex buffer leaks
1 parent caba20d commit c6ab45a

File tree

5 files changed

+30
-27
lines changed

5 files changed

+30
-27
lines changed

src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#pragma once
22

3+
#include <Metal/Metal.hpp>
4+
5+
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
6+
37
inline size_t Align(size_t size, size_t alignment)
48
{
59
return (size + alignment - 1) & ~(alignment - 1);

src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ MetalVertexBufferCache::~MetalVertexBufferCache()
7070
for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++)
7171
{
7272
auto vertexBufferRange = m_bufferRanges[i];
73-
if (vertexBufferRange)
73+
if (vertexBufferRange.offset != INVALID_OFFSET)
7474
{
75-
if (vertexBufferRange->restrideInfo.buffer)
75+
if (vertexBufferRange.restrideInfo->buffer)
7676
{
77-
vertexBufferRange->restrideInfo.buffer->release();
77+
vertexBufferRange.restrideInfo->buffer->release();
7878
}
7979
}
8080
}
@@ -83,29 +83,30 @@ MetalVertexBufferCache::~MetalVertexBufferCache()
8383
MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride)
8484
{
8585
auto vertexBufferRange = m_bufferRanges[bufferIndex];
86-
auto& restrideInfo = vertexBufferRange->restrideInfo;
86+
auto& restrideInfo = *vertexBufferRange.restrideInfo;
8787

8888
if (stride % 4 == 0)
8989
{
9090
// No restride needed
91-
return {bufferCache, vertexBufferRange->offset};
91+
return {bufferCache, vertexBufferRange.offset};
9292
}
9393

9494
if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride)
9595
{
9696
// TODO: use compute/void vertex function instead
9797
size_t newStride = Align(stride, 4);
98-
size_t newSize = vertexBufferRange->size / stride * newStride;
98+
size_t newSize = vertexBufferRange.size / stride * newStride;
9999
restrideInfo.buffer = m_mtlr->GetDevice()->newBuffer(newSize, MTL::StorageModeShared);
100100

101-
uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange->offset;
101+
uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange.offset;
102102
uint8* newPtr = (uint8*)restrideInfo.buffer->contents();
103103

104-
for (size_t elem = 0; elem < vertexBufferRange->size / stride; elem++)
104+
for (size_t elem = 0; elem < vertexBufferRange.size / stride; elem++)
105105
{
106106
memcpy(newPtr + elem * newStride, oldPtr + elem * stride, stride);
107107
}
108-
debug_printf("Restrided vertex buffer (old stride: %zu, new stride: %zu, old size: %zu, new size: %zu)\n", stride, newStride, vertexBufferRange->size, newSize);
108+
// TODO: remove
109+
debug_printf("Restrided vertex buffer (old stride: %zu, new stride: %zu, old size: %zu, new size: %zu)\n", stride, newStride, vertexBufferRange.size, newSize);
109110

110111
restrideInfo.memoryInvalidated = false;
111112
restrideInfo.lastStride = newStride;
@@ -119,15 +120,15 @@ void MetalVertexBufferCache::MemoryRangeChanged(size_t offset, size_t size)
119120
for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++)
120121
{
121122
auto vertexBufferRange = m_bufferRanges[i];
122-
if (vertexBufferRange)
123+
if (vertexBufferRange.offset != INVALID_OFFSET)
123124
{
124-
if ((offset < vertexBufferRange->offset && (offset + size) < (vertexBufferRange->offset + vertexBufferRange->size)) ||
125-
(offset > vertexBufferRange->offset && (offset + size) > (vertexBufferRange->offset + vertexBufferRange->size)))
125+
if ((offset < vertexBufferRange.offset && (offset + size) < (vertexBufferRange.offset + vertexBufferRange.size)) ||
126+
(offset > vertexBufferRange.offset && (offset + size) > (vertexBufferRange.offset + vertexBufferRange.size)))
126127
{
127128
continue;
128129
}
129130

130-
vertexBufferRange->restrideInfo.memoryInvalidated = true;
131+
vertexBufferRange.restrideInfo->memoryInvalidated = true;
131132
}
132133
}
133134
}

src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#pragma once
22

3-
#include <Metal/Metal.hpp>
4-
53
#include "Cafe/HW/Latte/ISA/LatteReg.h"
64
#include "Cafe/HW/Latte/Core/LatteConst.h"
5+
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
76

87
//const uint32 bufferAllocatorIndexShift = 24;
98

@@ -68,9 +67,9 @@ struct MetalRestrideInfo
6867

6968
struct MetalVertexBufferRange
7069
{
71-
size_t offset;
70+
size_t offset = INVALID_OFFSET;
7271
size_t size;
73-
MetalRestrideInfo& restrideInfo;
72+
MetalRestrideInfo* restrideInfo;
7473
};
7574

7675
class MetalVertexBufferCache
@@ -82,27 +81,27 @@ class MetalVertexBufferCache
8281
~MetalVertexBufferCache();
8382

8483
// Vertex buffer cache
85-
void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo& restrideInfo)
84+
void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo* restrideInfo)
8685
{
87-
m_bufferRanges[bufferIndex] = new MetalVertexBufferRange{offset, size, restrideInfo};
86+
m_bufferRanges[bufferIndex] = MetalVertexBufferRange{offset, size, restrideInfo};
8887
}
8988

9089
void UntrackVertexBuffer(uint32 bufferIndex)
9190
{
9291
auto& range = m_bufferRanges[bufferIndex];
93-
if (range->restrideInfo.buffer)
92+
if (range.restrideInfo->buffer)
9493
{
95-
range->restrideInfo.buffer->release();
94+
range.restrideInfo->buffer->release();
9695
}
97-
range = nullptr;
96+
range.offset = INVALID_OFFSET;
9897
}
9998

10099
MetalRestridedBufferRange RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride);
101100

102101
private:
103102
class MetalRenderer* m_mtlr;
104103

105-
MetalVertexBufferRange* m_bufferRanges[LATTE_MAX_VERTEX_BUFFERS] = {nullptr};
104+
MetalVertexBufferRange m_bufferRanges[LATTE_MAX_VERTEX_BUFFERS] = {};
106105

107106
void MemoryRangeChanged(size_t offset, size_t size);
108107
};
@@ -147,7 +146,7 @@ class MetalMemoryManager
147146
void CopyBufferCache(size_t srcOffset, size_t dstOffset, size_t size);
148147

149148
// Vertex buffer cache
150-
void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo& restrideInfo)
149+
void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo* restrideInfo)
151150
{
152151
m_vertexBufferCache.TrackVertexBuffer(bufferIndex, offset, size, restrideInfo);
153152
}

src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow)
7777

7878
m_metalLayer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle);
7979
m_metalLayer->setDevice(m_device);
80+
// TODO: don't always force sRGB
8081
// TODO: shouldn't this be handled differently?
8182
m_metalLayer->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
8283

@@ -476,7 +477,7 @@ void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, u
476477
buffer.size = size;
477478
buffer.restrideInfo = {};
478479

479-
m_memoryManager->TrackVertexBuffer(bufferIndex, offset, size, buffer.restrideInfo);
480+
m_memoryManager->TrackVertexBuffer(bufferIndex, offset, size, &buffer.restrideInfo);
480481
}
481482

482483
void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size)

src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#define MAX_MTL_TEXTURES 31
1717
#define MAX_MTL_SAMPLERS 16
1818

19-
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
20-
2119
struct MetalBoundBuffer
2220
{
2321
bool needsRebind = false;

0 commit comments

Comments
 (0)