Skip to content

Commit

Permalink
WebGPURenderer: Fix filterable depth textures (#30023)
Browse files Browse the repository at this point in the history
* fix filterable depth textures

* cleanup
  • Loading branch information
sunag authored Dec 3, 2024
1 parent 93dccc1 commit ae2791a
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 18 deletions.
Binary file modified examples/screenshots/webgpu_backdrop_water.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/webgpu_backdrop_water.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@

// renderer

renderer = new THREE.WebGPURenderer( /*{ antialias: true }*/ );
renderer = new THREE.WebGPURenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
Expand Down
18 changes: 18 additions & 0 deletions src/core/RenderTarget.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class RenderTarget extends EventDispatcher {

this.textures[ i ] = texture.clone();
this.textures[ i ].isRenderTargetTexture = true;
this.textures[ i ].renderTarget = this;

}

Expand All @@ -63,6 +64,7 @@ class RenderTarget extends EventDispatcher {
this.resolveDepthBuffer = options.resolveDepthBuffer;
this.resolveStencilBuffer = options.resolveStencilBuffer;

this._depthTexture = null;
this.depthTexture = options.depthTexture;

this.samples = options.samples;
Expand All @@ -81,6 +83,21 @@ class RenderTarget extends EventDispatcher {

}

set depthTexture( current ) {

if ( this._depthTexture !== null ) this._depthTexture.renderTarget = null;
if ( current !== null ) current.renderTarget = this;

this._depthTexture = current;

}

get depthTexture() {

return this._depthTexture;

}

setSize( width, height, depth = 1 ) {

if ( this.width !== width || this.height !== height || this.depth !== depth ) {
Expand Down Expand Up @@ -129,6 +146,7 @@ class RenderTarget extends EventDispatcher {

this.textures[ i ] = source.textures[ i ].clone();
this.textures[ i ].isRenderTargetTexture = true;
this.textures[ i ].renderTarget = this;

}

Expand Down
4 changes: 0 additions & 4 deletions src/nodes/display/PassNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ class PassNode extends TempNode {
const refTexture = this.renderTarget.texture;

texture = refTexture.clone();
texture.isRenderTargetTexture = true;
texture.name = name;

this._textures[ name ] = texture;
Expand All @@ -189,7 +188,6 @@ class PassNode extends TempNode {
if ( texture === undefined ) {

texture = this.getTexture( name ).clone();
texture.isRenderTargetTexture = true;

this._previousTextures[ name ] = texture;

Expand Down Expand Up @@ -302,8 +300,6 @@ class PassNode extends TempNode {

}

this.renderTarget.depthTexture.isMultisampleRenderTargetTexture = this.renderTarget.samples > 1;

return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode();

}
Expand Down
10 changes: 7 additions & 3 deletions src/renderers/webgpu/nodes/WGSLNodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,9 @@ class WGSLNodeBuilder extends NodeBuilder {

let textureDimensionsParams;

if ( texture.isMultisampleRenderTargetTexture === true ) {
const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture );

if ( primarySamples > 1 ) {

textureDimensionsParams = textureProperty;

Expand Down Expand Up @@ -388,7 +390,7 @@ class WGSLNodeBuilder extends NodeBuilder {
return this.getComponentTypeFromTexture( texture ) !== 'float' ||
( ! this.isAvailable( 'float32Filterable' ) && texture.isDataTexture === true && texture.type === FloatType ) ||
( this.isSampleCompare( texture ) === false && texture.minFilter === NearestFilter && texture.magFilter === NearestFilter ) ||
texture.isMultisampleRenderTargetTexture === true;
this.renderer.backend.utils.getTextureSampleData( texture ).primarySamples > 1;

}

Expand Down Expand Up @@ -1120,7 +1122,9 @@ ${ flowData.code }

let multisampled = '';

if ( texture.isMultisampleRenderTargetTexture === true ) {
const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture );

if ( primarySamples > 1 ) {

multisampled = '_multisampled';

Expand Down
10 changes: 9 additions & 1 deletion src/renderers/webgpu/utils/WebGPUBindingUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,18 @@ class WebGPUBindingUtils {

const texture = {}; // GPUTextureBindingLayout

if ( binding.texture.isMultisampleRenderTargetTexture === true ) {
const { primarySamples } = backend.utils.getTextureSampleData( binding.texture );

if ( primarySamples > 1 ) {

texture.multisampled = true;

if ( ! binding.texture.isDepthTexture ) {

texture.sampleType = GPUTextureSampleType.UnfilterableFloat;

}

}

if ( binding.texture.isDepthTexture ) {
Expand Down
14 changes: 5 additions & 9 deletions src/renderers/webgpu/utils/WebGPUTextureUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,7 @@ class WebGPUTextureUtils {

textureData.format = format;

let sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1;

sampleCount = backend.utils.getSampleCount( sampleCount );

const primarySampleCount = texture.isRenderTargetTexture && ! texture.isMultisampleRenderTargetTexture ? 1 : sampleCount;
const { samples, primarySamples, isMSAA } = backend.utils.getTextureSampleData( texture );

let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;

Expand All @@ -174,7 +170,7 @@ class WebGPUTextureUtils {
depthOrArrayLayers: depth,
},
mipLevelCount: levels,
sampleCount: primarySampleCount,
sampleCount: primarySamples,
dimension: dimension,
format: format,
usage: usage
Expand Down Expand Up @@ -208,12 +204,12 @@ class WebGPUTextureUtils {

}

if ( texture.isRenderTargetTexture && sampleCount > 1 && ! texture.isMultisampleRenderTargetTexture ) {
if ( isMSAA ) {

const msaaTextureDescriptorGPU = Object.assign( {}, textureDescriptorGPU );

msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + '-msaa';
msaaTextureDescriptorGPU.sampleCount = sampleCount;
msaaTextureDescriptorGPU.sampleCount = samples;

textureData.msaaTexture = backend.device.createTexture( msaaTextureDescriptorGPU );

Expand Down Expand Up @@ -336,7 +332,7 @@ class WebGPUTextureUtils {
depthTexture.image.width = width;
depthTexture.image.height = height;

this.createTexture( depthTexture, { sampleCount: backend.utils.getSampleCount( backend.renderer.samples ), width, height } );
this.createTexture( depthTexture, { width, height } );

return backend.get( depthTexture ).texture;

Expand Down
30 changes: 30 additions & 0 deletions src/renderers/webgpu/utils/WebGPUUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@ class WebGPUUtils {

}

getTextureSampleData( texture ) {

let samples;

if ( texture.isFramebufferTexture ) {

samples = 1;

} else if ( texture.isDepthTexture && ! texture.renderTarget ) {

const renderer = this.backend.renderer;
const renderTarget = renderer.getRenderTarget();

samples = renderTarget ? renderTarget.samples : renderer.samples;

} else if ( texture.renderTarget ) {

samples = texture.renderTarget.samples;

}

samples = samples || 1;

const isMSAA = samples > 1 && texture.renderTarget !== null && ( texture.isDepthTexture !== true && texture.isFramebufferTexture !== true );
const primarySamples = isMSAA ? 1 : samples;

return { samples, primarySamples, isMSAA };

}

getCurrentColorFormat( renderContext ) {

let format;
Expand Down
4 changes: 4 additions & 0 deletions src/textures/Texture.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Texture extends EventDispatcher {
this.version = 0;
this.onUpdate = null;

this.renderTarget = null; // assign texture to a render target
this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)

Expand Down Expand Up @@ -134,6 +135,9 @@ class Texture extends EventDispatcher {
this.unpackAlignment = source.unpackAlignment;
this.colorSpace = source.colorSpace;

this.renderTarget = source.renderTarget;
this.isRenderTargetTexture = source.isRenderTargetTexture;

this.userData = JSON.parse( JSON.stringify( source.userData ) );

this.needsUpdate = true;
Expand Down

0 comments on commit ae2791a

Please sign in to comment.