Skip to content
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

Suport for reading from StorageTexture by a shader (WebGPU) #6268

Merged
merged 3 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions src/platform/graphics/bind-group-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class BindStorageBufferFormat extends BindBaseFormat {
* - {@link SHADERSTAGE_FRAGMENT}
* - {@link SHADERSTAGE_COMPUTE}
*
* @param {boolean} readOnly - Whether the storage buffer is read-only, or read-write. Defaults
* @param {boolean} [readOnly] - Whether the storage buffer is read-only, or read-write. Defaults
* to false. This has to be true for the storage buffer used in the vertex shader.
*/
constructor(name, visibility, readOnly = false) {
Expand Down Expand Up @@ -107,7 +107,7 @@ class BindTextureFormat extends BindBaseFormat {
* - {@link SHADERSTAGE_FRAGMENT}
* - {@link SHADERSTAGE_COMPUTE}
*
* @param {string} textureDimension - The dimension of the texture. Defaults to
* @param {string} [textureDimension] - The dimension of the texture. Defaults to
* {@link TEXTUREDIMENSION_2D}. Can be:
*
* - {@link TEXTUREDIMENSION_1D}
Expand All @@ -117,7 +117,7 @@ class BindTextureFormat extends BindBaseFormat {
* - {@link TEXTUREDIMENSION_CUBE_ARRAY}
* - {@link TEXTUREDIMENSION_3D}
*
* @param {number} sampleType - The type of the texture samples. Defaults to
* @param {number} [sampleType] - The type of the texture samples. Defaults to
* {@link SAMPLETYPE_FLOAT}. Can be:
*
* - {@link SAMPLETYPE_FLOAT}
Expand All @@ -126,7 +126,7 @@ class BindTextureFormat extends BindBaseFormat {
* - {@link SAMPLETYPE_INT}
* - {@link SAMPLETYPE_UINT}
*
* @param {boolean} hasSampler - True if the sampler for the texture is needed. Note that if the
* @param {boolean} [hasSampler] - True if the sampler for the texture is needed. Note that if the
* sampler is used, it will take up an additional slot, directly following the texture slot.
* Defaults to true.
*/
Expand Down Expand Up @@ -158,24 +158,37 @@ class BindStorageTextureFormat extends BindBaseFormat {
* Create a new instance.
*
* @param {string} name - The name of the storage buffer.
* @param {number} format - The pixel format of the texture. Note that not all formats can be
* @param {number} [format] - The pixel format of the texture. Note that not all formats can be
* used. Defaults to {@link PIXELFORMAT_RGBA8}.
* @param {string} textureDimension - The dimension of the texture. Defaults to
* @param {string} [textureDimension] - The dimension of the texture. Defaults to
* {@link TEXTUREDIMENSION_2D}. Can be:
*
* - {@link TEXTUREDIMENSION_1D}
* - {@link TEXTUREDIMENSION_2D}
* - {@link TEXTUREDIMENSION_2D_ARRAY}
* - {@link TEXTUREDIMENSION_3D}
*
* @param {boolean} [write] - Whether the storage texture is writeable. Defaults to true.
* @param {boolean} [read] - Whether the storage texture is readable. Defaults to false. Note
* that storage texture reads are only supported if
* {@link GraphicsDevice#supportsStorageTextureRead} is true. Also note that only a subset of
* pixel formats can be used for storage texture reads - as an example, PIXELFORMAT_RGBA8 is not
* compatible, but PIXELFORMAT_R32U is.
*/
constructor(name, format = PIXELFORMAT_RGBA8, textureDimension = TEXTUREDIMENSION_2D) {
constructor(name, format = PIXELFORMAT_RGBA8, textureDimension = TEXTUREDIMENSION_2D, write = true, read = false) {
super(name, SHADERSTAGE_COMPUTE);

// PIXELFORMAT_***
this.format = format;

// TEXTUREDIMENSION_***
this.textureDimension = textureDimension;

// whether the texture is writeable
this.write = write;

// whether the texture is readable
this.read = read;
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/platform/graphics/graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,20 @@ class GraphicsDevice extends EventHandler {
*/
supportsCompute = false;

/**
* True if the device can read from StorageTexture in the compute shader. By default, the
* storage texture can be only used with the write operation.
* When a shader uses this feature, it's recommended to use a `requires` directive to signal the
* potential for non-portability at the top of the WGSL shader code:
* ```javascript
* requires readonly_and_readwrite_storage_textures;
* ```
*
* @readonly
* @type {boolean}
*/
supportsStorageTextureRead = false;

/**
* Currently active render target.
*
Expand Down
6 changes: 4 additions & 2 deletions src/platform/graphics/webgpu/webgpu-bind-group-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ class WebgpuBindGroupFormat {
bindGroupFormat.storageTextureFormats.forEach((textureFormat) => {

const { format, textureDimension } = textureFormat;
key += `#${textureFormat.slot}ST:${format}-${textureDimension}`;
const { read, write } = textureFormat;
key += `#${textureFormat.slot}ST:${format}-${textureDimension}-${read ? 'r1' : 'r0'}-${write ? 'w1' : 'w0'}`;

// storage texture
entries.push({
Expand All @@ -176,7 +177,8 @@ class WebgpuBindGroupFormat {
storageTexture: {

// The access mode for this binding, indicating readability and writability.
access: 'write-only', // only single option currently, more in the future
// 'write-only' is always support, 'read-write' and 'read-only' optionally
access: read ? (write ? 'read-write' : 'read-only') : 'write-only',

// The required format of texture views bound to this binding.
format: gpuTextureFormats[format],
Expand Down
4 changes: 4 additions & 0 deletions src/platform/graphics/webgpu/webgpu-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class WebgpuGraphicsDevice extends GraphicsDevice {

// WebGPU currently only supports 1 and 4 samples
this.samples = this.backBufferAntialias ? 4 : 1;

// WGSL features
const wgslFeatures = navigator.gpu.wgslLanguageFeatures;
this.supportsStorageTextureRead = wgslFeatures.has('readonly_and_readwrite_storage_textures');
}

async initWebGpu(glslangUrl, twgslUrl) {
Expand Down