这是indexloc提供的服务,不要输入任何密码
Skip to content

Occlusion Queries #72

@kvark

Description

@kvark

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:

  1. by issuing a command that copies query data into a buffer: VkCmdCopyQueryPoolResults
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions