Fast Semantics
Fast semantics provide significant CPU performance gains, but adopting them involves a number of changes in the use of D3D11X. Enabling fast semantics is straightforward, but adapting rendering to their use is more complex. Fast semantics on Direct3D 11.x is similar to the high-performance, low-level API aspect of Direct3D 12.
Review of immediate and deferred contexts
Direct3D 11 supports two types of rendering: immediate and deferred. Both are implemented by using the ID3D11DeviceContext interface.
- Immediate rendering refers to calling rendering APIs or commands from a device, which queues the commands in a buffer for execution on the GPU. Use an immediate context to render, set pipeline state, and play back a command list.
- Deferred rendering records graphics commands in a command buffer so that they can be played back at some other time. Use a deferred context to record commands (rendering as well as state setting) to a command list. Deferred rendering is a new concept in Direct3D 11; deferred rendering is designed to support rendering on one thread while recording commands for rendering on additional threads. This parallel, multithread strategy allows you to break up complex scenes into concurrent tasks. For more information, see Immediate and Deferred Rendering.
Fast semantics with an immediate and deferred contexts
Fast semantics can be applied at context granularity; you can create an immediate context with fast semantics, and you can create a deferred context with fast semantics.
A command list recorded by a deferred context that has been created with fast semantics will itself employ fast semantics upon execution. Fast semantics command lists may be executed on an immediate context created without fast semantics. Both fast semantics and legacy semantics command lists may be executed on an immediate context created with fast semantics - however, fast and legacy semantics command lists cannot be mixed within the scope of BeginCommandListExecution and EndCommandListExecution calls.
After a context has been created with fast semantics, its behavior will change from its legacy counterpart in several key areas. Failure to address these changes will result in rendering errors and possible GPU hangs—no existing graphics application will be able to just set the FAST_SEMANTICS flag and continue to work unmodified. The following sections document the most significant differences to be expected and addressed when using a context created with fast semantics.
Implementing Fast Semantics in your title
Using fast semantics in a title has the following considerations for coding.
No hazard tracking
- Contexts and command lists created with fast semantics will perform no fence-based updates on the resources referenced by them. Synchronization of access to resources must be managed through explicit fence insertion and wait operations, with CPU access achieved by fence polling (Map calls will not automatically block). Validation will warn of synchronization failures.
- Invalidation of GPU caches will not be performed by a context created with fast semantics. All necessary invalidation must be identified and handled by sending relevant pipelined events using ID3D11ComputeContextX::GpuSendPipelinedEvent. Validation will not perform cache invalidation, though PIX may ultimately be used in isolating errors due to lack of invalidation.
- No vertex, pixel, or compute partial flushes will be automatically performed by a context created with fast semantics. ID3D11DeviceContextX::CSEnableAutomaticGpuFlush is unsupported on fast semantics contexts and will fail. All necessary partial flushes must be explicitly invoked with GpuSendPipelinedEvent Validation will not perform partial flushes.
- A context created with fast semantics will not detect the need for decompression or fast clear elimination of render targets and depth/stencil buffers when they are set on the context for read access, nor will it automatically perform the necessary decompression of the resource. The compression and fast clear state of a resource may be queried, and decompression or fast clear elimination must be explicitly invoked through a new API extension. Validation will warn of failures to decompress resources before reading from, copying, or presenting them.
- A render target view whose base resource is a swap chain buffer will include no operation to wait until the buffer has concluded presentation, should the view be set on a fast semantics context. If Present has been called on the buffer and it either resides in the presentation queue or is actively being scanned, the context and GPU may begin immediately writing to the buffer. The ID3D11DeviceContextX::InsertWaitOnPresent immediate context API must be explicitly called on the back buffer every frame before setting a render target view or unordered access view (for write) on the context.
No object lifetime management
- Fast semantics contexts and command lists produced by such contexts will not modify the reference counts of objects used with them.
- Object reference counts (external and internal) will be unchanged when the object is set on a context. Objects cannot be set, fully released, and then referenced by a draw or dispatch. An object destroyed before it has been unset from a context will trigger a warning under validation (under the control of D3D11X_DEBUG_UBR_WARNING_DISABLE).
- Command lists will not take references on the objects recorded into them. No objects used in the recording of a command list can be fully released before execution of the command list. Command lists and their associated objects can be destroyed in any arbitrary order however.
- Objects cannot be fully released until all GPU commands referencing them have completed. GPU completion must be explicitly tested before calling the final release on an object.
No state shadowing
- A context created with fast semantics will not shadow any state that has been set on it.
- All Get APIs called on a fast semantics context will fail.
- Device context state cannot be created or swapped using the immediate context. The CreateDeviceContextState and SwapDeviceContextState methods will fail.
Explicit rebinding
- Any views bound to a context when Map is called on the underlying resource must be explicitly re-set on the context at every bound slot.
- Any render target or depth stencil views bound to a context when ClearRenderTargetView or ClearDepthStencilView are called on the views, or DecompressResource is called on the underlying resources, must be explicitly re-set on the context at every bound slot.
Explicit swap chain view rotation
- All render target views, shader resource views, and unordered access views on a swap chain buffer must be explicitly rotated after every Present. Rotation may be accomplished by maintaining a set of views associated with every buffer in the chain and cycling through them, by updating views every frame with the PlaceSwapChainView API to migrate them to the current back buffer, or by recreating the views every frame.
- Render target view, shader resource view, and unordered access view descriptors must be likewise updated by maintaining descriptor sets or performing view recomposition.
- All rotated views must be explicitly re-set on their contexts. Any command list referencing a rotated view must either be reconstructed or expanded into a rotating set.
Dynamic usage limitations
- While resources created with dynamic usage and mapped using write discard may be set on contexts created with fast semantics, their use is restricted and the persistence of their contents is limited.
- Dynamic resources referenced in a command list cannot inherit their contents. A dynamic resource referenced by a deferred context created with fast semantics must be mapped and filled before it is set on the context at every command list recording.
- Dynamic resources referenced outside of a command list will not have their contents modified by execution of a command list recorded by a fast semantics deferred context. Once command list execution finishes, the contents of a dynamic resource as visible to the immediate context will revert to that which was present before execution began, even if the resource’s view is explicitly re-bound on the immediate context.
- A dynamic resource mapped for write discard using Map on a deferred context created with fast semantics cannot be shared with any other context.
State resets on Present and Resume
- All state will be reset and pipeline bindings cleared after every Present (with the same effect produced as a call to ClearState).
- Suspend on an immediate context created with fast semantics will not save state or pipeline bindings. Resume will leave the immediate context in the same condition as a call to ClearState.
No state resets after command list execution and at start of command list recording
- Command list constructions performed by contexts created with fast semantics will not contain ClearState commands at their start to reset them to default state and bindings. All state in a fast semantics deferred context will persist between the recording of one command list and the next. Only explicit changes to state will be reflect in command list recordings.
- An immediate context created with fast semantics will not reset all state to default or clear resource bindings after command list execution (ExecuteCommandList or EndCommandListExecution), nor will it support restoring pre-execution state. State and resource bindings set during the course of command list execution will persist after execution into the immediate context.
Minimum level of detail set on view rather than resource
- The MinLOD used when sampling from a texture must be set on the shader resource view and not the underlying resource when the view is set on a context created with fast semantics.
- The MinLOD for a view is initially taken from the current MinLOD set on the underlying resource. All subsequent changes to resource MinLOD made by SetResourceMinLOD after view creation will be ignored by the view with fast semantics.
- The shader resource view MinLOD may be updated using the SetShaderResourceViewMinLOD API extension. Updates to the view MinLOD will be ignored by contexts that have not been created with fast semantics (for compatibility, they will continue to defer to the MinLOD set using SetResourceMinLOD).
- Shader resource view descriptors set on contexts created with either fast or legacy semantics will use the MinLevelOfDetail specified in the texture access control description (D3D11X_TEX_ACCESS_CONTROL) when composed, ignoring the referenced resource’s MinLOD.
- The range of SetResources, ..SetFastShaderResource, and ..SetPlacementShaderResource methods will respect a view object’s MinLOD established with SetShaderResourceViewMinLOD , even when called on a context that has not been created with fast semantics (the APIs always act as though the context was created with fast semantics).
- For contexts created with either fast or legacy semantics, changes to resource and view MinLOD made after the shader resource view has been set on a context will not take effect until the view has been re-bound on the context.
No UpdateSubresource or UpdateSubresource1
No unordered access views on buffers with append or counter
No automatic appending to stream output buffers
- SOSetTargets will fail if any of the given offsets is a value of -1 (append).
No automatic primitive resets on index values of 0xFFFF when using 16 bit index buffers
- The default primitive reset index value is 0xFFFFFFFF on contexts created with fast semantics, which will be used on both 16 bit and 32 bit index buffers.
- For 16 bit index buffers, the primitive reset index value should be explicitly changed through the API extension ID3D11DeviceContextX::IASetPrimitiveResetIndex (though use of the API is disallowed on legacy semantics contexts), for example:
pDeviceContext->IASetIndexBuffer( pBuffer, format, 0 );
if ( format >= DXGI_FORMAT_R8G8_TYPELESS && format <= DXGI_FORMAT_R16_SINT )
{
pDeviceContext->IASetPrimitiveResetIndex( DX11_16BIT_INDEX_STRIP_CUT_VALUE );
}
Fast kickoffs and write combined buffers
- An immediate context created with fast semantics will always employ fast kickoffs, and always create command buffers and dynamic buffers as write-combined.
- The behavior is consistent with the behavior that is produced by using the D3D11_CREATE_DEVICE_FAST_KICKOFFS, D3D11_CREATE_DEVICE_WRITE_COMBINED_COMMAND_BUFFERS, and D3D11_CREATE_DEVICE_WRITE_COMBINED_DYNAMIC_BUFFERS device creation flags (see D3D11_CREATE_DEVICE_FLAG).
See also
DirectX
Optimizing Monolithic Driver Performance
Fast Semantics Render Loops
Descriptor Tables