diff --git a/examples/jsm/nodes/Nodes.js b/examples/jsm/nodes/Nodes.js index cfccddbea2c181..6243d695de0c5d 100644 --- a/examples/jsm/nodes/Nodes.js +++ b/examples/jsm/nodes/Nodes.js @@ -103,7 +103,7 @@ export { default as SceneNode, backgroundBlurriness, backgroundIntensity } from export { default as StorageBufferNode, storage, storageObject } from './accessors/StorageBufferNode.js'; export * from './accessors/TangentNode.js'; export { default as TextureNode, texture, textureLoad, /*textureLevel,*/ sampler } from './accessors/TextureNode.js'; -export { default as StorageTextureNode, storageTexture, textureStore, storageTextureReadOnly, storageTextureReadWrite } from './accessors/StorageTextureNode.js'; +export { default as StorageTextureNode, storageTexture, textureStore } from './accessors/StorageTextureNode.js'; export { default as Texture3DNode, texture3D } from './accessors/Texture3DNode.js'; export * from './accessors/UVNode.js'; export { default as UserDataNode, userData } from './accessors/UserDataNode.js'; diff --git a/examples/jsm/nodes/accessors/StorageBufferNode.js b/examples/jsm/nodes/accessors/StorageBufferNode.js index 855f051c6635d7..19627829517b3c 100644 --- a/examples/jsm/nodes/accessors/StorageBufferNode.js +++ b/examples/jsm/nodes/accessors/StorageBufferNode.js @@ -4,6 +4,7 @@ import { addNodeClass } from '../core/Node.js'; import { nodeObject } from '../shadernode/ShaderNode.js'; import { varying } from '../core/VaryingNode.js'; import { storageElement } from '../utils/StorageArrayElementNode.js'; +import { GPUBufferBindingType } from '../../renderers/webgpu/utils/WebGPUConstants.js'; class StorageBufferNode extends BufferNode { @@ -13,6 +14,8 @@ class StorageBufferNode extends BufferNode { this.isStorageBufferNode = true; + this.access = GPUBufferBindingType.Storage; + this.bufferObject = false; this.bufferCount = bufferCount; @@ -76,9 +79,27 @@ class StorageBufferNode extends BufferNode { } + setAccess( value ) { + + this.access = value; + + return this; + + } + + toReadOnly() { + + return this.setAccess( GPUBufferBindingType.ReadOnlyStorage ); + + } + generate( builder ) { - if ( builder.isAvailable( 'storageBuffer' ) ) return super.generate( builder ); + if ( builder.isAvailable( 'storageBuffer' ) ) { + + return super.generate( builder ); + + } const nodeType = this.getNodeType( builder ); @@ -102,6 +123,7 @@ class StorageBufferNode extends BufferNode { export default StorageBufferNode; +// Read-Write Storage export const storage = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ) ); export const storageObject = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ).setBufferObject( true ) ); diff --git a/examples/jsm/nodes/accessors/StorageTextureNode.js b/examples/jsm/nodes/accessors/StorageTextureNode.js index 6e9f97f0051d06..fbaa982456da0a 100644 --- a/examples/jsm/nodes/accessors/StorageTextureNode.js +++ b/examples/jsm/nodes/accessors/StorageTextureNode.js @@ -57,6 +57,18 @@ class StorageTextureNode extends TextureNode { } + toReadOnly() { + + return this.setAccess( GPUStorageTextureAccess.ReadOnly ); + + } + + toWriteOnly() { + + return this.setAccess( GPUStorageTextureAccess.WriteOnly ); + + } + generateStore( builder ) { const properties = builder.getNodeProperties( this ); @@ -79,9 +91,6 @@ export default StorageTextureNode; export const storageTexture = nodeProxy( StorageTextureNode ); -export const storageTextureReadOnly = ( value, uvNode, storeNode ) => storageTexture( value, uvNode, storeNode ).setAccess( 'read-only' ); -export const storageTextureReadWrite = ( value, uvNode, storeNode ) => storageTexture( value, uvNode, storeNode ).setAccess( 'read-write' ); - export const textureStore = ( value, uvNode, storeNode ) => { const node = storageTexture( value, uvNode, storeNode ); diff --git a/examples/jsm/renderers/common/Renderer.js b/examples/jsm/renderers/common/Renderer.js index 2da84821d7163e..1cc18a4c2d6769 100644 --- a/examples/jsm/renderers/common/Renderer.js +++ b/examples/jsm/renderers/common/Renderer.js @@ -1089,6 +1089,7 @@ class Renderer { const pipelines = this._pipelines; const bindings = this._bindings; const nodes = this._nodes; + const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ]; if ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) { diff --git a/examples/jsm/renderers/common/nodes/NodeStorageBuffer.js b/examples/jsm/renderers/common/nodes/NodeStorageBuffer.js index 67a436f729d0e0..8e5ae85ee5f63b 100644 --- a/examples/jsm/renderers/common/nodes/NodeStorageBuffer.js +++ b/examples/jsm/renderers/common/nodes/NodeStorageBuffer.js @@ -1,4 +1,5 @@ import StorageBuffer from '../StorageBuffer.js'; +import { GPUBufferBindingType } from '../../webgpu/utils/WebGPUConstants.js'; let _id = 0; @@ -9,8 +10,10 @@ class NodeStorageBuffer extends StorageBuffer { super( 'StorageBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); this.nodeUniform = nodeUniform; + this.access = nodeUniform ? nodeUniform.access : GPUBufferBindingType.Storage this.groupNode = groupNode; + } get buffer() { diff --git a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js index d649c66f20b112..e67f588923d9e8 100644 --- a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -13,8 +13,7 @@ import { NodeBuilder, CodeNode } from '../../../nodes/Nodes.js'; import { getFormat } from '../utils/WebGPUTextureUtils.js'; import WGSLNodeParser from './WGSLNodeParser.js'; -import { GPUStorageTextureAccess } from '../utils/WebGPUConstants.js'; - +import { GPUBufferBindingType, GPUStorageTextureAccess } from '../utils/WebGPUConstants.js'; // GPUShaderStage is not defined in browsers not supporting WebGPU const GPUShaderStage = self.GPUShaderStage; @@ -26,6 +25,7 @@ const gpuShaderStageLib = { }; const supports = { + instance: true, swizzleAssign: false, storageBuffer: true }; @@ -411,30 +411,38 @@ class WGSLNodeBuilder extends NodeBuilder { switch ( node.access ) { - case GPUStorageTextureAccess.ReadOnly: { + case GPUStorageTextureAccess.ReadOnly: return 'read'; - } - - case GPUStorageTextureAccess.WriteOnly: { + case GPUStorageTextureAccess.WriteOnly: return 'write'; - } - - default: { + default: return 'read_write'; - } - } } else { - // @TODO: Account for future read-only storage buffer pull request - return 'read_write'; + switch ( node.access ) { + + case GPUBufferBindingType.Storage: + + return 'read_write'; + + + case GPUBufferBindingType.ReadOnlyStorage: + + return 'read'; + + default: + + return 'write'; + + } } @@ -714,6 +722,7 @@ ${ flowData.code } snippet += this.getStructMembers( struct ); snippet += '\n}'; + snippets.push( snippet ); snippets.push( `\nvar<private> output : ${ name };\n\n` ); @@ -880,7 +889,7 @@ ${ flowData.code } const bufferCountSnippet = bufferCount > 0 ? ', ' + bufferCount : ''; const bufferSnippet = `\t${ uniform.name } : array< ${ bufferType }${ bufferCountSnippet } >\n`; - const bufferAccessMode = bufferNode.isStorageBufferNode ? 'storage,read_write' : 'uniform'; + const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode ) }` : 'uniform'; bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, uniformIndexes.binding ++, uniformIndexes.group ) ); @@ -997,6 +1006,7 @@ ${ flowData.code } stageData.flow = flow; + } if ( this.material !== null ) { diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js index 13230bc645991a..a7b7c62220bf77 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js @@ -1,5 +1,5 @@ import { - GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType, GPUTextureSampleType + GPUTextureAspect, GPUTextureViewDimension, GPUTextureSampleType } from './WebGPUConstants.js'; import { FloatType, IntType, UnsignedIntType } from 'three'; @@ -33,7 +33,7 @@ class WebGPUBindingUtils { if ( binding.isStorageBuffer ) { - buffer.type = GPUBufferBindingType.Storage; + buffer.type = binding.access; } diff --git a/examples/webgpu_compute_audio.html b/examples/webgpu_compute_audio.html index 18f6915fb61428..06f9ea1a883b06 100644 --- a/examples/webgpu_compute_audio.html +++ b/examples/webgpu_compute_audio.html @@ -29,7 +29,7 @@ <script type="module"> import * as THREE from 'three'; - import { tslFn, uniform, storage, storageObject, instanceIndex, float, texture, viewportTopLeft, color } from 'three/nodes'; + import { tslFn, uniform, storage, instanceIndex, float, texture, viewportTopLeft, color } from 'three/nodes'; import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; @@ -112,11 +112,9 @@ const waveStorageNode = storage( waveGPUBuffer, 'float', waveBuffer.length ); - // read-only buffer - const waveNode = storageObject( new StorageInstancedBufferAttribute( waveBuffer, 1 ), 'float', waveBuffer.length ); - + const waveNode = storage( new StorageInstancedBufferAttribute( waveBuffer, 1 ), 'float', waveBuffer.length ).toReadOnly(); // params diff --git a/examples/webgpu_compute_geometry.html b/examples/webgpu_compute_geometry.html index 45267483aebdb7..41a7d31c117e7e 100644 --- a/examples/webgpu_compute_geometry.html +++ b/examples/webgpu_compute_geometry.html @@ -72,8 +72,8 @@ const computeFn = tslFn( () => { - const positionAttribute = storage( positionBaseAttribute, 'vec3', positionBaseAttribute.count ); - const normalAttribute = storage( normalBaseAttribute, 'vec3', normalBaseAttribute.count ); + const positionAttribute = storage( positionBaseAttribute, 'vec3', positionBaseAttribute.count ).toReadOnly(); + const normalAttribute = storage( normalBaseAttribute, 'vec3', normalBaseAttribute.count ).toReadOnly(); const positionStorageAttribute = storage( positionStorageBufferAttribute, 'vec4', positionStorageBufferAttribute.count ); const normalStorageAttribute = storage( normalStorageBufferAttribute, 'vec4', normalStorageBufferAttribute.count ); diff --git a/examples/webgpu_compute_texture.html b/examples/webgpu_compute_texture.html index 1b67d14f9f1f68..3a49919e73e65b 100644 --- a/examples/webgpu_compute_texture.html +++ b/examples/webgpu_compute_texture.html @@ -81,7 +81,7 @@ const g = v.add( Math.PI ).sin(); const b = v.add( Math.PI ).sub( 0.5 ).sin(); - textureStore( storageTexture, indexUV, vec4( r, g, b, 1 ) ); + textureStore( storageTexture, indexUV, vec4( r, g, b, 1 ) ).toWriteOnly(); } );