From c768068ee7898847c4a7ffcb8c3bec371e0be1ae Mon Sep 17 00:00:00 2001 From: Andrew Depke Date: Wed, 8 Jul 2020 15:42:42 -0600 Subject: [PATCH] Implemented GPU synchronization protocol --- TracyD3D12.hpp | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/TracyD3D12.hpp b/TracyD3D12.hpp index 93d4b244..680c981b 100644 --- a/TracyD3D12.hpp +++ b/TracyD3D12.hpp @@ -50,8 +50,8 @@ namespace tracy bool m_initialized = false; - ID3D12Device* m_device; - ID3D12CommandQueue* m_queue; + ID3D12Device* m_device = nullptr; + ID3D12CommandQueue* m_queue = nullptr; uint8_t m_context; Microsoft::WRL::ComPtr m_queryHeap; Microsoft::WRL::ComPtr m_readbackBuffer; @@ -65,6 +65,9 @@ namespace tracy Microsoft::WRL::ComPtr m_payloadFence; std::queue m_payloadQueue; + int64_t m_prevCalibration = 0; + int64_t m_qpcToNs = int64_t{ 1000000000 / GetFrequencyQpc() }; + public: D3D12QueueCtx(ID3D12Device* device, ID3D12CommandQueue* queue) : m_device(device) @@ -98,6 +101,9 @@ namespace tracy assert(false && "Failed to get queue clock calibration."); } + // Save the device cpu timestamp, not the profiler's timestamp. + m_prevCalibration = cpuTimestamp * m_qpcToNs; + cpuTimestamp = Profiler::GetTime(); D3D12_QUERY_HEAP_DESC heapDesc{}; @@ -233,6 +239,34 @@ namespace tracy } m_readbackBuffer->Unmap(0, nullptr); + + // Recalibrate to account for drift. + + uint64_t cpuTimestamp; + uint64_t gpuTimestamp; + + if (FAILED(m_queue->GetClockCalibration(&gpuTimestamp, &cpuTimestamp))) + { + assert(false && "Failed to get queue clock calibration."); + } + + cpuTimestamp *= m_qpcToNs; + + const auto cpuDelta = cpuTimestamp - m_prevCalibration; + if (cpuDelta > 0) + { + m_prevCalibration = cpuTimestamp; + cpuTimestamp = Profiler::GetTime(); + + auto* item = Profiler::QueueSerial(); + MemWrite(&item->hdr.type, QueueType::GpuCalibration); + MemWrite(&item->gpuCalibration.gpuTime, gpuTimestamp); + MemWrite(&item->gpuCalibration.cpuTime, cpuTimestamp); + MemWrite(&item->gpuCalibration.cpuDelta, cpuDelta); + MemWrite(&item->gpuCalibration.context, m_context); + + Profiler::QueueSerialFinish(); + } } private: