diff --git a/public/tracy/TracyD3D12.hpp b/public/tracy/TracyD3D12.hpp index ffb6e609..502defa0 100644 --- a/public/tracy/TracyD3D12.hpp +++ b/public/tracy/TracyD3D12.hpp @@ -47,11 +47,20 @@ using TracyD3D12Ctx = void*; #include #ifndef TRACY_D3D12_TIMESTAMP_COLLECT_TIMEOUT -#define TRACY_D3D12_TIMESTAMP_COLLECT_TIMEOUT 0.020f +#define TRACY_D3D12_TIMESTAMP_COLLECT_TIMEOUT 0.005f #endif +#define TRACY_D3D12_DEBUG (1) +#define TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER (1) + #define TracyD3D12Panic(msg, ...) do { assert(false && "TracyD3D12: " msg); tracy::Profiler::LogString( tracy::MessageSourceType::Tracy, tracy::MessageSeverity::Error, tracy::Color::Red4, 0, msg ); __VA_ARGS__; } while(false); +#if TRACY_D3D12_DEBUG +#define TracyD3D12Debug(...) __VA_ARGS__ +#else +#define TracyD3D12Debug(...) +#endif + namespace tracy { @@ -71,6 +80,10 @@ namespace tracy ID3D12QueryHeap* m_queryHeap = nullptr; ID3D12Resource* m_readbackBuffer = nullptr; +#if TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER + UINT64* m_timestampBuffer = nullptr; +#endif + using atomic_counter = std::atomic; atomic_counter m_queryCounter = 0; atomic_counter m_previousCheckpoint = 0; @@ -203,7 +216,11 @@ namespace tracy m_queryRequestTime[i] = AgeClock::time_point::max(); } // TODO: any advantages to making this Map() persist? +#if TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER + m_timestampBuffer = timestampBuffer; +#else m_readbackBuffer->Unmap(0, &zeroRange); +#endif } float period = [queue]() @@ -264,6 +281,10 @@ namespace tracy Collect(); } +#if TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER + D3D12_RANGE fullRange { 0, m_queryLimit * sizeof(UINT64) }; + m_readbackBuffer->Unmap(0, &fullRange); +#endif m_readbackBuffer->Release(); m_queryHeap->Release(); } @@ -319,6 +340,9 @@ namespace tracy TracyD3D12Panic("Collect: FULL! too many pending timestamp queries.", return); } +#if TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER + UINT64* timestampBuffer = m_timestampBuffer; +#else D3D12_RANGE mapRange{ 0, m_queryLimit * sizeof(UINT64) }; void* readbackBufferMapping = nullptr; if (FAILED(m_readbackBuffer->Map(0, &mapRange, &readbackBufferMapping))) @@ -326,15 +350,18 @@ namespace tracy TracyD3D12Panic("Collect: failed to map timestamp buffer.", return); } UINT64* timestampBuffer = static_cast(readbackBufferMapping); +#endif // Process timestamp queries two at a time, as (start, end) pairs for (uint64_t i = begin; i != latestCheckpoint; i += 2) { const uint32_t queryId = RingIndex(i); + UINT64 gpuZoneBeginTimestamp = timestampBuffer[queryId]; + UINT64 gpuZoneEndTimestamp = timestampBuffer[queryId+1]; if (timestampBuffer[queryId+1] == InvalidTimestamp) { - // drop the timestamp query if it's been in flight for too long + // determine for how long the query has been in flight auto now = AgeClock::now(); auto start = m_queryRequestTime[queryId+1]; auto elapsed = now - start; @@ -343,41 +370,44 @@ namespace tracy double fudge = RingSize() / double(count); auto timeout = std::chrono::duration(TRACY_D3D12_TIMESTAMP_COLLECT_TIMEOUT); //timeout *= fudge; - if (elapsed >= timeout) - { + // if it's a recent query, let subsequent Collect() calls handle it + if (elapsed < timeout) + break; + // otherwise, give up on waiting and drop it + TracyD3D12Debug( ZoneScopedNC("[drop]", Color::Red4); ZoneValue(int64_t(queryId)); ZoneValue(int64_t(m_lastEmittedGpuTimestamp)); TracyPlot("TracyD3D12 timeout", 0.0); TracyPlot("TracyD3D12 timeout", std::chrono::duration{elapsed}.count()); TracyPlot("TracyD3D12 timeout", 0.0); - m_queryRequestTime[queryId+0] = AgeClock::time_point::max(); - m_queryRequestTime[queryId+1] = AgeClock::time_point::max(); - // emit a "bogus" GpuTime just to provide a "match" for the query ids - // that have been instrumented (this way, the UI does not freak out) - EmitGpuTime(m_lastEmittedGpuTimestamp+1000, queryId+0); - EmitGpuTime(m_lastEmittedGpuTimestamp+1000, queryId+1); - m_previousCheckpoint.store(i+2); - continue; - } - // otherwise, let subsequent Collect() calls handle it - break; + ); + // emit a "bogus" GpuTime just to provide a "match" for the query ids + // that have been instrumented (this way, the UI does not freak out) + gpuZoneBeginTimestamp = m_lastEmittedGpuTimestamp; + gpuZoneEndTimestamp = m_lastEmittedGpuTimestamp+1; } - EmitGpuTime(timestampBuffer[queryId+0], queryId+0); - EmitGpuTime(timestampBuffer[queryId+1], queryId+1); + EmitGpuTime(gpuZoneBeginTimestamp, queryId); + EmitGpuTime(gpuZoneEndTimestamp, queryId+1); - // "slow" write (to a readback heap memory) + // "slow" write (to timestampBuffer, backed by "readback" heap memory) timestampBuffer[queryId+0] = InvalidTimestamp; timestampBuffer[queryId+1] = InvalidTimestamp; - m_queryRequestTime[queryId+0] = AgeClock::time_point::max(); m_queryRequestTime[queryId+1] = AgeClock::time_point::max(); + TracyD3D12Debug( + TracyFreeN(reinterpret_cast(uintptr_t(queryId+0)), "TracyD3D12 Query"); + TracyFreeN(reinterpret_cast(uintptr_t(queryId+1)), "TracyD3D12 Query"); + ); + m_previousCheckpoint.store(i+2); } +#if !TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER m_readbackBuffer->Unmap(0, &mapRange); +#endif //RecalibrateClocks(); } @@ -424,18 +454,18 @@ namespace tracy const uint32_t queryId = RingIndex(seqIdx); - if (m_queryRequestTime[queryId+0] != AgeClock::time_point::max()) { - TracyD3D12Panic("Unexpected Request Time! (+0)"); - } - if (m_queryRequestTime[queryId+1] != AgeClock::time_point::max()) { - TracyD3D12Panic("Unexpected Request Time! (+1)"); - } - const auto t = AgeClock::now(); m_queryRequestTime[queryId+0] = t; m_queryRequestTime[queryId+1] = t; +#if TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER + m_timestampBuffer[queryId+0] = InvalidTimestamp; + m_timestampBuffer[queryId+1] = InvalidTimestamp; +#endif - TracyPlot("TracyD3D12 QueryID", int64_t(queryId)); + TracyD3D12Debug( + TracyAllocN(reinterpret_cast(uintptr_t(queryId+0)), 1, "TracyD3D12 Query"); + TracyAllocN(reinterpret_cast(uintptr_t(queryId+1)), 1, "TracyD3D12 Query"); + ); return queryId; } @@ -577,8 +607,10 @@ namespace tracy } -#undef TracyD3D12Panic +#undef TRACY_D3D12_DEBUG +#undef TRACY_D3D12_PERSISTENT_TIMESTAMP_BUFFER #undef TRACY_D3D12_TIMESTAMP_COLLECT_TIMEOUT +#undef TracyD3D12Panic using TracyD3D12Ctx = tracy::D3D12QueueCtx*;