-
Notifications
You must be signed in to change notification settings - Fork 345
Description
Intro
This investigation is based on gfx-rs/gfx#1638
Modern graphics API allow applications to query some of the information that's processed internally by graphics hardware. The oldest and most common example is an occlusion query. If the user has a complex object to draw, they could first attempt to draw a simpler bounding object and only proceed with the original one if there are some fragments that passed the depth/stencil/scissor checks.
Queries are used by some of the existing software, e.g. Dota2, RPCS3, and Dolphin. So it is important to support it in WebGPU.
Native APIs
Vulkan
Vulkan provides 3 types of queries: occlusion, timestamp, and pipeline statistics. Only the former one is required for implementation in the driver.
Users create a pool of queries of the same type with VkCreateQueryPool that has a concrete length. From there on, users refer to individual queries by (QueryPool, IndexWithinPool) pair of values. Each query can be in either of those states:
- "unavailable" - query has no data
- "active" (within a command buffer) - query is tracking the fragments being rendered
- "available" - query has the data
Users reset, begin, and end queries via command buffer operations. When activating a query (via VkCmdBeginQuery) the user specifies if it needs to actually count the fragments or just produce a single boolean result. The actual state change happens when the command buffer is submitted to a queue.
Vulkan is very flexible when it comes to obtaining the query results. It could be done by different means:
- by issuing a command that copies query data into a buffer:
VkCmdCopyQueryPoolResults - by asking the device specifically:
VkGetQueryPoolResults
Users can also specify if they want results to be 32bit, if they also need to know if the query is available (which means an extra boolean word of data is returned), and if the driver needs to wait for the queries to complete (become available) before the results are obtained.
There is no specific mechanism to do conditional rendering based on the occlusion result. Instead, users can use indirect drawing with the instance count depending on the query result.
D3D12
D3D12 has a notion of query heaps that is very similar to VkQueryPool. The different states a query can be in: Inactive/Querying/Predicating - also corresponds to Vulkan pretty closely.
The querying of the results doesn't offer the synchronous path (like VkGetQueryPoolResults). There is only a path via command buffers (ResolveQueryData) and the results are always 64 bits. The target buffer, like in case of Vulkan, needs to support being a transfer destination.
I assume that the queries are guaranteed to be available (Microsoft - please confirm).
Metal
In Metal, it's called "visibility results", and they are scoped to render passes. When beginning a pass, users may provide the visibility buffer. To start a query, user changes the visibility result mode to either Counting or Boolean and specifies the offset into the buffer to place results. Query is ended by switching the mode to Disabled. Results are always 64bit.
TODO
Pipeline statistics and timestamp queries