diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h index 1bf017b2..cb65162e 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h @@ -6,6 +6,7 @@ public: size_t m_bufferAllocatorMemory = 0; // Per frame data + uint32 m_commandBuffers = 0; uint32 m_renderPasses = 0; uint32 m_clears = 0; uint32 m_manualVertexFetchDraws = 0; @@ -17,6 +18,7 @@ public: void ResetPerFrameData() { + m_commandBuffers = 0; m_renderPasses = 0; m_clears = 0; m_manualVertexFetchDraws = 0; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalQuery.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalQuery.cpp index 6e6b14c3..5a60d4ea 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalQuery.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalQuery.cpp @@ -37,9 +37,8 @@ void LatteQueryObjectMtl::end() { m_range.end = m_mtlr->GetOcclusionQueryIndex(); m_mtlr->EndOcclusionQuery(); + + m_commandBuffer = m_mtlr->GetCurrentCommandBuffer()->retain(); if (m_mtlr->IsCommandBufferActive()) - { - m_commandBuffer = m_mtlr->GetCurrentCommandBuffer()->retain(); m_mtlr->RequestSoonCommit(); - } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 96956282..b2b230ba 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -234,7 +234,6 @@ void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC) // Reset the command buffers (they are released by TemporaryBufferAllocator) CommitCommandBuffer(); - m_commandBuffers.clear(); // Release frame persistent buffers m_memoryManager->GetFramePersistentBufferAllocator().ResetAllocations(); @@ -318,12 +317,9 @@ void MetalRenderer::Flush(bool waitIdle) CommitCommandBuffer(); if (waitIdle) { - for (auto commandBuffer : m_commandBuffers) - { - cemu_assert_debug(commandBuffer.m_commited); + cemu_assert_debug(m_currentCommandBuffer.m_commited); - commandBuffer.m_commandBuffer->waitUntilCompleted(); - } + m_currentCommandBuffer.m_commandBuffer->waitUntilCompleted(); } } @@ -448,7 +444,7 @@ void MetalRenderer::AppendOverlayDebugInfo() ImGui::Text("Buffer allocator memory %zuMB", m_performanceMonitor.m_bufferAllocatorMemory / 1024 / 1024); ImGui::Text("--- Metal info (per frame) ---"); - ImGui::Text("Command buffers %zu", m_commandBuffers.size()); + ImGui::Text("Command buffers %u", m_performanceMonitor.m_commandBuffers); ImGui::Text("Render passes %u", m_performanceMonitor.m_renderPasses); ImGui::Text("Clears %u", m_performanceMonitor.m_clears); ImGui::Text("Manual vertex fetch draws %u (mesh draws: %u)", m_performanceMonitor.m_manualVertexFetchDraws, m_performanceMonitor.m_meshDraws); @@ -1427,14 +1423,14 @@ void MetalRenderer::SetSamplerState(MTL::RenderCommandEncoder* renderCommandEnco MTL::CommandBuffer* MetalRenderer::GetCommandBuffer() { - bool needsNewCommandBuffer = (m_commandBuffers.empty() || m_commandBuffers.back().m_commited); + bool needsNewCommandBuffer = (!m_currentCommandBuffer.m_commandBuffer || m_currentCommandBuffer.m_commited); if (needsNewCommandBuffer) { // Debug //m_commandQueue->insertDebugCaptureBoundary(); MTL::CommandBuffer* mtlCommandBuffer = m_commandQueue->commandBuffer(); - m_commandBuffers.push_back({mtlCommandBuffer}); + m_currentCommandBuffer = {mtlCommandBuffer}; m_recordedDrawcalls = 0; m_commitTreshold = m_defaultCommitTreshlod; @@ -1442,11 +1438,14 @@ MTL::CommandBuffer* MetalRenderer::GetCommandBuffer() // Notify memory manager about the new command buffer m_memoryManager->GetTemporaryBufferAllocator().SetActiveCommandBuffer(mtlCommandBuffer); + // Debug + m_performanceMonitor.m_commandBuffers++; + return mtlCommandBuffer; } else { - return m_commandBuffers.back().m_commandBuffer; + return m_currentCommandBuffer.m_commandBuffer; } } @@ -1594,27 +1593,26 @@ void MetalRenderer::EndEncoding() void MetalRenderer::CommitCommandBuffer() { - if (m_commandBuffers.size() != 0) + if (!m_currentCommandBuffer.m_commandBuffer) + return; + + EndEncoding(); + + if (!m_currentCommandBuffer.m_commited) { - EndEncoding(); + // Handled differently, since it seems like Metal doesn't always call the completion handler + //commandBuffer.m_commandBuffer->addCompletedHandler(^(MTL::CommandBuffer*) { + // m_memoryManager->GetTemporaryBufferAllocator().CommandBufferFinished(commandBuffer.m_commandBuffer); + //}); - auto& commandBuffer = m_commandBuffers.back(); - if (!commandBuffer.m_commited) - { - // Handled differently, since it seems like Metal doesn't always call the completion handler - //commandBuffer.m_commandBuffer->addCompletedHandler(^(MTL::CommandBuffer*) { - // m_memoryManager->GetTemporaryBufferAllocator().CommandBufferFinished(commandBuffer.m_commandBuffer); - //}); + m_currentCommandBuffer.m_commandBuffer->commit(); + m_currentCommandBuffer.m_commandBuffer->release(); + m_currentCommandBuffer.m_commited = true; - commandBuffer.m_commandBuffer->commit(); - commandBuffer.m_commandBuffer->release(); - commandBuffer.m_commited = true; + m_memoryManager->GetTemporaryBufferAllocator().SetActiveCommandBuffer(nullptr); - m_memoryManager->GetTemporaryBufferAllocator().SetActiveCommandBuffer(nullptr); - - // Debug - //m_commandQueue->insertDebugCaptureBoundary(); - } + // Debug + //m_commandQueue->insertDebugCaptureBoundary(); } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index baae288d..3ffdaa9e 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -137,7 +137,7 @@ struct MetalState struct MetalCommandBuffer { - MTL::CommandBuffer* m_commandBuffer; + MTL::CommandBuffer* m_commandBuffer = nullptr; bool m_commited = false; }; @@ -280,14 +280,14 @@ public: bool IsCommandBufferActive() const { - return (m_commandBuffers.size() != 0); + return (m_currentCommandBuffer.m_commandBuffer && !m_currentCommandBuffer.m_commited); } MTL::CommandBuffer* GetCurrentCommandBuffer() { - cemu_assert_debug(m_commandBuffers.size() != 0); + cemu_assert_debug(m_currentCommandBuffer.m_commandBuffer); - return m_commandBuffers[m_commandBuffers.size() - 1].m_commandBuffer; + return m_currentCommandBuffer.m_commandBuffer; } void RequestSoonCommit() @@ -431,10 +431,7 @@ public: m_occlusionQuery.m_active = false; if (m_occlusionQuery.m_lastCommandBuffer) m_occlusionQuery.m_lastCommandBuffer->release(); - if (IsCommandBufferActive()) - m_occlusionQuery.m_lastCommandBuffer = GetCurrentCommandBuffer()->retain(); - else - m_occlusionQuery.m_lastCommandBuffer = nullptr; + m_occlusionQuery.m_lastCommandBuffer = GetCurrentCommandBuffer()->retain(); } private: @@ -490,7 +487,7 @@ private: } m_occlusionQuery; // Active objects - std::vector m_commandBuffers; + MetalCommandBuffer m_currentCommandBuffer{}; MetalEncoderType m_encoderType = MetalEncoderType::None; MTL::CommandEncoder* m_commandEncoder = nullptr;