New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigation: Storage Texture #513
Comments
Thank you for the excellent investigation!
That approach looks the simplest without loss of generality imho. |
@Jiawei-Shao
Argument buffers have 2 tiers, and writable textures are not supported on the 1st tier.
This block is repeated. Was it meant to explain how the "write" access works?
There are severe restrictions on making memory barriers inside a render pass, making it mostly unfeasible to do.
I agree, that would be useful.
How would this help specifically? The list that follows, I think, mostly applies to the benefits of "READONLY-STORAGE".
Are they equivalent? My understanding was that
Metal baseline is macOS 10.12, so this isn't a restriction.
Could you clarify this requirement please? The investigation only mentions the barriers for inside-render-pass usage, Agree with the rest of the proposal! 👍 |
Hi @kvark, My replies are inline, PTAL, thanks!
Oh here I want to talk about the total size of the argument table, not for Metal Argument buffers.
Yes it's duplicated and I've removed it.
Thanks to point out this and I have added the restrictions in this paragraph.
It will help create the right D3D12 root signatures. The binding point "
On Vulkan,
Yes. It would be great to define the minimum feature requirements for the devices that support WebGPU.
Oh I just see the Metal document mentions that within a Render Command Encoder, for textures, we need the |
@Jiawei-Shao I think my points didn't get through. Let me try to re-phrase.
We agreed previously that the API is designed with native support by Metal Argument Buffers in mind. So we need to consider their limitations in the binding space.
Or, the user could just use the "sampled-texture" binding point instead. Is there a downside to do so versus adding a new bind point?
What I'm saying is that there might be performance and quality considerations for using
We agreed to not synchronize individual draw calls within a render pass a while ago. That's why I'm saying the barriers are not needed here. |
@kvark thanks for your comments!
Thanks for your comments and I have added the information.
In Vulkan
OK now I agree with you and I've removed that paragraph.
Thanks for your explanation and I've added this decision into the proposal. |
Didn't we to target all Metal devices? It started with macOS 10.11 so we'd need an extension for read-write storage textures. |
Ah right, so 10.11 is a problem... :/ |
In SPIR-V as " |
As discussed offline with @Jiawei-Shao the differing hardware paths between |
I thought it was particularly sad to miss out on rg16float/uint/sint formats, so I went looking. It looooks like a bunch of these optional-in-Vulkan formats are valid with the feature gpuinfo is less than helpful in how it tries to make the format bits easier to read, but now I can't tell what they mean! I'm hoping that these otherwise-common formats have enough support to reintroduce after further investigation. |
I'm trying to ping pong update floating point textures in the compute shader and when using const texture = device.createTexture({
size: {
width: 64,
height: 64,
},
format: "rgba32float",
usage:
GPUTextureUsage.COPY_DST |
GPUTextureUsage.STORAGE |
GPUTextureUsage.SAMPLED,
}) [[group(0), binding(1)]] var writeTex: texture_storage_2d<rgba32float, write>; Chrome Version 94.0.4593.0 (Official Build) canary (x86_64) |
I finally figured it out... The error was
|
Could someone check whether requiring this feature is now possible? The link seems to indicate only 67 entries for Android that don't have support for shaderStorageImageExtendedFormats compared to 637 entries for devices that do. Yet, the "Device Coverage" percentage for Android is reported as 62% so maybe I'm misunderstanding something |
@fintelia this is a great suggestion!
Perhaps it shows 67 unique reports, but the actual number of reports is bigger (i.e. duplicate reports).
I see a lot of correlation with devices lacking a good maxDrawIndexedIndexValue - #1343 (comment) . Namely, Qualcomm devices. However, in addition to Qualcomm there are ARM, ImgTec, and software Vulkan implementations (hello #2030). So requiring the It would be great to make this decision based on the actual statistics from browsers use on these devices, as opposed to vulkaninfo reports. |
Looking more closely at the non-Qualcomm devices, it seems the ARM devices all are unsupported due to maxImageArrayLayers=256 (see #1327) while most of the ImgTec ones lack the necessary compressed texture support (EDIT: see #144 (comment)). On the software Vulkan implementation front, shaderStorageImageExtendedFormats is supported by both SwiftShader and LavaPipe at this point |
compressed textures aren't in WebGPU core though. But overall this does sound as quite a strong argument to just require |
We agreed to require (BC || (ETC && ASTC)) but those devices don't have ASTC |
Editors meeting:
If anybody wants to collect this list, this would be much welcome! |
We should try to collect a complete list of reports from gpuinfo.org, and filter out all the ones we know we've dropped, and then see what else we would lose by requiring this. |
We should probably revisit that, it's not ok for WebGPU to be completely unsupported on all ARM Android devices. |
Based on internal data, we shouldn't require |
I think this investigation can be closed: storage textures have been added to the spec (at least writable ones. We need data on whether to add readwrite ones, see #1772) |
Introduction
“
Storage-texture
” is a binding type defined in WebGPU Specification. This binding type allows performing texture reads without sampling and store to arbitrary positions in shaders. This report will discuss the implementation details to support Storage Textures in WebGPU.Related Features
Texture Usage
D3D12, Metal and Vulkan all require that the texture must be created with a proper usage before it can be used as a storage texture.
On D3D12, when we want to use the texture as a read-only storage texture, a Shader Resource View (SRV) will be enough. When we want to write to a storage texture, we need to create an Unordered Access View (UAV) on it, which requires the texture be created with the flag
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
. The D3D12 document suggests “applications should avoid setting this flag when unordered access operations will never occur”. UAVs are allocated in the same type of descriptor heap as SRVs (CBV/SRV/UAV Heap).On Metal, the option
MTLTextureUsageShaderRead
is required when we want to access the given texture with aread()
orsample()
function in any shader. When we want to access the texture withload()
function, we need to specify the optionMTLTextureUsageShaderWrite
when we create the texture.On Vulkan, we are required to set
VK_IMAGE_USAGE_STORAGE_BIT
to specify that the image can be used to create aVkImageView
suitable for occupying aVkDescriptorSet
slot of typeVK_DESCRIPTOR_TYPE_STORAGE_IMAGE
.Texture Format
D3D12, Metal and Vulkan all have the minimum requirements on the texture formats that support storage textures. Here we will mainly talk about the supports of writable storage textures and read-write storage textures on each texture color format.
Writable Storage Textures
The supports of writable storage textures on D3D12, Metal and Vulkan on the texture color formats that are required in current WebGPU SPEC are summarized in the following table.
Read-Write Storage Textures
D3D12 and Metal have special requirements on the texture formats that support both read and write in one shader.
D3D12 devices that support feature level 11_0 are required to support UAV Load on R32_FLOAT, R32_UINT and R32_SINT.
Metal supports “Texture ReadWrite” since Metal 1.2. On iOS 11+ and macOS 10.13+ we can query the Tier of the support of “ReadWrite Texture” with MTLDevice.readWriteTextureSupport.
The supports of read-write storage textures for all the texture color formats in the current WebGPU on D3D12, Metal and Vulkan are listed here:
Sample Count
D3D12 requires when we set
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
, the sample count must be 1.Metal requires multisampled textures only support “
read
” attribute in Metal Shading Languages (Chapter 2.8, “Textures”).Vulkan SPEC requires if the multisampled storage image feature (“
shaderStorageImageMultisample
”) is not enabled, and the usage containsVK_IMAGE_USAGE_STORAGE_BIT
,samples
must beVK_SAMPLE_COUNT_1_BIT
. The coverage of the Vulkan feature “shaderStorageImageMultisample
” is 67%.Resource Bindings
D3D12 defines a descriptor range type
D3D12_DESCRIPTOR_RANGE_TYPE_UAV
for UAVs in the root signature.Metal treats the textures used as storage textures the same as sampled textures (all of them should be set in the related Argument tables). For Metal Argument Buffers, Metal defines two Tiers for Argument Buffers and writable textures are only supported in Tier 2.
Vulkan defines the descriptor type
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
for storage images. IfdescriptorType
isVK_DESCRIPTOR_TYPE_STORAGE_IMAGE
, theimageView
member of each element ofpImageInfo
must have been created withVK_IMAGE_USAGE_STORAGE_BIT
set.Shader Stages
On D3D12 I fail to find any restrictions to limit the use of UAVs in any shader stages. On D3D11, with feature level 11_0, UAVs can only be used in the pixel shaders and compute shaders, and with feature level 11_1+, UAVs can be used in all shader stages.
Metal supports
MTLTextureUsageShaderRead
in any shader stage, andMTLTextureUsageShaderWrite
only in compute shaders. SinceOSX_GPUFamily1_v2
, both vertex and fragment functions can now write to textures.Vulkan SPEC requires storage image loads must be supported in all shader stages, and stores to storage images in compute shaders.
fragmentStoresAndAtomics
” specifies whether storage buffers and images support stores and atomic operations in the fragment shader stage. This feature has a coverage of 99%.vertexPipelineStoresAndAtomics
” specifies whether storage buffers and images support stores and atomic operations in the vertex, tessellation, and geometry shader stages. This feature has a coverage of 85%.Shader Operations
Sample, Load and Store
On D3D12, according to HLSL documents,
Sample()
can only be allowed on read-only texture objects (Texture1D
,Texture2D
, etc), and on writable texture objects (RWTexture2D
,RWTexture2DArray
, etc) it is not allowed to callSample()
. Both read-only and writable texture objects supportLoad()
operation.On Metal Shading Language (Chapter 2.8), “
sample
” and “read
” are different “access
” attributes. "sample
" implies the ability to read from a texture with and without a sampler, and “read
” implies without a sampler, a graphics or kernel function can only read the texture object.On Vulkan, According to the definition of
OpTypeImage
in SPIR-V, “Sampled
” indicates whether or not this image will be accessed in combination with a sampler. In the Vulkan execution environment,OpTypeImage
must have a “Sampled
” operand of 1 (sampled image) or 2 (storage image). “storage image
” and “sampled image
” have different usages in SPIR-V. SPIR-V providesOpImageRead
to read a texel from an image without a sampler andOpImageWrite
to write a texel to an image without a sampler. Both of these two instructions require the operand “Image
” must be an object whose type isOpTypeImage
with a “Sampled
” operand of 2.Atomic Functions
On D3D12, feature level 11_0 devices support atomic operations (UAV Atomic Exchange, UAV Atomic Signed Min/Max, UAV Atomic Unsigned Min/Max, UAV Atomic Add, UAV Atomic Bitwise Ops and UAV Atomic Cmp&Store/ Cmp&Exch) on
R32_UINT
andR32_SINT
.On Metal Shading Language (Chapter 6.13), atomic functions are only allowed on Metal atomic data, which does not include writable textures.
On Vulkan, the image atomic functions are supported on the formats with
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
. Vulkan SPEC (Table 65) requiresVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
must be supported onVK_FORMAT_R32_UINT
andVK_FORMAT_R32_SINT
.Resource Limits
On D3D12, the resource limits about UAVs are defined together with Hardware Tiers. The maximum number of UAVs in all descriptor tables across all stages are listed as follows:
According to the Metal document Metal-Feature-Set-Tables, the maximum number of entries in the texture argument table, per graphics or compute function are listed here:
MTLGPUFamilyApple1
,MTLGPUFamilyApple2
,MTLGPUFamilyApple3
(A7 - A10): 31MTLGPUFamilyApple4
,MTLGPUFamilyApple5
(A11, A12): 96MTLGPUFamilyApple6
,MTLGPUFamilyMac1
,MTLGPUFamilyMac2
: 128On Vulkan, the minimum required resource limits that are related to storage images in Vulkan SPEC are listed as follows:
maxPerStageDescriptorStorageImages
(4)maxDescriptorSetStorageImages
(4 * 6, 6 is the number of shader stages)maxFragmentCombinedOutputResources
(4)maxFragmentCombinedOutputResources
is the total number of storage buffers, storage images and output buffers which can be used in the fragment stage.Resource Barriers
On D3D12 there are two types of barriers that are related to UAVs:
D3D12_RESOURCE_STATE_UNORDERED_ACCESS
): A subresource must be in this state when it is accessed by the 3D pipeline via UAV.D3D12_RESOURCE_UAV_BARRIER
): indicate all UAV accesses (read or write) to a particular resource must complete before any future UAV accesses (read or write) can begin.On Metal devices that support
OSX_GPUFamily1_v2
, it is guaranteed that:textureBarrier
(deprecated, only available until macOS 10.14, useMTLCommandEncoder.memoryBarrierWithScope
since macOS 10.14) method ensures that writes performed in a given draw call are visible to subsequent reads in the next draw call.Vulkan defines image memory barriers that are only apply to memory accesses involving a specific image subresource range.
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
, for each descriptor that will be accessed via load or store operations theimageLayout
member for corresponding elements of pImageInfo must beVK_IMAGE_LAYOUT_GENERAL
.Besides, Vulkan SPEC has severe restrictions to use image memory barriers in a render pass instance:
vkCmdPipelineBarrier
is called within a render pass instance, theoldLayout
andnewLayout
members of any element ofpImageMemoryBarriers
must be equal to the layout member of an element of thepColorAttachments
,pResolveAttachments
orpDepthStencilAttachment
members of theVkSubpassDescription
instance that the current subpass was created with, that refers to the same image.vkCmdPipelineBarrier
is called within a render pass instance, theoldLayout
andnewLayout
members of an element ofpImageMemoryBarriers
must be equal.Because of these restrictions, the group has agreed to not synchronize individual draw calls within a render pass.
Proposal
Now that we have added "
storage-texture
" inGPUBindingType
and “STORAGE
” inGPUTextureUsage
, we can just discuss some details on the support of Storage Textures in WebGPU implementations.Textures that are used as writable storage textures cannot be multisampled as it is not allowed in D3D12 and Metal.
Maybe it is better to add “
READONLY-STORAGE
” as a new enum inGPUTextureUsage
because with this extra information we can easily know:D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS
when creating textures on D3D12.MTLTextureUsageShaderWrite
when creating textures on Metal.SAMPLED-TEXTURE
” being used as “READONLY-STORAGE
”, then on Vulkan we have to set bothVK_IMAGE_USAGE_SAMPLED_BIT
andVK_IMAGE_USAGE_STORAGE_BIT
, which may hurt the performance of texture sampling if the texture is actually only used for sampling.Maybe we also need to and “
readonly-storage-texture
” as a new type of binding point because we need to know the following information when we create the bind group layouts:D3D12_DESCRIPTOR_RANGE_TYPE_UAV
when creating the root signatures on D3D12.VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
as thedescriptorType
member of aVkDescriptorSetLayoutBinding
object used in the creation of Vulkan graphics pipeline asVK_DESCRIPTOR_TYPE_STORAGE_IMAGE
andVK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
are differentVkDescriptorType
enums.The color texture formats that are allowed to be writable storage textures on D3D12, Metal and Vulkan are summarized in the previous tables.
The support of Read-Write storage textures has to be an extension because it is only supported on macOS 10.12+ and iOS 11+.
Readable storage textures can be supported in all shader stages, and writable storage textures can only be supported in compute shaders.
vertexPipelineStoresAndAtomics
”We suggest the maximum number of storage images is 4 as it is following the resource limits in Vulkan, which is the strictest among D3D12, Metal and Vulkan.
We cannot support image atomic functions because this feature cannot be supported on Metal.
The text was updated successfully, but these errors were encountered: