这是indexloc提供的服务,不要输入任何密码
Skip to content

Investigation: Texture View #79

@Jiawei-Shao

Description

@Jiawei-Shao

Introduction

In explicit APIs, texture views are used to specify which range of subresources are used by the shaders and how the data in the texture is interpreted. This report investigates how to support texture views in WebGPU.

Native APIs

D3D12

In D3D12, A view is a format-specific way to look at the data in a resource. D3D12 provides 4 kinds of resource views for different usages:

  • Shader Resource View (SRV) wraps a texture in a format that the shaders can read.
  • Unordered Access View (UAV) wraps a texture in a format that the shaders can both read and write.
  • Render Target View (RTV) enables rendering scene to the specified texture.
  • Depth Stencil View (DSV) enables a texture to hold depth and stencil information.

We will mainly focus on SRVs and UAVs here because RTVs and DSVs are CPU state-tracking objects and aren’t used in shaders.

To create a SRV, we need D3D12_SHADER_RESOURCE_VIEW_DESC struct:

typedef struct D3D12_SHADER_RESOURCE_VIEW_DESC {
  DXGI_FORMAT         Format;
  D3D12_SRV_DIMENSION ViewDimension;
  UINT                Shader4ComponentMapping;
  union {
    D3D12_BUFFER_SRV                            Buffer;
    D3D12_TEX1D_SRV                             Texture1D;
    D3D12_TEX1D_ARRAY_SRV                       Texture1DArray;
    D3D12_TEX2D_SRV                             Texture2D;
    D3D12_TEX2D_ARRAY_SRV                       Texture2DArray;
    D3D12_TEX2DMS_SRV                           Texture2DMS;
    D3D12_TEX2DMS_ARRAY_SRV                     Texture2DMSArray;
    D3D12_TEX3D_SRV                             Texture3D;
    D3D12_TEXCUBE_SRV                           TextureCube;
    D3D12_TEXCUBE_ARRAY_SRV                     TextureCubeArray;
    D3D12_RAYTRACING_ACCELERATION_STRUCTURE_SRV RaytracingAccelerationStructure;
  };
};
  1. Format specifies the format of the SRV. D3D12 requires when viewing a resource, the resource-view description must specify a typed format, that is compatible with the resource format.
  2. ViewDimension specifies the resource type of the SRV. It also determines which item to use in the union member of the struct. This type is the same as the resource type of the underlying resource.
  3. Shader4ComponentMapping enables the SRV to choose how memory gets routed to the 4 return components in a shader after a memory fetch.
  4. The union member specifies the information of the subresources for the SRV. Here we take D3D12_TEX2D_ARRAY_SRV for example:
typedef struct D3D12_TEX2D_ARRAY_SRV {
  UINT  MostDetailedMip;
  UINT  MipLevels;
  UINT  FirstArraySlice;
  UINT  ArraySize;
  UINT  PlaneSlice;
  FLOAT ResourceMinLODClamp;
};
  • MostDetailedMap and MipLevels specify the visible range of mipmap levels in the shader.
  • FirstArraySlice and ArraySize specify the visible range of texture array slices.
  • PlaneSlice specifies the plane slice number of the plane to use in an array of textures.
  • ResourceMinLODClamp specifies a value to clamp sample LOD values to. For example, if you specify 2.0f for the clamp value, you ensure that no individual sample accesses a mip level less than 2.0f.

To create a UAV, we need D3D12_UNORDERED_ACCESS_VIEW_DESC struct:

typedef struct D3D12_UNORDERED_ACCESS_VIEW_DESC {
  DXGI_FORMAT         Format;
  D3D12_UAV_DIMENSION ViewDimension;
  union {
    D3D12_BUFFER_UAV      Buffer;
    D3D12_TEX1D_UAV       Texture1D;
    D3D12_TEX1D_ARRAY_UAV Texture1DArray;
    D3D12_TEX2D_UAV       Texture2D;
    D3D12_TEX2D_ARRAY_UAV Texture2DArray;
    D3D12_TEX3D_UAV       Texture3D;
  };
};

The meanings of the fields in this struct are very similar to the ones in D3D12_SHADER_RESOURCE_VIEW_DESC. For the union members of this struct, we take the definition of D3D12_TEX2D_ARRAY_UAV for example:

typedef struct D3D12_TEX2D_ARRAY_UAV {
  UINT MipSlice;
  UINT FirstArraySlice;
  UINT ArraySize;
  UINT PlaneSlice;
};

According to this definition, D3D12 only allows creating UAV on one mipmap slice of a texture.

Here is the summary of D3D12 texture views:

  1. Usage: D3D12 defines 4 kinds of resource views for different usages.
  2. Format: D3D12 requires the format of the resource view must be compatible with the original texture.
  3. Type: D3D12 requires this type must be the same as the resource type of the underlying resource.
  4. Component Remapping: D3D12 supports texture component remapping.
  5. Multi-planar Textures: D3D12 supports creating resource views on one plane of a multi-planar texture.

Metal

Metal provides makeTextureView() to create a texture view that shares the same storage allocation of the calling texture object, reinterpreting the data with a different format and type.

A texture must be created with MTLTextureUsagePixelFormatView usage if you want to call makeTextureView() on this texture.

Here is the declaration of makeTextureView():

func makeTextureView(pixelFormat: MTLPixelFormat, 
                     textureType: MTLTextureType,
                     levels levelRange: Range<Int>,
                     slices sliceRange: Range<Int>) ->MTLTexture?
  1. pixelFormat specifies the pixel format of the new texture view. Metal requires the new pixel format must be compatible with the original pixel format. For example, you can't use this method between color pixel formats of different sizes.
  2. textureType specifies the type of the new texture view. The new texture type is required to be compatible to the original texture type.
  • MTLTextureTypeCube and MTLTextureTypeCubeArray is compatible to MTLTextureType2DArray, so we can use cube map textures by creating a cube map (array) texture view on a 2D array texture.
  • MTLTextureType3D is only compatible to MTLTextureType3D, which means Metal does not allow creating a 2D array texture view on a 3D texture.
  1. levelRange specifies which mipmap levels are visible in the texture view.
  2. sliceRange specifies which array slices are visible in the new texture view.

Here is the summary of texture view on Metal:

  1. Usage: Metal only allows using makeTextureView() on the textures created with MTLTextureUsagePixelFormatView usage. Metal cannot specify the usage of the texture view in makeTextureView().
  2. Format: Metal requires the new pixel format must be compatible with the old pixel format. Color pixel formats of different sizes are not compatible.
  3. Type: The new texture type must be compatible with the old texture type.
  4. Component Remapping: Metal does not support texture component remapping.
  5. Multi-planar Textures: Metal supports 2 YUV pixel formats, but Metal cannot create a texture view on one plane of a multi-planar texture.

Vulkan

Vulkan supports vkCreateImageView() on creating image view on a given image. A VkImageViewCreateInfo struct is needed for this function. Here is the definition of this struct:

typedef struct VkImageViewCreateInfo {
    VkStructureType            sType;
    const void*                pNext;
    VkImageViewCreateFlags     flags;
    VkImage                    image;
    VkImageViewType            viewType;
    VkFormat                   format;
    VkComponentMapping         components;
    VkImageSubresourceRange    subresourceRange;
} VkImageViewCreateInfo;
  1. viewType specifies the type of the image view. Vulkan defines the compatibility requirements between the image view and the original image.
  1. format specifies the format of the image view.
  1. components specifies a remapping of color components.
  2. subresourceRange specifies the range of the image in the image view. Here is the definition of VkImageSubresourceRange:
typedef struct VkImageSubresourceRange {
    VkImageAspectFlags    aspectMask;
    uint32_t              baseMipLevel;
    uint32_t              levelCount;
    uint32_t              baseArrayLayer;
    uint32_t              layerCount;
} VkImageSubresourceRange;
  • aspectMask is a bitmask of VkImageAspectFlagBits that specifies which aspect(s) of the image are included in the view.
    • aspectMask must be only VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT if format is a color, depth-only or stencil-only format, respectively, except if format is a multi-planar format.
    • For images in multi-planar formats, aspectMask can be VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT, or VK_IMAGE_ASPECT_PLANE_2_BIT to create a single-plane image view.
  • baseMipLevel and levelCount specify the visible range of the mipmap levels in shaders.
  • baseArrayLayer and layerCount specify the visible range of the array layers in shaders.

Here is the summary of Vulkan image views:

  1. Usage: Vulkan cannot specify usage when creating an image view.
  2. Format: For non-multi-planar formats, Vulkan only allows creating image views in different format on the images created with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, and the format of the image view must be compatible to the image.
  3. Type: Vulkan requires the type of the image view must be compatible with the image. Image cube map array is an extension in Vulkan. Vulkan only allows creating a cube map or cube map array view on the images created with VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT. Vulkan only allows creating a 2D or 2D array view on the 3D images created with VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT.
  4. Component Remapping: Vulkan supports texture component remapping.
  5. Multi-planar Textures: Vulkan supports creating resource views on a plane of a multi-planar texture.

Proposal

Here is our proposal on WebGPU texture view:

enum WebGPUTextureViewDimension {
    "1d",
    "2d",
    "2darray",
    "cube",
    "cubearray",
    "3d",
};


dictionary WebGPUTextureViewDescriptor {
    WebGPUTextureFormat format;
    WebGPUTextureViewDimension type;
    WebGPUTextureAspectFlags aspect;
    u32 baseMipLevel;
    u32 levelCount;
    u32 baseArrayLayer;
    u32 layerCount;
};

interface WebGPUTexture {
   WebGPUTextureView createTextureView(WebGPUTextureViewDescriptor desc);
   WebGPUTextureView createDefaultTextureView();
};
  1. format specifies the format of the texture view. D3D12, Metal and Vulkan all have requirements that the format of the view must be compatible with that of the original texture.
  • We need to define the rules of format compatibility based on all the explicit APIs.
  • The issues on compressed formats and multi-planar formats can be discussed after WebGPU MVP.
  1. type specifies the type of the texture view.
    We should follow Metal’s compatibility rule as it is the most strict one.
Texture Type Supported Texture View Type
1D 1D
2D 2D, 2D array, Cube map, Cube map array
3D 3D
  • 1D array is not included because MTLTextureType1DArray is not included in Metal’s compatibility rule.
  • Cube map array is included because it has been universally supported in Vulkan.
  • On Vulkan we always set VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT when creating a 2D texture whose arrayLayer is no less than 6. We may consider other choices if this method causes any big performance issues.
  1. baseMipLevel and levelCount specify the visible range of the mipmap levels in shaders.
  • levelCount is limited to 1 when the texture view is bound as a writable resource as D3D12 does not support creating a UAV that covers multiple mipmap levels of a texture.
  1. baseArrayLayer and layerCount specify the visible range of the array layers in shaders.
  • layerCount must be 6 if the texture view type is cube map or a multiple of 6 if the texture view type is cube map array.
  1. Component remapping is not included as it is not supported in Metal.
  2. We always set MTLTextureUsagePixelFormatView on Metal and VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT on Vulkan when creating new textures so that we can always create texture views on all textures on these platforms.
  • We may consider other choices if this method causes any big performance issues.
  1. We provide a fast path to create a texture view that uses the same type, same format, the whole mipmap levels and whole array layers of the original texture.
  2. aspect specifies which part (color, depth and/or stencil) is included in this texture view.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions