implement new index cache

This commit is contained in:
Samuliak 2025-01-18 09:40:31 +01:00
parent 800aae4fdb
commit 24ff85b11f
No known key found for this signature in database
5 changed files with 88 additions and 65 deletions

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Common/precompiled.h" #include "util/helpers/MemoryPool.h"
#include "Metal/MTLResource.hpp"
#include <utility> #include <utility>
struct MetalBufferRange struct MetalBufferRange
@ -54,7 +54,7 @@ public:
return m_buffers[bufferIndex].m_buffer; return m_buffers[bufferIndex].m_buffer;
} }
MetalBufferAllocation GetBufferAllocation(size_t size) MetalBufferAllocation GetAllocation(size_t size)
{ {
// Align the size // Align the size
size = Align(size, 128); size = Align(size, 128);
@ -121,29 +121,6 @@ public:
return allocation; return allocation;
} }
void FreeAllocation(MetalBufferAllocation& allocation)
{
MetalBufferRange range;
range.offset = allocation.offset;
range.size = allocation.size;
allocation.offset = INVALID_OFFSET;
// Find the correct position to insert the free range
auto& buffer = m_buffers[allocation.bufferIndex];
for (uint32 i = 0; i < buffer.m_freeRanges.size(); i++)
{
auto& freeRange = buffer.m_freeRanges[i];
if (freeRange.offset + freeRange.size == range.offset)
{
freeRange.size += range.size;
return;
}
}
buffer.m_freeRanges.push_back(range);
}
protected: protected:
class MetalRenderer* m_mtlr; class MetalRenderer* m_mtlr;
@ -276,7 +253,7 @@ public:
m_executingCommandBuffers.erase(it); m_executingCommandBuffers.erase(it);
} }
MTL::Buffer* GetBuffer(uint32 bufferIndex) void MarkBufferAsUsed(uint32 bufferIndex)
{ {
cemu_assert_debug(m_activeCommandBuffer); cemu_assert_debug(m_activeCommandBuffer);
@ -287,8 +264,13 @@ public:
buffer.m_data.m_commandBufferCount++; buffer.m_data.m_commandBufferCount++;
buffer.m_data.m_lastCommandBuffer = m_activeCommandBuffer; buffer.m_data.m_lastCommandBuffer = m_activeCommandBuffer;
} }
}
return buffer.m_buffer; MTL::Buffer* GetBuffer(uint32 bufferIndex)
{
MarkBufferAsUsed(bufferIndex);
return m_buffers[bufferIndex].m_buffer;
} }
MTL::Buffer* GetBufferOutsideOfCommandBuffer(uint32 bufferIndex) MTL::Buffer* GetBufferOutsideOfCommandBuffer(uint32 bufferIndex)
@ -296,6 +278,49 @@ public:
return m_buffers[bufferIndex].m_buffer; return m_buffers[bufferIndex].m_buffer;
} }
MetalBufferAllocation* GetAllocationPtr(size_t size)
{
MetalBufferAllocation* allocation = m_poolAllocatorReservation.allocObj();
*allocation = GetAllocation(size);
LockBuffer(allocation->bufferIndex);
return allocation;
}
void FreeAllocation(MetalBufferAllocation& allocation)
{
// TODO
/*
MetalBufferRange range;
range.offset = allocation.offset;
range.size = allocation.size;
allocation.offset = INVALID_OFFSET;
// Find the correct position to insert the free range
auto& buffer = m_buffers[allocation.bufferIndex];
for (uint32 i = 0; i < buffer.m_freeRanges.size(); i++)
{
auto& freeRange = buffer.m_freeRanges[i];
if (freeRange.offset + freeRange.size == range.offset)
{
freeRange.size += range.size;
return;
}
}
buffer.m_freeRanges.push_back(range);
*/
UnlockBuffer(allocation.bufferIndex);
}
void FreeAllocation(MetalBufferAllocation* allocation)
{
FreeAllocation(*allocation);
m_poolAllocatorReservation.freeObj(allocation);
}
/* /*
MetalBufferAllocation GetBufferAllocation(size_t size) MetalBufferAllocation GetBufferAllocation(size_t size)
{ {
@ -350,5 +375,7 @@ private:
std::map<MTL::CommandBuffer*, std::vector<uint32>> m_executingCommandBuffers; std::map<MTL::CommandBuffer*, std::vector<uint32>> m_executingCommandBuffers;
std::map<MTL::CommandBuffer*, std::vector<uint32>>::iterator m_activeCommandBufferIt; std::map<MTL::CommandBuffer*, std::vector<uint32>>::iterator m_activeCommandBufferIt;
MemoryPool<MetalBufferAllocation> m_poolAllocatorReservation{32};
uint16 m_framesSinceBackBufferAccess = 0; uint16 m_framesSinceBackBufferAccess = 0;
}; };

View file

@ -73,7 +73,7 @@ void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, si
if (m_bufferCacheMode == BufferCacheMode::DevicePrivate) if (m_bufferCacheMode == BufferCacheMode::DevicePrivate)
{ {
auto allocation = m_tempBufferAllocator.GetBufferAllocation(size); auto allocation = m_tempBufferAllocator.GetAllocation(size);
auto buffer = m_tempBufferAllocator.GetBufferOutsideOfCommandBuffer(allocation.bufferIndex); auto buffer = m_tempBufferAllocator.GetBufferOutsideOfCommandBuffer(allocation.bufferIndex);
memcpy((uint8*)buffer->contents() + allocation.offset, data, size); memcpy((uint8*)buffer->contents() + allocation.offset, data, size);
@ -82,8 +82,8 @@ void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, si
m_mtlr->CopyBufferToBuffer(buffer, allocation.offset, m_bufferCache, offset, size, ALL_MTL_RENDER_STAGES, ALL_MTL_RENDER_STAGES); m_mtlr->CopyBufferToBuffer(buffer, allocation.offset, m_bufferCache, offset, size, ALL_MTL_RENDER_STAGES, ALL_MTL_RENDER_STAGES);
// Make sure the buffer has the right command buffer // Mark buffer as used
m_tempBufferAllocator.GetBuffer(allocation.bufferIndex); // TODO: make a helper function for this m_tempBufferAllocator.MarkBufferAsUsed(allocation.bufferIndex);
// We can now safely unlock the buffer // We can now safely unlock the buffer
m_tempBufferAllocator.UnlockBuffer(allocation.bufferIndex); m_tempBufferAllocator.UnlockBuffer(allocation.bufferIndex);

View file

@ -683,7 +683,7 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
// Allocate a temporary buffer // Allocate a temporary buffer
auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator(); auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
auto allocation = bufferAllocator.GetBufferAllocation(compressedImageSize); auto allocation = bufferAllocator.GetAllocation(compressedImageSize);
auto buffer = bufferAllocator.GetBuffer(allocation.bufferIndex); auto buffer = bufferAllocator.GetBuffer(allocation.bufferIndex);
// Copy the data to the temporary buffer // Copy the data to the temporary buffer
@ -1067,9 +1067,9 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
uint32 hostIndexCount; uint32 hostIndexCount;
uint32 indexMin = 0; uint32 indexMin = 0;
uint32 indexMax = 0; uint32 indexMax = 0;
uint32 indexBufferOffset = 0; Renderer::IndexAllocation indexAllocation;
uint32 indexBufferIndex = 0; LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation);
LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexBufferOffset, indexBufferIndex); MetalBufferAllocation* indexAllocationMtl = static_cast<MetalBufferAllocation*>(indexAllocation.rendererInternal);
// Buffer cache // Buffer cache
if (m_memoryManager->UseHostMemoryForCache()) if (m_memoryManager->UseHostMemoryForCache())
@ -1312,16 +1312,13 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
if (hostIndexType != INDEX_TYPE::NONE) if (hostIndexType != INDEX_TYPE::NONE)
{ {
auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator(); auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
indexBuffer = bufferAllocator.GetBuffer(indexBufferIndex); indexBuffer = bufferAllocator.GetBuffer(indexAllocationMtl->bufferIndex);
// We have already retrieved the buffer, no need for it to be locked anymore
bufferAllocator.UnlockBuffer(indexBufferIndex);
} }
if (usesGeometryShader) if (usesGeometryShader)
{ {
if (indexBuffer) if (indexBuffer)
SetBuffer(renderCommandEncoder, METAL_SHADER_TYPE_OBJECT, indexBuffer, indexBufferOffset, vertexShader->resourceMapping.indexBufferBinding); SetBuffer(renderCommandEncoder, METAL_SHADER_TYPE_OBJECT, indexBuffer, indexAllocationMtl->offset, vertexShader->resourceMapping.indexBufferBinding);
uint8 hostIndexTypeU8 = (uint8)hostIndexType; uint8 hostIndexTypeU8 = (uint8)hostIndexType;
renderCommandEncoder->setObjectBytes(&hostIndexTypeU8, sizeof(hostIndexTypeU8), vertexShader->resourceMapping.indexTypeBinding); renderCommandEncoder->setObjectBytes(&hostIndexTypeU8, sizeof(hostIndexTypeU8), vertexShader->resourceMapping.indexTypeBinding);
@ -1352,7 +1349,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
if (indexBuffer) if (indexBuffer)
{ {
auto mtlIndexType = GetMtlIndexType(hostIndexType); auto mtlIndexType = GetMtlIndexType(hostIndexType);
renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, indexBufferOffset, instanceCount, baseVertex, baseInstance); renderCommandEncoder->drawIndexedPrimitives(mtlPrimitiveType, hostIndexCount, mtlIndexType, indexBuffer, indexAllocationMtl->offset, instanceCount, baseVertex, baseInstance);
} }
else else
{ {
@ -1492,29 +1489,27 @@ void MetalRenderer::draw_handleSpecialState5()
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3)); renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
} }
void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) Renderer::IndexAllocation MetalRenderer::indexData_reserveIndexMemory(uint32 size)
{ {
auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator(); auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
auto allocation = bufferAllocator.GetBufferAllocation(size); auto allocation = bufferAllocator.GetAllocationPtr(size);
offset = allocation.offset;
bufferIndex = allocation.bufferIndex;
// Lock the buffer so that it doesn't get released return {allocation->data, allocation};
bufferAllocator.LockBuffer(allocation.bufferIndex);
return allocation.data;
} }
void MetalRenderer::indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) void MetalRenderer::indexData_releaseIndexMemory(IndexAllocation& allocation)
{ {
// Do nothing auto allocationMtl = static_cast<MetalBufferAllocation*>(allocation.rendererInternal);
/*
if (!HasUnifiedMemory()) auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
{ bufferAllocator.FreeAllocation(allocationMtl);
auto buffer = m_memoryManager->GetTemporaryBufferAllocator().GetBufferOutsideOfCommandBuffer(bufferIndex); }
buffer->didModifyRange(NS::Range(offset, size));
} void MetalRenderer::indexData_uploadIndexMemory(IndexAllocation& allocation)
*/ {
// TODO: uncomment
//auto& bufferAllocator = m_memoryManager->GetBufferAllocator();
//bufferAllocator.FlushAllocation(static_cast<MetalBufferAllocation*>(allocation.rendererInternal));
} }
LatteQueryObject* MetalRenderer::occlusionQuery_create() { LatteQueryObject* MetalRenderer::occlusionQuery_create() {
@ -2102,9 +2097,9 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
} }
} }
auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
size_t size = shader->uniform.uniformRangeSize; size_t size = shader->uniform.uniformRangeSize;
auto supportBuffer = bufferAllocator.GetBufferAllocation(size); auto& bufferAllocator = m_memoryManager->GetTemporaryBufferAllocator();
auto supportBuffer = bufferAllocator.GetAllocation(size);
memcpy(supportBuffer.data, supportBufferData, size); memcpy(supportBuffer.data, supportBufferData, size);
auto buffer = bufferAllocator.GetBuffer(supportBuffer.bufferIndex); auto buffer = bufferAllocator.GetBuffer(supportBuffer.bufferIndex);
//if (!HasUnifiedMemory()) //if (!HasUnifiedMemory())

View file

@ -271,8 +271,9 @@ public:
void draw_handleSpecialState5(); void draw_handleSpecialState5();
// index // index
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override; IndexAllocation indexData_reserveIndexMemory(uint32 size) override;
void indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) override; void indexData_releaseIndexMemory(IndexAllocation& allocation) override;
void indexData_uploadIndexMemory(IndexAllocation& allocation) override;
// occlusion queries // occlusion queries
LatteQueryObject* occlusionQuery_create() override; LatteQueryObject* occlusionQuery_create() override;

View file

@ -15,8 +15,8 @@
#define METAL_AIR_CACHE_BLOCK_COUNT (METAL_AIR_CACHE_SIZE / 512) #define METAL_AIR_CACHE_BLOCK_COUNT (METAL_AIR_CACHE_SIZE / 512)
static bool s_isLoadingShadersMtl{false}; static bool s_isLoadingShadersMtl{false};
static bool s_hasRAMFilesystem{false}; //static bool s_hasRAMFilesystem{false};
class FileCache* s_airCache{nullptr}; //class FileCache* s_airCache{nullptr};
extern std::atomic_int g_compiled_shaders_total; extern std::atomic_int g_compiled_shaders_total;
extern std::atomic_int g_compiled_shaders_async; extern std::atomic_int g_compiled_shaders_async;
@ -190,6 +190,7 @@ void RendererShaderMtl::ShaderCacheLoading_end()
void RendererShaderMtl::ShaderCacheLoading_Close() void RendererShaderMtl::ShaderCacheLoading_Close()
{ {
// Close the AIR cache // Close the AIR cache
/*
if (s_airCache) if (s_airCache)
{ {
delete s_airCache; delete s_airCache;
@ -197,7 +198,6 @@ void RendererShaderMtl::ShaderCacheLoading_Close()
} }
// Close RAM filesystem // Close RAM filesystem
/*
if (s_hasRAMFilesystem) if (s_hasRAMFilesystem)
executeCommand("diskutil eject {}", METAL_AIR_CACHE_PATH); executeCommand("diskutil eject {}", METAL_AIR_CACHE_PATH);
*/ */