This document describes a proposal for adding support for taking a sliced view of a 3D image, where the result is a 3D image view with a restricted range of depth slices.

1. Problem Statement

D3D11 and D3D12 allows applications to create a 3D UAV (storage image) descriptor where the depth range is offset and clamped. For API docs, see D3D12_TEX3D_UAV.

While this can be emulated by passing down metadata to the shader and doing manual range computation, it is not as efficient as using the existing hardware support for this feature, especially when faced with descriptor indexing, which is essentially required for D3D12 emulation.

2. Solution Space

The proposed solution needs to be able to create a VkImageView where we view a range of the depth slices. There are two main options for exposing this:

  1. Allowing 2D array view of a 3D images, even when used for storage image purposes. Shader code can rewrite 3D storage image types to 2D array storage images without any significant change. Functionally, the difference is minimal.

  2. Specifying the offset and range when creating a 3D image view of a 3D image, using an extension structure at image view creation time.

2D array support was rejected from VK_EXT_image_2d_view_of_3d due to lack of universal hardware support, and this idea would have similar concerns. There are also potential performance issues allowing 2D array views on 3D. We still expect to access the 3D resource as a 3D resource in D3D12 emulation, so it seems more direct to expose 3D views rather than 2D array. It also has the advantage of not having to modify shader code to accommodate this API feature.

3. Proposal

3.1. New Vulkan feature

typedef struct VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           imageSlicedViewOf3D;
} VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT;

3.2. New VkImageViewSlicedCreateInfoEXT struct and slice enum

#define VK_REMAINING_3D_SLICES_EXT        (~0U)

typedef struct VkImageViewSlicedCreateInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    uint32_t           sliceOffset;
    uint32_t           sliceCount;
} VkImageViewSlicedCreateInfoEXT;

VkImageViewSlicedCreateInfoEXT changes how 3D images are accessed in shaders. Normally, the Z coordinate is bounded by the depth value specified in the VkExtent3D of VkImageCreateInfo. If this struct is appended to the pNext chain when creating an image view, however, any Z coordinate used to access the image view in a shader is offset by sliceOffset. sliceCount controls how many depth slices are part of the view. Accessing texels outside this range is considered out of bounds and it handled by robustness with the usual rules.

3.3. Enforcing single mip level

When expressing ranges in terms of the integer Z coordinate, this only works if the image view is restricted to a single mip level. This matches D3D12 restrictions, which does not support the concept of multiple UAV levels. The Z coordinate range is not adjusted based on log2 reduction.

3.4. Only storage image support

This feature is only supported for UAVs on D3D12, and in Vulkan it is only supported on storage images. Similar to VK_EXT_image_view_min_lod, the 3D slice is ignored when the descriptor is consumed with a descriptor type that is not supported.

4. Issues

4.1. RESOLVED: Do we need another image creation flag?