From 48efdb18daecf0164bd2ca5f35ff157596e6d393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 22 Jun 2026 00:28:50 -0700 Subject: [PATCH] Metal: Implement timer queries. Closes #3774. (#3778) --- src/renderer_mtl.cpp | 39 ++++++++++++++++++++++----------------- src/renderer_mtl.h | 2 +- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 2bb32d48b..3202a28ee 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -4613,9 +4613,16 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ra.clear(); } + static constexpr uint64_t kNanosecondsPerSecond = UINT64_C(1000000000); + void TimerQueryMtl::init() { - m_frequency = bx::getHPFrequency(); + m_frequency = kNanosecondsPerSecond; + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) + { + m_result[ii].reset(); + } } void TimerQueryMtl::shutdown() @@ -4624,8 +4631,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames uint32_t TimerQueryMtl::begin(uint32_t _resultIdx, uint32_t _frameNum) { - BX_UNUSED(_resultIdx); - BX_UNUSED(_frameNum); + BX_UNUSED(_resultIdx, _frameNum); return 0; } @@ -4634,11 +4640,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames BX_UNUSED(_idx); } - static void setTimestamp(void* _data) - { - *( (int64_t*)_data) = bx::getHPCounter(); - } - void TimerQueryMtl::addHandlers(MTL::CommandBuffer*& _commandBuffer) { while (0 == m_control.reserve(1) ) @@ -4646,14 +4647,18 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_control.consume(1); } - uint32_t offset = m_control.m_current; + const uint32_t offset = m_control.m_current; - _commandBuffer->addScheduledHandler( - MTL::HandlerFunction([pBegin = &m_result[offset].m_begin](MTL::CommandBuffer*) { setTimestamp(pBegin); }) - ); _commandBuffer->addCompletedHandler( - MTL::HandlerFunction([pEnd = &m_result[offset].m_end](MTL::CommandBuffer*) { setTimestamp(pEnd); }) + MTL::HandlerFunction([this, offset](MTL::CommandBuffer* _cmdBuf) + { + const double gpuBegin = _cmdBuf->GPUStartTime(); + const double gpuEnd = _cmdBuf->GPUEndTime(); + m_result[offset].m_begin = uint64_t(gpuBegin * double(kNanosecondsPerSecond) ); + m_result[offset].m_end = uint64_t(gpuEnd * double(kNanosecondsPerSecond) ); + }) ); + m_control.commit(1); } @@ -4662,8 +4667,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (0 != m_control.getNumUsed() ) { uint32_t offset = m_control.m_read; - m_begin = m_result[offset].m_begin; - m_end = m_result[offset].m_end; + m_begin = m_result[offset].m_begin; + m_end = m_result[offset].m_end; m_elapsed = m_end - m_begin; m_control.consume(1); @@ -4849,8 +4854,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames int64_t timeBegin = bx::getHPCounter(); int64_t captureElapsed = 0; - m_gpuTimer.addHandlers(m_commandBuffer); - if (m_blitCommandEncoder) { m_blitCommandEncoder->endEncoding(); @@ -6123,6 +6126,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (NULL != m_commandBuffer) { + m_gpuTimer.addHandlers(m_commandBuffer); + m_cmd.kick(true, false); m_commandBuffer = NULL; } diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index d9c003117..a8a3010ac 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -626,7 +626,7 @@ namespace bgfx { namespace mtl uint64_t m_begin; uint64_t m_end; uint32_t m_pending; - uint32_t m_frameNum; // TODO: implement (currently stays 0) + uint32_t m_frameNum; }; uint64_t m_begin;