Cache Synchronization

By radv_cmd_flush_bits, there are many different types of cache in the GPU.

For example, we have a typical case where the texture is used as the color attachement first and used as the sampled image later. When the texture is used as the color attachement, CB(Color Block) Cache and CB META (Color Block Metadata) Cache are involved. But when the texture is used as the sampled image, L2 METADATA (Level 2 Metadata) cache will be involved. We need to flush all data in the CB Cache and CB META Cache to the memory and invalidate all data in the L2 METADATA Cache.

Metadata is some extra data which is used to improve the performance of the texture. For AMD GPU, the DCC metadata can be used to perform the clear operation more efficiently on the color attachmemnt. And by "Figure 23.13" of Real-Time Rendering Fourth Edition, HiZ (Hierarchy Z) is usualy used to handle coarse depth testing for the depth attachment. For AMD GPU, by "23.10.3 Case Study: AMD GCN Vega" of Real-Time Rendering Fourth Edition, the related HiZ data is stored in the HTILE metadata. Technically, we may also need to decompress the metadata (see radv_decompress_dcc and radv_expand_depth_stencil for more information) before we flush the cache.

In legacy OpenGL or Direct3D11 APIs, the texture usage is tracked by the driver. And the driver will handle the cache synchronization (and the metadata decompression) when the texture usage changes.

Evidently, it is more efficient for the application to handle the cache synchronization (and the metadata decompression) directly.

The changing of texture usage usually happens at the beginning or end of the render pass. We can efficiently use VkAttachmentDescription::initialLayout, VkAttachmentDescription::layout and VkAttachmentDescription::finalLayout to specify the changing of texture usage in Vulkan. Actually, we rarely use the vkCmdPipelineBarrier in Vulkan. But since there is no decent render pass in Direct3D12, we have to use the ID3D12GraphicsCommandList::ResourceBarrier at the beginning or end of the render pass to specify the changing of texture usage in Direct3D12.

The texture usage is denoted by VkImageLayout in Vulkan or D3D12_RESOURCE_STATES in Direct3D12. The essential of specifying the changing of the texture usage is to specify the cache synchronization. The old texture usage tells which cache we should flush, and the new texture usage tells which cache we should invalidate. Technically, if we do not need to preserve the content of the texture, especially for the textures which will be cleared at the beginning of the render pass, we do not need to provide correct old texture usage. We can efficiently specify VK_IMAGE_LAYOUT_UNDEFINED in Vulkan in such case, but we have to track the texture usage in Direct3D12 even if we do not need to preserve the content of the texture.