mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 22:41:18 +12:00
implement new index cache
This commit is contained in:
parent
800aae4fdb
commit
24ff85b11f
5 changed files with 88 additions and 65 deletions
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue