DirectX-Specs

D3D12 ExecuteTileMappings

Contents

Overview

ExecuteTileMappings provides GPU-driven tile mapping. The GPU or CPU can write tile mapping commands into a GPU-accessible argument buffer, which is later executed on a dedicated tile mapping queue between ExecuteCommandLists submissions.

The operation resembles ID3D12CommandQueue::UpdateTileMappings, but is batched across multiple source tile pools and destination reserved resources. The input is a token-based command stream that can be generated by application shaders or CPU code without a command signature.

The application sizes, allocates, manages, and can reuse the input buffers. Each mapping token refers to application-selected indices in registered tile pool and reserved-resource layout tables.

Feature requirements

Tiled Resources Tier 5

ExecuteTileMappings requires Tiled Resources Tier 5. Tier 5 is a superset of Tiers 1 through 4 and adds ExecuteTileMappings support.

Resource and heap flags

Two creation-time flags determine whether a reserved resource or heap is eligible for ExecuteTileMappings:

The heap flag does not prevent the heap from being used for placed resources.

API

typedef enum D3D12_RESOURCE_FLAGS
{
    // Existing values omitted.
    D3D12_RESOURCE_FLAG_ALLOW_EXECUTE_TILE_MAPPINGS = 0x1000,
} D3D12_RESOURCE_FLAGS;

typedef enum D3D12_HEAP_FLAGS
{
    // Existing values omitted.
    D3D12_HEAP_FLAG_ALLOW_EXECUTE_TILE_MAPPINGS = 0x8000,
} D3D12_HEAP_FLAGS;

Mapping tokens

Every mapping token occupies eight DWORDs. TokenType identifies the token layout, MappingType identifies how source tiles are selected, and SubresourceIndex selects the destination subresource.

typedef enum D3D12_EXECUTETILEMAPPINGS_TOKEN_TYPES : UINT
{
    D3D12_EXECUTETILEMAPPINGS_TOKEN_TYPE_NO_OPERATION = 1,
    D3D12_EXECUTETILEMAPPINGS_TOKEN_TYPE_LINEAR_MAPPING = 128,
    D3D12_EXECUTETILEMAPPINGS_TOKEN_TYPE_BOX_MAPPING = 129,
} D3D12_EXECUTETILEMAPPINGS_TOKEN_TYPES;

struct D3D12_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER
{
    UINT TokenType : 8;
    UINT MappingType : 8;
    UINT SubresourceIndex : 16;
};

typedef enum D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPES
{
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPE_INCREMENTING_TILE_INDICES = 0,
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPE_NULL = 1,
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPE_SKIP = 2,
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPE_REUSE_SINGLE_TILE = 3,
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPE_TILE_INDEX_LIST = 4,
} D3D12_EXECUTETILEMAPPINGS_MAPPING_TYPES;

struct D3D12_EXECUTETILEMAPPINGS_LINEAR_MAPPING_TOKEN
{
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER Header;
    UINT TilePoolBaseOffsetInTiles;
    UINT SubresourceBaseOffsetInTiles;
    UINT TileCount;
    UINT _Padding;
    UINT TilePoolLayoutIndex;
    UINT ResourceLayoutIndex;
    UINT TileListOffsetDwords;
};

struct D3D12_EXECUTETILEMAPPINGS_BOX_MAPPING_TOKEN
{
    D3D12_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER Header;
    UINT TilePoolBaseOffsetInTiles;
    UINT16 X;
    UINT16 Y;
    UINT16 Z;
    UINT16 Width;
    UINT16 Height;
    UINT16 Depth;
    UINT TilePoolLayoutIndex;
    UINT ResourceLayoutIndex;
    UINT TileListOffsetDwords;
};

Capability query

typedef enum D3D12_FEATURE
{
    // Existing values omitted.
    D3D12_FEATURE_EXECUTE_TILE_MAPPINGS,
} D3D12_FEATURE;

typedef struct D3D12_FEATURE_DATA_EXECUTE_TILE_MAPPINGS
{
    UINT NodeIndex;
    UINT MaxTilePoolLayoutIndexCount;
    UINT MaxResourceLayoutIndexCount;
} D3D12_FEATURE_DATA_EXECUTE_TILE_MAPPINGS;

Applications query D3D12_FEATURE_EXECUTE_TILE_MAPPINGS through ID3D12Device::CheckFeatureSupport. NodeIndex selects a D3D12 node and must be less than ID3D12Device::GetNodeCount.

The returned maximums are the number of tile pool and reserved-resource layout slots supported for the selected node. On a supported node, both values are greater than zero. On an unsupported node, both values are zero.

The values are per physical adapter and are not aggregated across linked adapter members.

The query does not allocate or resize either table and returns the same hardware maximums for the lifetime of the device.

Tile mapping queue

typedef enum D3D12_EXECUTE_TILE_MAPPINGS_FLAGS
{
    D3D12_EXECUTE_TILE_MAPPINGS_FLAG_NONE = 0,
} D3D12_EXECUTE_TILE_MAPPINGS_FLAGS;

interface ID3D12TileMappingQueue : public ID3D12Pageable
{
    void ExecuteTileMappings(
        UINT MaxArgumentDwordCount,
        ID3D12Resource* pArgumentBuffer,
        UINT64 ArgumentBufferOffset,
        _In_opt_ ID3D12Resource* pCountBuffer,
        UINT64 CountBufferOffset,
        _In_opt_ ID3D12Resource* pTileListBuffer,
        UINT64 TileListBufferOffset,
        D3D12_EXECUTE_TILE_MAPPINGS_FLAGS Flags);

    HRESULT Signal(
        ID3D12Fence* pFence,
        UINT64 Value);

    HRESULT Wait(
        ID3D12Fence* pFence,
        UINT64 Value);
};

Each initialized physical adapter has one dedicated tile mapping queue.

Layout table management

interface ID3D12DeviceN : ID3D12DeviceNm1
{
    HRESULT GetTileMappingQueue(
        UINT NodeIndex,
        REFIID riid,
        void** ppQueue);

    HRESULT InitializeExecuteTileMappingLayoutTables(
        UINT NodeIndex,
        UINT TilePoolLayoutIndexCount,
        UINT ResourceLayoutIndexCount);

    HRESULT RegisterResourceLayouts(
        UINT NodeIndex,
        UINT NumResources,
        _In_reads_(NumResources)
            ID3D12Resource** pReservedResourceArray,
        _In_reads_(NumResources)
            const UINT* pResourceLayoutIndexArray);

    HRESULT RegisterHeapLayouts(
        UINT NodeIndex,
        UINT NumHeaps,
        _In_reads_(NumHeaps)
            ID3D12Heap** pHeapArray,
        _In_reads_(NumHeaps)
            const UINT* pTilePoolLayoutIndexArray);

    HRESULT UnregisterResourceLayouts(
        UINT NodeIndex,
        UINT NumResources,
        _In_reads_(NumResources)
            ID3D12Resource** pReservedResourceArray);

    HRESULT UnregisterHeapLayouts(
        UINT NodeIndex,
        UINT NumHeaps,
        _In_reads_(NumHeaps)
            ID3D12Heap** pHeapArray);
};

User-mode DDI

The driver must report at least DDI version 0124 to support this feature.

Feature reporting

typedef enum D3D12DDI_TILED_RESOURCES_TIER
{
    D3D12DDI_TILED_RESOURCES_TIER_NOT_SUPPORTED = 0,
    D3D12DDI_TILED_RESOURCES_TIER_1 = 1,
    D3D12DDI_TILED_RESOURCES_TIER_2 = 2,
    D3D12DDI_TILED_RESOURCES_TIER_3 = 3,
    D3D12DDI_TILED_RESOURCES_TIER_4 = 4,
    D3D12DDI_TILED_RESOURCES_TIER_5 = 5,
} D3D12DDI_TILED_RESOURCES_TIER;

The runtime requires TiledResourcesTier >= D3D12DDI_TILED_RESOURCES_TIER_5.

typedef enum D3D12DDICAPS_TYPE
{
    // Existing values omitted.
    D3D12DDICAPS_TYPE_EXECUTE_TILE_MAPPINGS_0124,
} D3D12DDICAPS_TYPE;

typedef struct D3D12DDI_FEATURE_DATA_EXECUTE_TILE_MAPPINGS_0124
{
    UINT NodeIndex;
    UINT MaxTilePoolLayoutIndexCount;
    UINT MaxResourceLayoutIndexCount;
    BOOL UMDOnlySupport;
} D3D12DDI_FEATURE_DATA_EXECUTE_TILE_MAPPINGS_0124;

The runtime translates this capability to D3D12_FEATURE_DATA_EXECUTE_TILE_MAPPINGS. Capabilities can be queried for each candidate node. If UMDOnlySupport is FALSE, the reported maximums must remain within the limits of the underlying implementation.

DDI resource and heap flags

// Addition to D3D12DDI_RESOURCE_FLAGS_0003
D3D12DDI_RESOURCE_FLAG_0124_ALLOW_EXECUTE_TILE_MAPPINGS = 0x20000,

// Addition to D3D12DDI_HEAP_FLAGS
D3D12DDI_HEAP_FLAG_0124_ALLOW_EXECUTE_TILE_MAPPINGS = 0x1000,

The runtime passes these creation flags to the driver and enforces the separation from legacy tile mapping DDIs:

DDI handles and tables

D3D10DDI_H(D3D12DDI_HTILEMAPPINGQUEUE_0124)

// Addition to D3D12DDI_HANDLETYPE
D3D12DDI_HT_0124_TILEMAPPINGQUEUE = 51,

// Addition to D3D12DDI_TABLE_TYPE
D3D12DDI_TABLE_TYPE_0124_TILE_MAPPING_QUEUE_FUNCS = 40,

DDI argument buffer types

The following types are defined in d3dukmdt.h. Their numeric values and memory layouts match the API types, so the runtime does not translate argument buffer contents.

typedef enum _D3DDDI_EXECUTETILEMAPPINGS_TOKEN_TYPES : UINT
{
    D3DDDI_EXECUTETILEMAPPINGS_TOKEN_TYPE_NO_OPERATION = 1,
    D3DDDI_EXECUTETILEMAPPINGS_TOKEN_TYPE_LINEAR_MAPPING = 128,
    D3DDDI_EXECUTETILEMAPPINGS_TOKEN_TYPE_BOX_MAPPING = 129,
} D3DDDI_EXECUTETILEMAPPINGS_TOKEN_TYPES;

typedef enum _D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPES
{
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPE_INCREMENTING_TILE_INDICES = 0,
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPE_NULL = 1,
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPE_SKIP = 2,
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPE_REUSE_SINGLE_TILE = 3,
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPE_TILE_INDEX_LIST = 4,
} D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TYPES;

typedef enum _D3DDDI_EXECUTE_TILE_MAPPINGS_FLAGS
{
    D3DDDI_EXECUTE_TILE_MAPPINGS_FLAG_NONE = 0,
} D3DDDI_EXECUTE_TILE_MAPPINGS_FLAGS;

typedef struct _D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER
{
    UINT TokenType : 8;
    UINT MappingType : 8;
    UINT SubresourceIndex : 16;
} D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER;

typedef struct _D3DDDI_EXECUTETILEMAPPINGS_LINEAR_MAPPING_TOKEN
{
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER Header;
    UINT TilePoolBaseOffsetInTiles;
    UINT SubresourceBaseOffsetInTiles;
    UINT TileCount;
    UINT _Padding;
    UINT TilePoolLayoutIndex;
    UINT ResourceLayoutIndex;
    UINT TileListOffsetDwords;
} D3DDDI_EXECUTETILEMAPPINGS_LINEAR_MAPPING_TOKEN;

typedef struct _D3DDDI_EXECUTETILEMAPPINGS_BOX_MAPPING_TOKEN
{
    D3DDDI_EXECUTETILEMAPPINGS_MAPPING_TOKEN_HEADER Header;
    UINT TilePoolBaseOffsetInTiles;
    UINT16 X;
    UINT16 Y;
    UINT16 Z;
    UINT16 Width;
    UINT16 Height;
    UINT16 Depth;
    UINT TilePoolLayoutIndex;
    UINT ResourceLayoutIndex;
    UINT TileListOffsetDwords;
} D3DDDI_EXECUTETILEMAPPINGS_BOX_MAPPING_TOKEN;

typedef struct _D3DDDI_QUERIED_RESOURCE_MAPPING
{
    UINT SourceLayoutId;
    UINT SourceOffsetInTiles;
} D3DDDI_QUERIED_RESOURCE_MAPPING;

For mapping queries, the runtime translates SourceLayoutId to TilePoolLayoutIndex and SourceOffsetInTiles to TilePoolOffsetInTiles.

DDI entry points

typedef SIZE_T (APIENTRY*
    PFND3D12DDI_CALCPRIVATETILEMAPPINGQUEUESIZE_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_CREATETILEMAPPINGQUEUE_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        D3D12DDI_HTILEMAPPINGQUEUE_0124 hDrvTileMappingQueue);

typedef VOID (APIENTRY*
    PFND3D12DDI_DESTROYTILEMAPPINGQUEUE_0124)(
        D3D12DDI_HDEVICE hDevice,
        D3D12DDI_HTILEMAPPINGQUEUE_0124 hDrvTileMappingQueue);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_INITIALIZEEXECUTETILEMAPPINGLAYOUTTABLES_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        UINT TilePoolLayoutIndexCount,
        UINT ResourceLayoutIndexCount);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_REGISTERRESOURCELAYOUTS_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        UINT NumResources,
        _In_reads_(NumResources)
            const D3D12DDI_HRESOURCE* pReservedResourceArray,
        _In_reads_(NumResources)
            const UINT* pResourceLayoutIndexArray);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_REGISTERHEAPLAYOUTS_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        UINT NumHeaps,
        _In_reads_(NumHeaps)
            const D3D12DDI_HHEAP* pHeapArray,
        _In_reads_(NumHeaps)
            const UINT* pTilePoolLayoutIndexArray);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_UNREGISTERRESOURCELAYOUTS_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        UINT NumResourceLayoutIndices,
        _In_reads_(NumResourceLayoutIndices)
            const UINT* pResourceLayoutIndexArray);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_UNREGISTERHEAPLAYOUTS_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        UINT NumTilePoolLayoutIndices,
        _In_reads_(NumTilePoolLayoutIndices)
            const UINT* pTilePoolLayoutIndexArray);

typedef HRESULT (APIENTRY*
    PFND3D12DDI_QUERYREGISTEREDRESERVEDRESOURCEMAPPINGS_0124)(
        D3D12DDI_HDEVICE hDevice,
        UINT NodeIndex,
        D3D12DDI_HRESOURCE hReservedResource,
        UINT64 ResourceMappingStartOffset,
        UINT64 ResourceMappingsCount,
        UINT64 ResourceMappingsOutputOffset,
        D3D12DDI_HRESOURCE hResourceMappingsOutput);

typedef VOID (APIENTRY*
    PFND3D12DDI_EXECUTETILEMAPPINGS_0124)(
        D3D12DDI_HTILEMAPPINGQUEUE_0124 hDrvTileMappingQueue,
        UINT MaxArgumentDwordCount,
        D3D12DDI_HRESOURCE hArgumentBuffer,
        UINT64 ArgumentBufferOffset,
        D3D12DDI_HRESOURCE hCountBuffer,
        UINT64 CountBufferOffset,
        D3D12DDI_HRESOURCE hTileListBuffer,
        UINT64 TileListBufferOffset,
        D3DDDI_EXECUTE_TILE_MAPPINGS_FLAGS Flags);

The device function table adds:

PFND3D12DDI_CALCPRIVATETILEMAPPINGQUEUESIZE_0124
    pfnCalcPrivateTileMappingQueueSize;
PFND3D12DDI_CREATETILEMAPPINGQUEUE_0124
    pfnCreateTileMappingQueue;
PFND3D12DDI_DESTROYTILEMAPPINGQUEUE_0124
    pfnDestroyTileMappingQueue;
PFND3D12DDI_INITIALIZEEXECUTETILEMAPPINGLAYOUTTABLES_0124
    pfnInitializeExecuteTileMappingLayoutTables;
PFND3D12DDI_REGISTERRESOURCELAYOUTS_0124
    pfnRegisterResourceLayouts;
PFND3D12DDI_REGISTERHEAPLAYOUTS_0124
    pfnRegisterHeapLayouts;
PFND3D12DDI_UNREGISTERRESOURCELAYOUTS_0124
    pfnUnregisterResourceLayouts;
PFND3D12DDI_UNREGISTERHEAPLAYOUTS_0124
    pfnUnregisterHeapLayouts;
PFND3D12DDI_QUERYREGISTEREDRESERVEDRESOURCEMAPPINGS_0124
    pfnQueryRegisteredReservedResourceMappings;

The tile mapping queue uses its own function table:

typedef struct D3D12DDI_TILE_MAPPING_QUEUE_FUNCS_0124
{
    PFND3D12DDI_EXECUTETILEMAPPINGS_0124 pfnExecuteTileMappings;
    PFND3D12DDI_SIGNAL_FENCE pfnSignalFence;
    PFND3D12DDI_WAIT_FOR_FENCE pfnWaitForFence;
} D3D12DDI_TILE_MAPPING_QUEUE_FUNCS_0124;

The runtime passes the argument, count, and tile-list resource handles, offsets, and flags directly to pfnExecuteTileMappings. pfnSignalFence and pfnWaitForFence provide GPU timeline synchronization for the tile mapping queue.

After layout-table initialization succeeds, the runtime calls the queue size and creation DDIs when the application first requests the tile mapping queue for that physical adapter. The queue is destroyed with the D3D12 device.

Usage

An argument buffer contains one or more mapping tokens. Each token refers to a tile pool layout, a reserved-resource layout, and optionally an offset in a tile-list buffer.

Tokens in one ExecuteTileMappings call complete in an unspecified order. Mappings in one call cannot overlap or otherwise depend on execution order. Each call synchronizes at the end of its argument buffer, so subsequent calls on the tile mapping queue complete in submission order.

Before unregistering a layout or destroying its registered object, the application must ensure that all tile mapping queue work referring to that layout has completed. A layout index can be reused only after unregistration completes.

Initializing layout tables

InitializeExecuteTileMappingLayoutTables selects the actual number of tile pool and resource layout slots for a node. Both counts must be greater than zero and no greater than the corresponding maximums returned by CheckFeatureSupport.

The first successful call for a physical adapter fixes both counts for the lifetime of the device. A later call for that physical adapter fails, including a call with the same counts. Physical adapters are initialized independently. If an initialization attempt fails, a retry uses the same NodeIndex but can select different counts.

After initialization, valid indices are from zero through IndexCount - 1. GetTileMappingQueue, RegisterHeapLayouts, and RegisterResourceLayouts fail for a physical adapter until initialization succeeds.

Referenced heaps, resources, and input buffers must be visible to the selected node.

Registering and unregistering tile pools

RegisterHeapLayouts associates heaps with application-selected tile pool layout indices. Each heap layout describes the entire heap. A heap must:

Indices and heaps must be unique within a registration call, each index must be within the initialized table, and neither the index nor heap can already be registered for the selected physical adapter.

Registration is batched and atomic: if any heap registration fails, no heap in the call is registered. After success, the selected index is stored for the physical adapter in the corresponding heap.

One heap can be registered independently with each physical adapter to which it is visible.

UnregisterHeapLayouts takes an array of registered heaps. Null, foreign, duplicate, or unregistered heaps make the entire call fail without unregistering any layout.

All ExecuteTileMappings work referring to the layouts must have completed, and mappings from registered reserved resources to each heap must have been removed before unregistration. Unregistration does not release the heap, and the heap can be registered again later.

Destroying a heap unregisters any stored layouts before destruction completes.

Registering and unregistering reserved resources

RegisterResourceLayouts associates reserved resources with application-selected resource layout indices. Each resource must:

Committed, placed, and shared resources cannot be registered.

Indices and resources must be unique within a registration call, each index must be within the initialized table, and neither the index nor resource can already be registered for the selected physical adapter.

Registration is batched and atomic: if any resource registration fails, no resource in the call is registered. After success, the selected index is stored for the physical adapter in the corresponding resource.

One resource can be registered independently with each physical adapter to which it is visible.

UnregisterResourceLayouts takes an array of registered reserved resources. Null, foreign, duplicate, non-reserved, or unregistered resources make the entire call fail without unregistering any layout.

All ExecuteTileMappings work referring to the layouts must have completed, and all tiles in each reserved resource must be unmapped before unregistration. Unregistration does not release the resource or its reserved GPU virtual address range, and the resource can be registered again later.

Destroying a reserved resource unregisters any stored layouts before destruction completes.

Executing tile mappings

The argument length in DWORDs is the lesser of MaxArgumentDwordCount and the unsigned 32-bit value in the count buffer when a count buffer is supplied.

The argument buffer can be in:

The optional tile-list buffer contains unsigned 32-bit tile pool indices.

A NO_OPERATION token consumes one eight-DWORD token and performs no mapping.

Linear mapping tokens

A linear token maps a linear range of tiles in one reserved-resource subresource to tiles in a tile pool.

SubresourceBaseOffsetInTiles and TileCount identify the destination range. The mapping must remain entirely within the selected subresource. For texture subresources, linear tile coordinates use XYZ typewriter order: X first, then Y, then Z. A mapping cannot spill into a subsequent subresource.

Box mapping tokens

A box token maps a three-dimensional tile region in one reserved texture subresource.

X, Y, and Z identify the destination origin. Width, Height, and Depth must be nonzero, and the complete box must fit in the selected subresource. The mapping contains Width * Height * Depth tiles and proceeds in XYZ typewriter order.

Box mappings are not valid for linear buffer layouts. ExecuteTileMappings does not copy existing mappings from one location in a reserved resource to another.

Mapping types

Each linear or box mapping uses one of these source selection modes:

  1. INCREMENTING_TILE_INDICES: select consecutive tiles beginning at TilePoolBaseOffsetInTiles.
  2. NULL: unmap the destination tiles. The tile pool is not accessed and TilePoolBaseOffsetInTiles is ignored.
  3. SKIP: perform no mapping for the token.
  4. REUSE_SINGLE_TILE: map every destination tile to the one tile selected by TilePoolBaseOffsetInTiles.
  5. TILE_INDEX_LIST: select tile indices from the tile-list buffer beginning at TileListOffsetDwords. The list must contain one entry per destination tile. TilePoolBaseOffsetInTiles is ignored.

Queue support

GetTileMappingQueue(NodeIndex) returns the dedicated tile mapping queue for the corresponding initialized physical adapter.

ExecuteTileMappings does not run on a DIRECT, COMPUTE, or COPY command queue. Those queues order work with the tile mapping queue through fence Signal and Wait operations.

GPU synchronization

At the beginning of ExecuteTileMappings, the GPU performs pipeline and cache flushes before consuming the argument buffer.

After the argument buffer completes, page table writes are flushed and GPU translation caches are invalidated before later work proceeds on the tile mapping queue.

Applications must ensure that simultaneous work on other queues does not depend on resources or memory being remapped. ExecuteTileMappings does not globally serialize command buffer execution across all queues.

Protected sessions

The argument, count, and tile-list buffers cannot be protected resources. Registered heaps and reserved resources are unaffected because ExecuteTileMappings does not access their contents.

Error handling

Invalid API parameters or invalid argument-buffer contents can cause device removal. When the debug layer is enabled, it reports mapping details through the info queue. Argument parsing and its errors occur asynchronously from the API call.

The runtime emits one D3D12_MESSAGE_ID_EXECUTETILEMAPPINGS_EXECUTION_ERROR message:

ExecuteTileMappings error <code>: <canonical-name>; token byte offset <offset>

The offset is relative to ArgumentBufferOffset and is not a GPU virtual address.

Code Name Meaning
128 OUT_OF_RESOURCE_BOUNDS A linear mapping exceeds the destination resource, or a box exceeds the destination subresource dimensions.
129 OUT_OF_TILEPOOL_BOUNDS A mapping selects a tile beyond the tile pool.
130 UNEXPECTED_END_OF_BUFFER The effective argument length ends in the middle of a token.
131 INVALID_TOKEN A token cannot be decoded or has an invalid token type.
132 INVALID_TILEPOOL The tile pool layout is invalid, stale, uninitialized, or corrupted, or a selected source tile is unmapped.
133 INVALID_RESOURCE The resource layout is invalid, stale, uninitialized, or corrupted; the destination cannot be updated; or the subresource index is invalid.
134 INCOMPATIBLE_BOX_MAPPING A box mapping targets a linear buffer layout.

PIX capture

PIX captures ExecuteTileMappings arguments similarly to existing GPU tile mapping APIs. GPU-generated buffer contents might not be captured when the work that generates them occurs before the capture window.

PIX can query the initial mapping state of a registered reserved resource:

#define D3D12_TILE_NOT_MAPPED UINT_MAX

struct D3D12_QUERIED_RESOURCE_MAPPING
{
    UINT TilePoolLayoutIndex;
    UINT TilePoolOffsetInTiles;
};

HRESULT ID3D12CommandQueueN::QueryRegisteredReservedResourceMappings(
    ID3D12Resource* pReservedResource,
    UINT64 ResourceMappingStartOffset,
    UINT64 ResourceMappingsCount,
    UINT64 ResourceMappingsOutputOffset,
    ID3D12Resource* pResourceMappingsOutput);

For an unmapped tile, both fields are D3D12_TILE_NOT_MAPPED.

The source must be a registered reserved resource. The source range must not exceed the total tile count of the resource, and the output range must fit in the output buffer. Invalid parameters return failure.

PIX can issue multiple queries for large resources and convert the results to linear mapping tokens for capture playback.