-
Notifications
You must be signed in to change notification settings - Fork 345
Description
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;
};
};- 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.
- 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.
- Shader4ComponentMapping enables the SRV to choose how memory gets routed to the 4 return components in a shader after a memory fetch.
- 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:
- Usage: D3D12 defines 4 kinds of resource views for different usages.
- Format: D3D12 requires the format of the resource view must be compatible with the original texture.
- Type: D3D12 requires this type must be the same as the resource type of the underlying resource.
- Component Remapping: D3D12 supports texture component remapping.
- 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?- 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.
- 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.
- levelRange specifies which mipmap levels are visible in the texture view.
- sliceRange specifies which array slices are visible in the new texture view.
Here is the summary of texture view on Metal:
- Usage: Metal only allows using makeTextureView() on the textures created with MTLTextureUsagePixelFormatView usage. Metal cannot specify the usage of the texture view in makeTextureView().
- Format: Metal requires the new pixel format must be compatible with the old pixel format. Color pixel formats of different sizes are not compatible.
- Type: The new texture type must be compatible with the old texture type.
- Component Remapping: Metal does not support texture component remapping.
- 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;- viewType specifies the type of the image view. Vulkan defines the compatibility requirements between the image view and the original image.
- Image cube map array is an optional Vulkan feature which has already been widely supported.
- If the image was not created with VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT flag, the view type cannot be cube map or cube map array.
- Vulkan does not allow creating a 2D or 2D array view on a 3D image without VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT flag.
- format specifies the format of the image view.
- If image was created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag, and if the format of the image is not multi-planar , format can be different from the image’s format.
- If image was created without the VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT flag and its format is not equal to the format of the image view, they must be compatible.
- components specifies a remapping of color components.
- 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:
- Usage: Vulkan cannot specify usage when creating an image view.
- 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.
- 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.
- Component Remapping: Vulkan supports texture component remapping.
- 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();
};- 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.
- 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.
- 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.
- 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.
- Component remapping is not included as it is not supported in Metal.
- 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.
- 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.
- aspect specifies which part (color, depth and/or stencil) is included in this texture view.