In Direct3D 12, queries are grouped into arrays of queries called a query heap. A query heap has a type which defines the valid types of queries that can be used with that heap.

Differences in Queries from Direct3D 11 to Direct3D 12

The following query types are no longer present in Direct3D 12, their functionality being incorporated into other processes:

  • Event queries - event functionally is now handled by fences.
  • Disjoint timestamp queries - GPU clocks can be set to a stable state in Direct3D 12 (see the Timing section). GPU clock comparisons are not meaningful if the GPU idled at all between the timestamps (known as a disjoint query). With stable power two timestamp queries issued from different command lists are reliably comparable. Two timestamps within the same command list are always reliably comparable.
  • Stream output statistics queries - in Direct3D 12 there is no single stream output (SO) overflow query for all the output streams. Apps need to issue multiple single-stream queries, and then correlate the results.
  • Stream output statistics predicate and occlusion predicate queries - queries (which write to memory) and Predication (which reads from memory) are no longer coupled, and so these query types are not needed.

A new binary occlusion query type has been added to Direct3D 12. This allows predication strategies that care only whether an object was fully occluded or not (rather than how many pixels were occluded) to indicate this to the device, which might be able to more efficiently perform the queries.

Query Heaps

Queries can be one from a number of types (D3D12_QUERY_HEAP_TYPE), and are grouped into query heaps before being submitted to the GPU.

A new query type D3D12_QUERY_TYPE_BINARY_OCCLUSION is available and acts like D3D12_QUERY_TYPE_OCCLUSION except that it returns a binary 0/1 result: 0 indicates that no samples passed depth and stencil testing, 1 indicates that at least one sample passed depth and stencil testing. This enables occlusion queries to not interfere with any GPU performance optimization associated with depth/stencil testing.

Creating Query heaps

The APIs relevant to creating query heaps are the enum D3D12_QUERY_HEAP_TYPE, the struct D3D12_QUERY_HEAP_DESC, and the method CreateQueryHeap.

The core runtime will validate that the query heap type is a valid member of the D3D12_HEAP_TYPE enumeration, and that the count is greater than 0.

Each individual query element within a query heap can be started and stopped separately.

The APIs for using the query heaps are the enum D3D12_QUERY_TYPE, and the methods BeginQuery and EndQuery.

D3D12_QUERY_TYPE_TIMESTAMP is the only query that supports EndQuery only. All other query types require BeginQuery and EndQuery.

The debug layer will validate the following:

  • It is illegal to begin a timestamp query—you can only end it
  • It is illegal to begin a query twice without ending it (for a given element). For queries that require both begin and end, it is illegal to end a query before the corresponding begin (for a given element).
  • The query type passed to BeginQuery must match the query type passed to EndQuery.

The core runtime will validate the following:

  • BeginQuery cannot be called on a timestamp query.

  • For the query types which support both BeginQuery and EndQuery (all except for timestamp), a query for a given element must not span command list boundaries.

  • ElementIndex must be within range.

  • The query type is a valid member of the D3D12_QUERY_TYPE enum.

  • The query type must be compatible with the query heap. The following table shows the query heap type required for each query type:

    Query Type Query Heap type


  • The query type is supported by the command list type. The following table shows which queries are supported on which command list types.

    Query Type Supported Command List Types
    D3D12_QUERY_TYPE_TIMESTAMP Direct, Compute, and optionally Copy


Extracting data from a query

The way to extract data from a query is to use the ResolveQueryData method. ResolveQueryData works with all memory types (whether they are system memory or device local memory), but requires the destination resource to be in D3D12_RESOURCE_STATE_COPY_DEST.