mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-02 05:54:18 +01:00
fix: vertex buffer leaks
This commit is contained in:
parent
caba20da4b
commit
c6ab45a098
@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Metal/Metal.hpp>
|
||||||
|
|
||||||
|
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
|
||||||
|
|
||||||
inline size_t Align(size_t size, size_t alignment)
|
inline size_t Align(size_t size, size_t alignment)
|
||||||
{
|
{
|
||||||
return (size + alignment - 1) & ~(alignment - 1);
|
return (size + alignment - 1) & ~(alignment - 1);
|
||||||
|
@ -70,11 +70,11 @@ MetalVertexBufferCache::~MetalVertexBufferCache()
|
|||||||
for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++)
|
for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++)
|
||||||
{
|
{
|
||||||
auto vertexBufferRange = m_bufferRanges[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)
|
MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride)
|
||||||
{
|
{
|
||||||
auto vertexBufferRange = m_bufferRanges[bufferIndex];
|
auto vertexBufferRange = m_bufferRanges[bufferIndex];
|
||||||
auto& restrideInfo = vertexBufferRange->restrideInfo;
|
auto& restrideInfo = *vertexBufferRange.restrideInfo;
|
||||||
|
|
||||||
if (stride % 4 == 0)
|
if (stride % 4 == 0)
|
||||||
{
|
{
|
||||||
// No restride needed
|
// No restride needed
|
||||||
return {bufferCache, vertexBufferRange->offset};
|
return {bufferCache, vertexBufferRange.offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride)
|
if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride)
|
||||||
{
|
{
|
||||||
// TODO: use compute/void vertex function instead
|
// TODO: use compute/void vertex function instead
|
||||||
size_t newStride = Align(stride, 4);
|
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);
|
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();
|
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);
|
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.memoryInvalidated = false;
|
||||||
restrideInfo.lastStride = newStride;
|
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++)
|
for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++)
|
||||||
{
|
{
|
||||||
auto vertexBufferRange = m_bufferRanges[i];
|
auto vertexBufferRange = m_bufferRanges[i];
|
||||||
if (vertexBufferRange)
|
if (vertexBufferRange.offset != INVALID_OFFSET)
|
||||||
{
|
{
|
||||||
if ((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)))
|
(offset > vertexBufferRange.offset && (offset + size) > (vertexBufferRange.offset + vertexBufferRange.size)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
vertexBufferRange->restrideInfo.memoryInvalidated = true;
|
vertexBufferRange.restrideInfo->memoryInvalidated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Metal/Metal.hpp>
|
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
|
|
||||||
//const uint32 bufferAllocatorIndexShift = 24;
|
//const uint32 bufferAllocatorIndexShift = 24;
|
||||||
|
|
||||||
@ -68,9 +67,9 @@ struct MetalRestrideInfo
|
|||||||
|
|
||||||
struct MetalVertexBufferRange
|
struct MetalVertexBufferRange
|
||||||
{
|
{
|
||||||
size_t offset;
|
size_t offset = INVALID_OFFSET;
|
||||||
size_t size;
|
size_t size;
|
||||||
MetalRestrideInfo& restrideInfo;
|
MetalRestrideInfo* restrideInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalVertexBufferCache
|
class MetalVertexBufferCache
|
||||||
@ -82,19 +81,19 @@ public:
|
|||||||
~MetalVertexBufferCache();
|
~MetalVertexBufferCache();
|
||||||
|
|
||||||
// Vertex buffer cache
|
// 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)
|
void UntrackVertexBuffer(uint32 bufferIndex)
|
||||||
{
|
{
|
||||||
auto& range = m_bufferRanges[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);
|
MetalRestridedBufferRange RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride);
|
||||||
@ -102,7 +101,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
class MetalRenderer* m_mtlr;
|
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);
|
void MemoryRangeChanged(size_t offset, size_t size);
|
||||||
};
|
};
|
||||||
@ -147,7 +146,7 @@ public:
|
|||||||
void CopyBufferCache(size_t srcOffset, size_t dstOffset, size_t size);
|
void CopyBufferCache(size_t srcOffset, size_t dstOffset, size_t size);
|
||||||
|
|
||||||
// Vertex buffer cache
|
// 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);
|
m_vertexBufferCache.TrackVertexBuffer(bufferIndex, offset, size, restrideInfo);
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow)
|
|||||||
|
|
||||||
m_metalLayer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle);
|
m_metalLayer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle);
|
||||||
m_metalLayer->setDevice(m_device);
|
m_metalLayer->setDevice(m_device);
|
||||||
|
// TODO: don't always force sRGB
|
||||||
// TODO: shouldn't this be handled differently?
|
// TODO: shouldn't this be handled differently?
|
||||||
m_metalLayer->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
|
m_metalLayer->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
|
||||||
|
|
||||||
@ -476,7 +477,7 @@ void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, u
|
|||||||
buffer.size = size;
|
buffer.size = size;
|
||||||
buffer.restrideInfo = {};
|
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)
|
void MetalRenderer::buffer_bindUniformBuffer(LatteConst::ShaderType shaderType, uint32 bufferIndex, uint32 offset, uint32 size)
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#define MAX_MTL_TEXTURES 31
|
#define MAX_MTL_TEXTURES 31
|
||||||
#define MAX_MTL_SAMPLERS 16
|
#define MAX_MTL_SAMPLERS 16
|
||||||
|
|
||||||
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
|
|
||||||
|
|
||||||
struct MetalBoundBuffer
|
struct MetalBoundBuffer
|
||||||
{
|
{
|
||||||
bool needsRebind = false;
|
bool needsRebind = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user