From 6a5d6de348e8b3a252e8bd585853558be97371f2 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 26 Sep 2023 16:13:03 -0300 Subject: [PATCH] StorageTexture: Adds support for other formats. (#26842) * TimeNode: Define `frameId` as integer * Renderer: Set `info` as public * StorageTexture: Adds support for other formats. * Update example to `temporal blur` * fix device in getFormat() --- examples/jsm/nodes/utils/TimerNode.js | 2 +- examples/jsm/renderers/common/Renderer.js | 21 +- .../renderers/webgpu/nodes/WGSLNodeBuilder.js | 7 +- .../webgpu/utils/WebGPUTextureUtils.js | 304 +++++++++--------- examples/webgpu_compute_texture_pingpong.html | 64 +++- 5 files changed, 219 insertions(+), 179 deletions(-) diff --git a/examples/jsm/nodes/utils/TimerNode.js b/examples/jsm/nodes/utils/TimerNode.js index 7870f389f4afa6..608ebb3d0351b4 100644 --- a/examples/jsm/nodes/utils/TimerNode.js +++ b/examples/jsm/nodes/utils/TimerNode.js @@ -89,6 +89,6 @@ export default TimerNode; export const timerLocal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.LOCAL, timeScale, value ) ); export const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.GLOBAL, timeScale, value ) ); export const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) ); -export const frameId = nodeImmutable( TimerNode, TimerNode.FRAME ); +export const frameId = nodeImmutable( TimerNode, TimerNode.FRAME ).uint(); addNodeClass( TimerNode ); diff --git a/examples/jsm/renderers/common/Renderer.js b/examples/jsm/renderers/common/Renderer.js index 50df1a7bbfa408..f469ef80f96b43 100644 --- a/examples/jsm/renderers/common/Renderer.js +++ b/examples/jsm/renderers/common/Renderer.js @@ -46,6 +46,8 @@ class Renderer { this.depth = true; this.stencil = true; + this.info = new Info(); + // internals this._pixelRatio = 1; @@ -56,7 +58,6 @@ class Renderer { this._scissor = new Vector4( 0, 0, this._width, this._height ); this._scissorTest = false; - this._info = null; this._properties = null; this._attributes = null; this._geometries = null; @@ -131,15 +132,14 @@ class Renderer { } - this._info = new Info(); this._nodes = new Nodes( this, backend ); this._attributes = new Attributes( backend ); this._background = new Background( this, this._nodes ); - this._geometries = new Geometries( this._attributes, this._info ); - this._textures = new Textures( backend, this._info ); + this._geometries = new Geometries( this._attributes, this.info ); + this._textures = new Textures( backend, this.info ); this._pipelines = new Pipelines( backend, this._nodes ); - this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this._info ); - this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this._info ); + this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info ); + this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info ); this._renderLists = new RenderLists(); this._renderContexts = new RenderContexts(); @@ -214,9 +214,9 @@ class Renderer { if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); - if ( this._info.autoReset === true ) this._info.reset(); + if ( this.info.autoReset === true ) this.info.reset(); - this._info.render.frame ++; + this.info.render.frame ++; // @@ -612,12 +612,13 @@ class Renderer { dispose() { + this.info.dispose(); + this._objects.dispose(); this._properties.dispose(); this._pipelines.dispose(); this._nodes.dispose(); this._bindings.dispose(); - this._info.dispose(); this._renderLists.dispose(); this._renderContexts.dispose(); this._textures.dispose(); @@ -921,7 +922,7 @@ class Renderer { // - this.backend.draw( renderObject, this._info ); + this.backend.draw( renderObject, this.info ); } diff --git a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js index 8aaafba0ba50fe..eb87a0e817738b 100644 --- a/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -11,6 +11,8 @@ import { getVectorLength, getStrideLength } from '../../common/BufferUtils.js'; import { NodeBuilder, CodeNode, NodeMaterial } from '../../../nodes/Nodes.js'; +import { getFormat } from '../utils/WebGPUTextureUtils.js'; + import WGSLNodeParser from './WGSLNodeParser.js'; const gpuShaderStageLib = { @@ -659,8 +661,9 @@ class WGSLNodeBuilder extends NodeBuilder { } else if ( uniform.node.isStoreTextureNode === true ) { - // @TODO: Add support for other formats - textureType = 'texture_storage_2d'; + const format = getFormat( texture ); + + textureType = 'texture_storage_2d<' + format + ', write>'; } else { diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js index 5af43e9b31c91d..15bd079c7a9406 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -106,7 +106,7 @@ class WebGPUTextureUtils { const { width, height, depth, levels } = options; const dimension = this._getDimension( texture ); - const format = texture.internalFormat || this._getFormat( texture ); + const format = texture.internalFormat || getFormat( texture, this.device ); const sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1; const primarySampleCount = texture.isRenderTargetTexture ? 1 : sampleCount; @@ -649,237 +649,237 @@ class WebGPUTextureUtils { } - _getFormat( texture ) { +} - const format = texture.format; - const type = texture.type; - const colorSpace = texture.colorSpace; +export function getFormat( texture, device = null ) { - let formatGPU; + const format = texture.format; + const type = texture.type; + const colorSpace = texture.colorSpace; - if ( /*texture.isRenderTargetTexture === true ||*/ texture.isFramebufferTexture === true ) { + let formatGPU; - formatGPU = GPUTextureFormat.BGRA8Unorm; + if ( /*texture.isRenderTargetTexture === true ||*/ texture.isFramebufferTexture === true ) { - } else if ( texture.isCompressedTexture === true ) { + formatGPU = GPUTextureFormat.BGRA8Unorm; - switch ( format ) { + } else if ( texture.isCompressedTexture === true ) { - case RGBA_S3TC_DXT1_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm; - break; + switch ( format ) { - case RGBA_S3TC_DXT3_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm; - break; + case RGBA_S3TC_DXT1_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm; + break; - case RGBA_S3TC_DXT5_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm; - break; + case RGBA_S3TC_DXT3_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm; + break; - case RGB_ETC2_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm; - break; + case RGBA_S3TC_DXT5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm; + break; - case RGBA_ETC2_EAC_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm; - break; + case RGB_ETC2_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm; + break; - case RGBA_ASTC_4x4_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm; - break; + case RGBA_ETC2_EAC_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm; + break; - case RGBA_ASTC_5x4_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm; - break; + case RGBA_ASTC_4x4_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm; + break; - case RGBA_ASTC_5x5_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm; - break; + case RGBA_ASTC_5x4_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm; + break; - case RGBA_ASTC_6x5_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm; - break; + case RGBA_ASTC_5x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm; + break; - case RGBA_ASTC_6x6_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm; - break; + case RGBA_ASTC_6x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm; + break; - case RGBA_ASTC_8x5_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm; - break; + case RGBA_ASTC_6x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm; + break; - case RGBA_ASTC_8x6_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm; - break; + case RGBA_ASTC_8x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm; + break; - case RGBA_ASTC_8x8_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm; - break; + case RGBA_ASTC_8x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm; + break; - case RGBA_ASTC_10x5_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm; - break; + case RGBA_ASTC_8x8_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm; + break; - case RGBA_ASTC_10x6_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm; - break; + case RGBA_ASTC_10x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm; + break; - case RGBA_ASTC_10x8_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm; - break; + case RGBA_ASTC_10x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm; + break; - case RGBA_ASTC_10x10_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm; - break; + case RGBA_ASTC_10x8_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm; + break; - case RGBA_ASTC_12x10_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm; - break; + case RGBA_ASTC_10x10_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm; + break; - case RGBA_ASTC_12x12_Format: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm; - break; + case RGBA_ASTC_12x10_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm; + break; - default: - console.error( 'WebGPURenderer: Unsupported texture format.', format ); + case RGBA_ASTC_12x12_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm; + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture format.', format ); - } else { + } - switch ( format ) { + } else { - case RGBAFormat: + switch ( format ) { - switch ( type ) { + case RGBAFormat: - case UnsignedByteType: - formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm; - break; + switch ( type ) { - case HalfFloatType: - formatGPU = GPUTextureFormat.RGBA16Float; - break; + case UnsignedByteType: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm; + break; - case FloatType: - formatGPU = GPUTextureFormat.RGBA32Float; - break; + case HalfFloatType: + formatGPU = GPUTextureFormat.RGBA16Float; + break; - default: - console.error( 'WebGPURenderer: Unsupported texture type with RGBAFormat.', type ); + case FloatType: + formatGPU = GPUTextureFormat.RGBA32Float; + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGBAFormat.', type ); - break; + } - case RedFormat: + break; - switch ( type ) { + case RedFormat: - case UnsignedByteType: - formatGPU = GPUTextureFormat.R8Unorm; - break; + switch ( type ) { - case HalfFloatType: - formatGPU = GPUTextureFormat.R16Float; - break; + case UnsignedByteType: + formatGPU = GPUTextureFormat.R8Unorm; + break; - case FloatType: - formatGPU = GPUTextureFormat.R32Float; - break; + case HalfFloatType: + formatGPU = GPUTextureFormat.R16Float; + break; - default: - console.error( 'WebGPURenderer: Unsupported texture type with RedFormat.', type ); + case FloatType: + formatGPU = GPUTextureFormat.R32Float; + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture type with RedFormat.', type ); - break; + } - case RGFormat: + break; - switch ( type ) { + case RGFormat: - case UnsignedByteType: - formatGPU = GPUTextureFormat.RG8Unorm; - break; + switch ( type ) { - case HalfFloatType: - formatGPU = GPUTextureFormat.RG16Float; - break; + case UnsignedByteType: + formatGPU = GPUTextureFormat.RG8Unorm; + break; - case FloatType: - formatGPU = GPUTextureFormat.RG32Float; - break; + case HalfFloatType: + formatGPU = GPUTextureFormat.RG16Float; + break; - default: - console.error( 'WebGPURenderer: Unsupported texture type with RGFormat.', type ); + case FloatType: + formatGPU = GPUTextureFormat.RG32Float; + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGFormat.', type ); - break; + } - case DepthFormat: + break; - switch ( type ) { + case DepthFormat: - case UnsignedShortType: - formatGPU = GPUTextureFormat.Depth16Unorm; - break; + switch ( type ) { - case UnsignedIntType: - formatGPU = GPUTextureFormat.Depth24Plus; - break; + case UnsignedShortType: + formatGPU = GPUTextureFormat.Depth16Unorm; + break; - case FloatType: - formatGPU = GPUTextureFormat.Depth32Float; - break; + case UnsignedIntType: + formatGPU = GPUTextureFormat.Depth24Plus; + break; - default: - console.error( 'WebGPURenderer: Unsupported texture type with DepthFormat.', type ); + case FloatType: + formatGPU = GPUTextureFormat.Depth32Float; + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture type with DepthFormat.', type ); - break; + } - case DepthStencilFormat: + break; - switch ( type ) { + case DepthStencilFormat: - case UnsignedInt248Type: - formatGPU = GPUTextureFormat.Depth24PlusStencil8; - break; + switch ( type ) { - case FloatType: + case UnsignedInt248Type: + formatGPU = GPUTextureFormat.Depth24PlusStencil8; + break; - if ( this.device.features.has( GPUFeatureName.Depth32FloatStencil8 ) === false ) { + case FloatType: - console.error( 'WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.' ); + if ( device && device.features.has( GPUFeatureName.Depth32FloatStencil8 ) === false ) { - } + console.error( 'WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.' ); - formatGPU = GPUTextureFormat.Depth32FloatStencil8; + } - break; + formatGPU = GPUTextureFormat.Depth32FloatStencil8; - default: - console.error( 'WebGPURenderer: Unsupported texture type with DepthStencilFormat.', type ); + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture type with DepthStencilFormat.', type ); - break; + } - default: - console.error( 'WebGPURenderer: Unsupported texture format.', format ); + break; - } + default: + console.error( 'WebGPURenderer: Unsupported texture format.', format ); } - return formatGPU; - } + return formatGPU; + } export default WebGPUTextureUtils; diff --git a/examples/webgpu_compute_texture_pingpong.html b/examples/webgpu_compute_texture_pingpong.html index a54e188b70dc92..07b88fc008d451 100644 --- a/examples/webgpu_compute_texture_pingpong.html +++ b/examples/webgpu_compute_texture_pingpong.html @@ -25,17 +25,18 @@