Last active
December 16, 2024 15:10
-
-
Save fredemmott/2247ff7259dfc7b3c2d0f4fec0431b7f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| struct D3D11Timer { | |
| D3D11Timer() = default; | |
| explicit D3D11Timer(ID3D11Device* device) { | |
| device->GetImmediateContext(mContext.put()); | |
| D3D11_QUERY_DESC desc {D3D11_QUERY_TIMESTAMP_DISJOINT}; | |
| device->CreateQuery(&desc, mDisjointQuery.put()); | |
| desc = {D3D11_QUERY_TIMESTAMP}; | |
| device->CreateQuery(&desc, mBeginRenderTimestampQuery.put()); | |
| device->CreateQuery(&desc, mEndRenderTimestampQuery.put()); | |
| } | |
| uint64_t GetDisplayTime() const noexcept { | |
| return mDisplayTime; | |
| } | |
| void StartRender() { | |
| if (!(mContext && mDisjointQuery && mBeginRenderTimestampQuery)) { | |
| return; | |
| } | |
| mDisplayTime = {}; | |
| QueryPerformanceCounter(&mBeginRenderCpu); | |
| mContext->Begin(mDisjointQuery.get()); | |
| // TIMESTAMP queries only have `End()` and `GetData()` called, never | |
| // `Begin()` | |
| mContext->End(mBeginRenderTimestampQuery.get()); | |
| } | |
| void StopRender(uint64_t displayTime) { | |
| if (!(mContext && mDisjointQuery && mBeginRenderTimestampQuery)) { | |
| return; | |
| } | |
| mDisplayTime = displayTime; | |
| mContext->End(mEndRenderTimestampQuery.get()); | |
| mContext->End(mDisjointQuery.get()); | |
| QueryPerformanceCounter(&mEndRenderCpu); | |
| } | |
| uint64_t GetRenderMicroseconds() { | |
| if (!(mContext && mDisjointQuery && mBeginRenderTimestampQuery)) { | |
| return 0; | |
| } | |
| D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint {}; | |
| uint64_t begin {}; | |
| uint64_t end {}; | |
| const auto disjointOk | |
| = mContext->GetData(mDisjointQuery.get(), &disjoint, sizeof(disjoint), 0) | |
| == S_OK; | |
| const auto beginOk | |
| = mContext->GetData( | |
| mBeginRenderTimestampQuery.get(), &begin, sizeof(begin), 0) | |
| == S_OK; | |
| const auto endOk | |
| = mContext->GetData(mEndRenderTimestampQuery.get(), &end, sizeof(end), 0) | |
| == S_OK; | |
| if (disjoint.Disjoint || !(disjoint.Frequency && begin && end)) { | |
| return 0; | |
| } | |
| if (!(disjointOk && beginOk && endOk)) { | |
| return 0; | |
| } | |
| const auto diff = end - begin; | |
| const auto gcd = std::gcd(1000000, disjoint.Frequency); | |
| const auto gpuMicros | |
| = (diff * (1000000 / gcd)) / (disjoint.Frequency / gcd); | |
| { | |
| const LARGE_INTEGER cpuDiff { | |
| .QuadPart = mEndRenderCpu.QuadPart - mBeginRenderCpu.QuadPart}; | |
| LARGE_INTEGER frequency {}; | |
| QueryPerformanceFrequency(&frequency); | |
| const auto cpuGcd = std::gcd(frequency.QuadPart, 1000000); | |
| const auto cpuMicros = (cpuDiff.QuadPart * (1000000 / cpuGcd)) | |
| / (frequency.QuadPart / cpuGcd); | |
| dprint("CPU {} GPU {}", cpuMicros, gpuMicros); | |
| } | |
| return gpuMicros; | |
| } | |
| private: | |
| uint64_t mDisplayTime {}; | |
| wil::com_ptr<ID3D11DeviceContext> mContext; | |
| wil::com_ptr<ID3D11Query> mDisjointQuery; | |
| wil::com_ptr<ID3D11Query> mBeginRenderTimestampQuery; | |
| wil::com_ptr<ID3D11Query> mEndRenderTimestampQuery; | |
| LARGE_INTEGER mBeginRenderCpu {}; | |
| LARGE_INTEGER mEndRenderCpu {}; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment