Cemu/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h
2024-09-21 09:28:46 +02:00

124 lines
3.8 KiB
C++

#pragma once
#include "Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h"
#include "Metal/MTLResource.hpp"
struct MetalRestridedBufferRange
{
MTL::Buffer* buffer;
size_t offset;
};
struct MetalVertexBufferRange
{
size_t offset = INVALID_OFFSET;
size_t size;
MetalRestrideInfo* restrideInfo;
};
class MetalVertexBufferCache
{
public:
friend class MetalMemoryManager;
MetalVertexBufferCache(class MetalRenderer* metalRenderer, MetalDefaultBufferAllocator& bufferAllocator) : m_mtlr{metalRenderer}, m_bufferAllocator{bufferAllocator} {}
~MetalVertexBufferCache();
void SetRestrideBufferPipeline(class MetalHybridComputePipeline* restrideBufferPipeline)
{
m_restrideBufferPipeline = restrideBufferPipeline;
}
void TrackVertexBuffer(uint32 bufferIndex, size_t offset, size_t size, MetalRestrideInfo* restrideInfo)
{
m_bufferRanges[bufferIndex] = MetalVertexBufferRange{offset, size, restrideInfo};
}
void UntrackVertexBuffer(uint32 bufferIndex)
{
auto& range = m_bufferRanges[bufferIndex];
//if (range.restrideInfo->allocation.offset != INVALID_OFFSET)
// m_bufferAllocator.FreeAllocation(range.restrideInfo->allocation);
range.offset = INVALID_OFFSET;
}
MetalRestridedBufferRange RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride);
private:
class MetalRenderer* m_mtlr;
MetalDefaultBufferAllocator& m_bufferAllocator;
class MetalHybridComputePipeline* m_restrideBufferPipeline = nullptr;
MetalVertexBufferRange m_bufferRanges[LATTE_MAX_VERTEX_BUFFERS] = {};
void MemoryRangeChanged(size_t offset, size_t size);
};
class MetalMemoryManager
{
public:
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer, m_mtlr->GetOptimalBufferStorageMode()), m_framePersistentBufferAllocator(metalRenderer, MTL::ResourceStorageModeShared), m_tempBufferAllocator(metalRenderer), m_vertexBufferCache(metalRenderer, m_framePersistentBufferAllocator) {}
~MetalMemoryManager();
// Pipelines
void SetRestrideBufferPipeline(class MetalHybridComputePipeline* restrideBufferPipeline)
{
m_vertexBufferCache.SetRestrideBufferPipeline(restrideBufferPipeline);
}
MetalDefaultBufferAllocator& GetBufferAllocator()
{
return m_bufferAllocator;
}
MetalDefaultBufferAllocator& GetFramePersistentBufferAllocator()
{
return m_framePersistentBufferAllocator;
}
MetalTemporaryBufferAllocator& GetTemporaryBufferAllocator()
{
return m_tempBufferAllocator;
}
MTL::Buffer* GetBufferCache()
{
return m_bufferCache;
}
void* GetTextureUploadBuffer(size_t size);
// Buffer cache
void InitBufferCache(size_t size);
void UploadToBufferCache(const void* data, size_t offset, size_t size);
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)
{
m_vertexBufferCache.TrackVertexBuffer(bufferIndex, offset, size, restrideInfo);
}
void UntrackVertexBuffer(uint32 bufferIndex)
{
m_vertexBufferCache.UntrackVertexBuffer(bufferIndex);
}
MetalRestridedBufferRange RestrideBufferIfNeeded(uint32 bufferIndex, size_t stride)
{
return m_vertexBufferCache.RestrideBufferIfNeeded(m_bufferCache, bufferIndex, stride);
}
private:
class MetalRenderer* m_mtlr;
std::vector<uint8> m_textureUploadBuffer;
MetalDefaultBufferAllocator m_bufferAllocator;
MetalDefaultBufferAllocator m_framePersistentBufferAllocator;
MetalTemporaryBufferAllocator m_tempBufferAllocator;
MetalVertexBufferCache m_vertexBufferCache;
MTL::Buffer* m_bufferCache = nullptr;
};