Skip to content

Implement GPU time measurement.#94

Merged
crud89 merged 3 commits intomainfrom
timing
Apr 1, 2023
Merged

Implement GPU time measurement.#94
crud89 merged 3 commits intomainfrom
timing

Conversation

@crud89
Copy link
Copy Markdown
Owner

@crud89 crud89 commented Apr 1, 2023

Describe the pull request

This PR implements support for GPU-based time measurements. This works by defining one or more Timing Events, that are written to a command buffer during frame drawing. If the frame has finished drawing (i.e., the next time the swap chain swaps back to the frame's back buffer), the results of the measurements are read and can be requested from the event.

Usage

During initialization (usually in the startup-callback for a backend), all timing events need to be registered:

m_beginEvent = m_device->swapChain().registerTimingEvent("Begin Frame");
// ...
m_endEvent = m_device->swapChain().registerTimingEvent("End Frame");

Note that it is possible to insert more events during runtime, but this results in re-creation of query pools/heaps, which may be inefficient.

When drawing a frame, the events can be set on a command buffer:

auto commandBuffer = renderPass.activeFrameBuffer().commandBuffer(0);
commandBuffer->writeTimingEvent(m_beginEvent);
// ...
commandBuffer->writeTimingEvent(m_endEvent);

Finally, the events themselves can be used to acquire the current readings. In this example, the duration is converted into milliseconds and then written into a string.

auto begin = m_beginEvent->readTimestamp();
auto end = m_endEvent->readTimestamp();
auto ticks = end - begin;
double time = ticks / m_device->ticksPerMillisecond();

std::stringstream drawTime;
drawTime << "Draw time: " << std::fixed << std::setprecision(4) << time << "ms";

Note that timestamp queries are asynchronous, so the readings are not representing the last frame drawn by the app, but the last presented frame. Also note that the timestamps are expressed as 64 bit ticks, which need to be converted into milliseconds by querying the ticksPerSecond property of the current device.

Known issues

When using the native Vulkan swap chain, the validation layers in some rare occasions complain about a query pool not being reset properly. Usually, this only means that the readings are not valid in those instances, but since the behavior is undefined, it is best not to rely on this feature when using this swap chain. This does not happen when using the D3D interop swap chain.

@crud89 crud89 added Priority: Medium A issue with normal priority. Feature New feature or request. Vulkan πŸŒ‹ The issue involves the Vulkan backend. DX12 ❎ The issue involves the DX12 backend. labels Apr 1, 2023
@crud89 crud89 added this to the Alpha #04 milestone Apr 1, 2023
@crud89 crud89 self-assigned this Apr 1, 2023
@crud89 crud89 marked this pull request as ready for review April 1, 2023 15:46
@crud89 crud89 merged commit 78367c2 into main Apr 1, 2023
@crud89 crud89 deleted the timing branch April 1, 2023 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DX12 ❎ The issue involves the DX12 backend. Feature New feature or request. Priority: Medium A issue with normal priority. Vulkan πŸŒ‹ The issue involves the Vulkan backend.

Projects

Status: v0.4.1

Development

Successfully merging this pull request may close these issues.

1 participant