diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp index ef6871a7..d14e9678 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.cpp @@ -70,17 +70,6 @@ MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size, siz MetalVertexBufferCache::~MetalVertexBufferCache() { - for (uint32 i = 0; i < LATTE_MAX_VERTEX_BUFFERS; i++) - { - auto vertexBufferRange = m_bufferRanges[i]; - if (vertexBufferRange.offset != INVALID_OFFSET) - { - if (vertexBufferRange.restrideInfo->buffer) - { - vertexBufferRange.restrideInfo->buffer->release(); - } - } - } } MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride) @@ -94,17 +83,12 @@ MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Bu return {bufferCache, vertexBufferRange.offset}; } + auto buffer = m_bufferAllocator->GetBuffer(restrideInfo.allocation.bufferIndex); if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride) { size_t newStride = Align(stride, 4); size_t newSize = vertexBufferRange.size / stride * newStride; - if (!restrideInfo.buffer || newSize != restrideInfo.buffer->length()) - { - if (restrideInfo.buffer) - restrideInfo.buffer->release(); - // TODO: use one big buffer for all restrided buffers - restrideInfo.buffer = m_mtlr->GetDevice()->newBuffer(newSize, MTL::StorageModeShared); - } + restrideInfo.allocation = m_bufferAllocator->GetBufferAllocation(newSize, 4); //uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange.offset; //uint8* newPtr = (uint8*)restrideInfo.buffer->contents(); @@ -120,8 +104,8 @@ MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Bu auto renderCommandEncoder = static_cast(m_mtlr->GetCommandEncoder()); renderCommandEncoder->setRenderPipelineState(m_restrideBufferPipeline->GetRenderPipelineState()); - MTL::Buffer* buffers[] = {bufferCache, restrideInfo.buffer}; - size_t offsets[] = {vertexBufferRange.offset, 0}; + MTL::Buffer* buffers[] = {bufferCache, buffer}; + size_t offsets[] = {vertexBufferRange.offset, restrideInfo.allocation.bufferOffset}; renderCommandEncoder->setVertexBuffers(buffers, offsets, NS::Range(0, 2)); struct @@ -133,7 +117,8 @@ MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Bu renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypePoint, NS::UInteger(0), vertexBufferRange.size / stride); - MTL::Resource* barrierBuffers[] = {restrideInfo.buffer}; + // TODO: restride in one call? + MTL::Resource* barrierBuffers[] = {buffer}; renderCommandEncoder->memoryBarrier(barrierBuffers, 1, MTL::RenderStageVertex, MTL::RenderStageVertex); } else @@ -146,7 +131,7 @@ MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Bu restrideInfo.lastStride = newStride; } - return {restrideInfo.buffer, 0}; + return {buffer, restrideInfo.allocation.bufferOffset}; } void MetalVertexBufferCache::MemoryRangeChanged(size_t offset, size_t size) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h index 0fc55936..d3588fd5 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h @@ -10,7 +10,12 @@ struct MetalBufferAllocation { void* data; uint32 bufferIndex; - size_t bufferOffset; + size_t bufferOffset = INVALID_OFFSET; + + bool IsValid() const + { + return bufferOffset != INVALID_OFFSET; + } }; struct MetalBufferRange @@ -62,7 +67,7 @@ struct MetalRestrideInfo { bool memoryInvalidated = true; size_t lastStride = 0; - MTL::Buffer* buffer = nullptr; + MetalBufferAllocation allocation{}; }; struct MetalVertexBufferRange @@ -77,7 +82,7 @@ class MetalVertexBufferCache public: friend class MetalMemoryManager; - MetalVertexBufferCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {} + MetalVertexBufferCache(class MetalRenderer* metalRenderer, MetalBufferAllocator* bufferAllocator) : m_mtlr{metalRenderer}, m_bufferAllocator{bufferAllocator} {} ~MetalVertexBufferCache(); void SetRestrideBufferPipeline(class MetalHybridComputePipeline* restrideBufferPipeline) @@ -93,10 +98,6 @@ public: void UntrackVertexBuffer(uint32 bufferIndex) { auto& range = m_bufferRanges[bufferIndex]; - if (range.restrideInfo->buffer) - { - range.restrideInfo->buffer->release(); - } range.offset = INVALID_OFFSET; } @@ -104,6 +105,7 @@ public: private: class MetalRenderer* m_mtlr; + MetalBufferAllocator* m_bufferAllocator; class MetalHybridComputePipeline* m_restrideBufferPipeline = nullptr; @@ -115,7 +117,7 @@ private: class MetalMemoryManager { public: - MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer), m_vertexBufferCache(metalRenderer) {} + MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer), m_vertexBufferCache(metalRenderer, &m_bufferAllocator) {} ~MetalMemoryManager(); // Pipelines diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 3c1b59e5..e55be3e2 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -795,7 +795,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 } // Render pipeline state - MTL::RenderPipelineState* renderPipelineState = m_pipelineCache->GetPipelineState(fetchShader, vertexShader, pixelShader, m_state.m_activeFBO, LatteGPUState.contextNew); + MTL::RenderPipelineState* renderPipelineState = m_pipelineCache->GetPipelineState(fetchShader, vertexShader, pixelShader, m_state.m_lastUsedFBO, LatteGPUState.contextNew); renderCommandEncoder->setRenderPipelineState(renderPipelineState); // Uniform buffers, textures and samplers