diff --git a/src/Three.WebGPU.js b/src/Three.WebGPU.js index 01d65d22c0ff01..332b02a68c92a8 100644 --- a/src/Three.WebGPU.js +++ b/src/Three.WebGPU.js @@ -10,6 +10,8 @@ export { default as PostProcessing } from './renderers/common/PostProcessing.js' import * as RendererUtils from './renderers/common/RendererUtils.js'; export { RendererUtils }; export { default as StorageTexture } from './renderers/common/StorageTexture.js'; +export { default as Storage3DTexture } from './renderers/common/Storage3DTexture.js'; +export { default as StorageArrayTexture } from './renderers/common/StorageArrayTexture.js'; export { default as StorageBufferAttribute } from './renderers/common/StorageBufferAttribute.js'; export { default as StorageInstancedBufferAttribute } from './renderers/common/StorageInstancedBufferAttribute.js'; export { default as IndirectStorageBufferAttribute } from './renderers/common/IndirectStorageBufferAttribute.js'; diff --git a/src/renderers/common/Storage3DTexture.js b/src/renderers/common/Storage3DTexture.js new file mode 100644 index 00000000000000..99125aaceaad84 --- /dev/null +++ b/src/renderers/common/Storage3DTexture.js @@ -0,0 +1,79 @@ +import { Texture } from '../../textures/Texture.js'; +import { LinearFilter, ClampToEdgeWrapping } from '../../constants.js'; + +/** + * This special type of texture is intended for compute shaders. + * It can be used to compute the data of a texture with a compute shader. + * + * Note: This type of texture can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments Texture + */ +class Storage3DTexture extends Texture { + + /** + * Constructs a new storage texture. + * + * @param {number} [width=1] - The storage texture's width. + * @param {number} [height=1] - The storage texture's height. + * @param {number} [depth=1] - The storage texture's depth. + */ + constructor( width = 1, height = 1, depth = 1 ) { + + super(); + + //inherited from texture. Must be false for 3DTexture + this.isArrayTexture = false; + + /** + * The image object which just represents the texture's dimension. + * + * @type {{width: number, height: number, depth: number}} + */ + this.image = { width, height, depth }; + + /** + * The default `magFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {number} + */ + this.magFilter = LinearFilter; + + /** + * The default `minFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {number} + */ + this.minFilter = LinearFilter; + + /** + * This defines how the texture is wrapped in the depth direction and corresponds to + * *W* in UVW mapping. + * + * @type {number} + */ + this.wrapR = ClampToEdgeWrapping; + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isStorageTexture = true; + + /** + * Indicates whether this texture is a 3D texture. + * + * @type {boolean} + * + */ + this.is3DTexture = true; + + } + +} + +export default Storage3DTexture; diff --git a/src/renderers/common/StorageArrayTexture.js b/src/renderers/common/StorageArrayTexture.js new file mode 100644 index 00000000000000..0b9a95a0d3543e --- /dev/null +++ b/src/renderers/common/StorageArrayTexture.js @@ -0,0 +1,63 @@ +import { Texture } from '../../textures/Texture.js'; +import { LinearFilter } from '../../constants.js'; + +/** + * This special type of texture is intended for compute shaders. + * It can be used to compute the data of a texture with a compute shader. + * + * Note: This type of texture can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments Texture + */ +class StorageArrayTexture extends Texture { + + /** + * Constructs a new storage texture. + * + * @param {number} [width=1] - The storage texture's width. + * @param {number} [height=1] - The storage texture's height. + * @param {number} [depth=1] - The storage texture's depth. + */ + constructor( width = 1, height = 1, depth = 1 ) { + + super(); + + //inherited from texture + this.isArrayTexture = true; + + /** + * The image object which just represents the texture's dimension. + * + * @type {{width: number, height: number, depth: number}} + */ + this.image = { width, height, depth }; + + /** + * The default `magFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {number} + */ + this.magFilter = LinearFilter; + + /** + * The default `minFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {number} + */ + this.minFilter = LinearFilter; + + /** + * This flag can be used for type testing. + * + * @type {boolean} + * @readonly + * @default true + */ + this.isStorageTexture = true; + + } + +} + +export default StorageArrayTexture; diff --git a/src/renderers/common/nodes/NodeSampledTexture.js b/src/renderers/common/nodes/NodeSampledTexture.js index d3bc51ba382a37..4d55f76c75fb96 100644 --- a/src/renderers/common/nodes/NodeSampledTexture.js +++ b/src/renderers/common/nodes/NodeSampledTexture.js @@ -143,7 +143,7 @@ class NodeSampledTexture3D extends NodeSampledTexture { * @readonly * @default true */ - this.isSampledTexture3D = true; + this.is3DTexture = true; } diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 55488ec8aa7aa2..86014feac1e5c9 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -1701,24 +1701,29 @@ ${ flowData.code } } - } else if ( texture.isArrayTexture === true || texture.isDataArrayTexture === true || texture.isCompressedArrayTexture === true ) { + } else if ( uniform.node.isStorageTextureNode === true ) { - textureType = 'texture_2d_array'; + const format = getFormat( texture ); + const access = this.getStorageAccess( uniform.node, shaderStage ); - } else if ( texture.isVideoTexture === true ) { + const is3D = uniform.node.value.is3DTexture; + const isArrayTexture = uniform.node.value.isArrayTexture; - textureType = 'texture_external'; + const dimension = is3D ? '3d' : `2d${ isArrayTexture ? '_array' : '' }`; - } else if ( texture.isData3DTexture === true ) { + textureType = `texture_storage_${ dimension }<${ format }, ${ access }>`; - textureType = 'texture_3d'; + } else if ( texture.isArrayTexture === true || texture.isDataArrayTexture === true || texture.isCompressedArrayTexture === true ) { - } else if ( uniform.node.isStorageTextureNode === true ) { + textureType = 'texture_2d_array'; - const format = getFormat( texture ); - const access = this.getStorageAccess( uniform.node, shaderStage ); + } else if ( texture.is3DTexture === true || texture.isData3DTexture === true ) { - textureType = `texture_storage_2d<${ format }, ${ access }>`; + textureType = 'texture_3d'; + + } else if ( texture.isVideoTexture === true ) { + + textureType = 'texture_external'; } else { diff --git a/src/renderers/webgpu/utils/WebGPUBindingUtils.js b/src/renderers/webgpu/utils/WebGPUBindingUtils.js index 3e2f731dd14014..e846703ca3e18e 100644 --- a/src/renderers/webgpu/utils/WebGPUBindingUtils.js +++ b/src/renderers/webgpu/utils/WebGPUBindingUtils.js @@ -138,6 +138,16 @@ class WebGPUBindingUtils { } + if ( binding.texture.isArrayTexture ) { + + storageTexture.viewDimension = GPUTextureViewDimension.TwoDArray; + + } else if ( binding.texture.is3DTexture ) { + + storageTexture.viewDimension = GPUTextureViewDimension.ThreeD; + + } + bindingGPU.storageTexture = storageTexture; } else if ( binding.isSampledTexture ) { @@ -206,7 +216,7 @@ class WebGPUBindingUtils { texture.viewDimension = GPUTextureViewDimension.TwoDArray; - } else if ( binding.isSampledTexture3D ) { + } else if ( binding.texture.is3DTexture ) { texture.viewDimension = GPUTextureViewDimension.ThreeD; @@ -428,7 +438,7 @@ class WebGPUBindingUtils { dimensionViewGPU = GPUTextureViewDimension.Cube; - } else if ( binding.isSampledTexture3D ) { + } else if ( binding.texture.is3DTexture ) { dimensionViewGPU = GPUTextureViewDimension.ThreeD; diff --git a/src/renderers/webgpu/utils/WebGPUTextureUtils.js b/src/renderers/webgpu/utils/WebGPUTextureUtils.js index 629cde6dfd0158..86a5a86edf9d3d 100644 --- a/src/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -1078,7 +1078,7 @@ class WebGPUTextureUtils { let dimension; - if ( texture.isData3DTexture ) { + if ( texture.is3DTexture || texture.isData3DTexture ) { dimension = GPUTextureDimension.ThreeD;