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
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Common/precompiled.h"
#include "Metal/MTLResource.hpp"
#include "util/helpers/MemoryPool.h"
#include <utility>
struct MetalBufferRange
@ -54,7 +54,7 @@ public:
return m_buffers[bufferIndex].m_buffer;
}
MetalBufferAllocation GetBufferAllocation(size_t size)
MetalBufferAllocation GetAllocation(size_t size)
{
// Align the size
size = Align(size, 128);
@ -121,29 +121,6 @@ public:
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:
class MetalRenderer* m_mtlr;
@ -276,7 +253,7 @@ public:
m_executingCommandBuffers.erase(it);
}
MTL::Buffer* GetBuffer(uint32 bufferIndex)
void MarkBufferAsUsed(uint32 bufferIndex)
{
cemu_assert_debug(m_activeCommandBuffer);
@ -287,8 +264,13 @@ public:
buffer.m_data.m_commandBufferCount++;
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)
@ -296,6 +278,49 @@ public:
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)
{
@ -350,5 +375,7 @@ private:
std::map<MTL::CommandBuffer*, std::vector<uint32>> m_executingCommandBuffers;
std::map<MTL::CommandBuffer*, std::vector<uint32>>::iterator m_activeCommandBufferIt;
MemoryPool<MetalBufferAllocation> m_poolAllocatorReservation{32};
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)
{
auto allocation = m_tempBufferAllocator.GetBufferAllocation(size);
auto allocation = m_tempBufferAllocator.GetAllocation(size);
auto buffer = m_tempBufferAllocator.GetBufferOutsideOfCommandBuffer(allocation.bufferIndex);
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);
// Make sure the buffer has the right command buffer
m_tempBufferAllocator.GetBuffer(allocation.bufferIndex); // TODO: make a helper function for this
// Mark buffer as used
m_tempBufferAllocator.MarkBufferAsUsed(allocation.bufferIndex);
// We can now safely unlock the buffer
m_tempBufferAllocator.UnlockBuffer(allocation.bufferIndex);

View file

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

View file

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

View file

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