Browse Source

WebGPURenderer: Improve support int/uint textures (#27932)

sunag 1 year ago
parent
commit
e6ec29855f

+ 7 - 14
examples/jsm/nodes/core/NodeBuilder.js

@@ -15,7 +15,7 @@ import {
 	ColorNodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
 	ColorNodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
 } from '../../renderers/common/nodes/NodeUniform.js';
 } from '../../renderers/common/nodes/NodeUniform.js';
 
 
-import { REVISION, RenderTarget, NoColorSpace, Color, Vector2, Vector3, Vector4, Float16BufferAttribute } from 'three';
+import { REVISION, RenderTarget, Color, Vector2, Vector3, Vector4, IntType, UnsignedIntType, Float16BufferAttribute } from 'three';
 
 
 import { stack } from './StackNode.js';
 import { stack } from './StackNode.js';
 import { getCurrentStack, setCurrentStack } from '../shadernode/ShaderNode.js';
 import { getCurrentStack, setCurrentStack } from '../shadernode/ShaderNode.js';
@@ -484,25 +484,18 @@ class NodeBuilder {
 
 
 	}
 	}
 
 
-	getTextureColorSpaceFromMap( map ) {
+	getComponentTypeFromTexture( texture ) {
 
 
-		let colorSpace;
+		const type = texture.type;
 
 
-		if ( map && map.isTexture ) {
+		if ( texture.isDataTexture ) {
 
 
-			colorSpace = map.colorSpace;
-
-		} else if ( map && map.isWebGLRenderTarget ) {
-
-			colorSpace = map.texture.colorSpace;
-
-		} else {
-
-			colorSpace = NoColorSpace;
+			if ( type === IntType ) return 'int';
+			if ( type === UnsignedIntType ) return 'uint';
 
 
 		}
 		}
 
 
-		return colorSpace;
+		return 'float';
 
 
 	}
 	}
 
 

+ 5 - 3
examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js

@@ -228,7 +228,7 @@ class WGSLNodeBuilder extends NodeBuilder {
 
 
 	isUnfilterable( texture ) {
 	isUnfilterable( texture ) {
 
 
-		return texture.isDataTexture === true && texture.type === FloatType;
+		return this.getComponentTypeFromTexture( texture ) !== 'float' || ( texture.isDataTexture === true && texture.type === FloatType );
 
 
 	}
 	}
 
 
@@ -759,11 +759,13 @@ ${ flowData.code }
 
 
 					const format = getFormat( texture );
 					const format = getFormat( texture );
 
 
-					textureType = 'texture_storage_2d<' + format + ', write>';
+					textureType = `texture_storage_2d<${ format }, write>`;
 
 
 				} else {
 				} else {
 
 
-					textureType = 'texture_2d<f32>';
+					const componentPrefix = this.getComponentTypeFromTexture( texture ).charAt( 0 );
+
+					textureType = `texture_2d<${ componentPrefix }32>`;
 
 
 				}
 				}
 
 

+ 18 - 4
examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js

@@ -1,7 +1,7 @@
 import {
 import {
 	GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType, GPUTextureSampleType
 	GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType, GPUTextureSampleType
 } from './WebGPUConstants.js';
 } from './WebGPUConstants.js';
-import { FloatType } from 'three';
+import { FloatType, IntType, UnsignedIntType } from 'three';
 
 
 class WebGPUBindingUtils {
 class WebGPUBindingUtils {
 
 
@@ -73,11 +73,25 @@ class WebGPUBindingUtils {
 
 
 					texture.sampleType = GPUTextureSampleType.Depth;
 					texture.sampleType = GPUTextureSampleType.Depth;
 
 
-				} else if ( binding.texture.isDataTexture && binding.texture.type === FloatType ) {
+				} else if ( binding.texture.isDataTexture ) {
 
 
-					// @TODO: Add support for this soon: backend.hasFeature( 'float32-filterable' )
+					const type = binding.texture.type;
 
 
-					texture.sampleType = GPUTextureSampleType.UnfilterableFloat;
+					if ( type === IntType ) {
+
+						texture.sampleType = GPUTextureSampleType.SInt;
+
+					} else if ( type === UnsignedIntType ) {
+
+						texture.sampleType = GPUTextureSampleType.UInt;
+
+					} else if ( type === FloatType ) {
+
+						// @TODO: Add support for this soon: backend.hasFeature( 'float32-filterable' )
+
+						texture.sampleType = GPUTextureSampleType.UnfilterableFloat;
+
+					}
 
 
 				}
 				}
 
 

+ 74 - 15
examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js

@@ -10,7 +10,7 @@ import {
 	RGBAFormat, RedFormat, RGFormat, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, UnsignedByteType, FloatType, HalfFloatType, SRGBColorSpace, DepthFormat, DepthStencilFormat,
 	RGBAFormat, RedFormat, RGFormat, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, UnsignedByteType, FloatType, HalfFloatType, SRGBColorSpace, DepthFormat, DepthStencilFormat,
 	RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format,
 	RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format,
 	RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, UnsignedIntType, UnsignedShortType, UnsignedInt248Type,
 	RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, UnsignedIntType, UnsignedShortType, UnsignedInt248Type,
-	NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare
+	NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare, IntType, RedIntegerFormat, RGIntegerFormat, RGBAIntegerFormat
 } from 'three';
 } from 'three';
 
 
 import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, DepthTexture } from 'three';
 import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping, DepthTexture } from 'three';
@@ -38,8 +38,8 @@ class WebGPUTextureUtils {
 
 
 		this._passUtils = null;
 		this._passUtils = null;
 
 
-		this.defaultTexture = null;
-		this.defaultCubeTexture = null;
+		this.defaultTexture = {};
+		this.defaultCubeTexture = {};
 
 
 		this.colorBuffer = null;
 		this.colorBuffer = null;
 
 
@@ -79,13 +79,15 @@ class WebGPUTextureUtils {
 
 
 		let textureGPU;
 		let textureGPU;
 
 
+		const format = getFormat( texture );
+
 		if ( texture.isCubeTexture ) {
 		if ( texture.isCubeTexture ) {
 
 
-			textureGPU = this._getDefaultCubeTextureGPU();
+			textureGPU = this._getDefaultCubeTextureGPU( format );
 
 
 		} else {
 		} else {
 
 
-			textureGPU = this._getDefaultTextureGPU();
+			textureGPU = this._getDefaultTextureGPU( format );
 
 
 		}
 		}
 
 
@@ -111,7 +113,7 @@ class WebGPUTextureUtils {
 		const { width, height, depth, levels } = options;
 		const { width, height, depth, levels } = options;
 
 
 		const dimension = this._getDimension( texture );
 		const dimension = this._getDimension( texture );
-		const format = texture.internalFormat || getFormat( texture, backend.device );
+		const format = texture.internalFormat || options.format || getFormat( texture, backend.device );
 
 
 		let sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1;
 		let sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1;
 
 
@@ -422,19 +424,19 @@ class WebGPUTextureUtils {
 
 
 	}
 	}
 
 
-	_getDefaultTextureGPU() {
+	_getDefaultTextureGPU( format ) {
 
 
-		let defaultTexture = this.defaultTexture;
+		let defaultTexture = this.defaultTexture[ format ];
 
 
-		if ( defaultTexture === null ) {
+		if ( defaultTexture === undefined ) {
 
 
 			const texture = new Texture();
 			const texture = new Texture();
 			texture.minFilter = NearestFilter;
 			texture.minFilter = NearestFilter;
 			texture.magFilter = NearestFilter;
 			texture.magFilter = NearestFilter;
 
 
-			this.createTexture( texture, { width: 1, height: 1 } );
+			this.createTexture( texture, { width: 1, height: 1, format } );
 
 
-			this.defaultTexture = defaultTexture = texture;
+			this.defaultTexture[ format ] = defaultTexture = texture;
 
 
 		}
 		}
 
 
@@ -442,11 +444,11 @@ class WebGPUTextureUtils {
 
 
 	}
 	}
 
 
-	_getDefaultCubeTextureGPU() {
+	_getDefaultCubeTextureGPU( format ) {
 
 
-		let defaultCubeTexture = this.defaultTexture;
+		let defaultCubeTexture = this.defaultTexture[ format ];
 
 
-		if ( defaultCubeTexture === null ) {
+		if ( defaultCubeTexture === undefined ) {
 
 
 			const texture = new CubeTexture();
 			const texture = new CubeTexture();
 			texture.minFilter = NearestFilter;
 			texture.minFilter = NearestFilter;
@@ -454,7 +456,7 @@ class WebGPUTextureUtils {
 
 
 			this.createTexture( texture, { width: 1, height: 1, depth: 6 } );
 			this.createTexture( texture, { width: 1, height: 1, depth: 6 } );
 
 
-			this.defaultCubeTexture = defaultCubeTexture = texture;
+			this.defaultCubeTexture[ format ] = defaultCubeTexture = texture;
 
 
 		}
 		}
 
 
@@ -1026,6 +1028,63 @@ export function getFormat( texture, device = null ) {
 
 
 				break;
 				break;
 
 
+			case RedIntegerFormat:
+
+				switch ( type ) {
+
+					case IntType:
+						formatGPU = GPUTextureFormat.R32Sint;
+						break;
+
+					case UnsignedIntType:
+						formatGPU = GPUTextureFormat.R32Uint;
+						break;
+
+					default:
+						console.error( 'WebGPURenderer: Unsupported texture type with RedIntegerFormat.', type );
+
+				}
+
+				break;
+
+			case RGIntegerFormat:
+
+				switch ( type ) {
+
+					case IntType:
+						formatGPU = GPUTextureFormat.RG32Sint;
+						break;
+
+					case UnsignedIntType:
+						formatGPU = GPUTextureFormat.RG32Uint;
+						break;
+
+					default:
+						console.error( 'WebGPURenderer: Unsupported texture type with RGIntegerFormat.', type );
+
+				}
+
+				break;
+
+			case RGBAIntegerFormat:
+
+				switch ( type ) {
+
+					case IntType:
+						formatGPU = GPUTextureFormat.RGBA32Sint;
+						break;
+
+					case UnsignedIntType:
+						formatGPU = GPUTextureFormat.RGBA32Uint;
+						break;
+
+					default:
+						console.error( 'WebGPURenderer: Unsupported texture type with RGBAIntegerFormat.', type );
+
+				}
+
+				break;
+
 			default:
 			default:
 				console.error( 'WebGPURenderer: Unsupported texture format.', format );
 				console.error( 'WebGPURenderer: Unsupported texture format.', format );