diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h index 209b1395..102ccdc9 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h @@ -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 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> m_executingCommandBuffers; std::map>::iterator m_activeCommandBufferIt; + MemoryPool m_poolAllocatorReservation{32}; + uint16 m_framesSinceBackBufferAccess = 0; }; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp index 8b9ac89f..25d82d5f 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp @@ -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); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 83c39b5c..a5d50c46 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -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(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(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(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()) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 760ad6bc..5a1dbbf5 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -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; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp index 9e6d3b9c..07073e08 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp @@ -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); */