Skip to content

Commit d9eec4f

Browse files
authored
WebGPURenderer: Skip resolving anti-aliasing twice (mrdoob#31743)
* improve antialiasing performance - wip * cleanup * cleanup * cleanup * Update PassNode.js * add js-docs * cleanup * more js-doc * Update WebGLState.js
1 parent 3e8df0a commit d9eec4f

File tree

11 files changed

+127
-43
lines changed

11 files changed

+127
-43
lines changed

src/materials/nodes/Line2NodeMaterial.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ class Line2NodeMaterial extends NodeMaterial {
378378

379379
if ( ! useDash ) {
380380

381-
if ( useAlphaToCoverage && renderer.samples > 1 ) {
381+
if ( useAlphaToCoverage && renderer.currentSamples > 0 ) {
382382

383383
const dnorm = norm.fwidth();
384384
alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() );
@@ -395,7 +395,7 @@ class Line2NodeMaterial extends NodeMaterial {
395395

396396
// round endcaps
397397

398-
if ( useAlphaToCoverage && renderer.samples > 1 ) {
398+
if ( useAlphaToCoverage && renderer.currentSamples > 0 ) {
399399

400400
const a = vUv.x;
401401
const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) );

src/materials/nodes/NodeMaterial.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ class NodeMaterial extends Material {
590590

591591
if ( unionPlanes.length > 0 || intersectionPlanes.length > 0 ) {
592592

593-
const samples = builder.renderer.samples;
593+
const samples = builder.renderer.currentSamples;
594594

595595
if ( this.alphaToCoverage && samples > 1 ) {
596596

src/nodes/shapes/Shapes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const shapeCircle = Fn( ( [ coord = uv() ], { renderer, material } ) => {
1616

1717
let alpha;
1818

19-
if ( material.alphaToCoverage && renderer.samples > 1 ) {
19+
if ( material.alphaToCoverage && renderer.currentSamples > 0 ) {
2020

2121
const dlen = float( len2.fwidth() ).toVar();
2222

src/renderers/common/Renderer.js

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ class Renderer {
118118
/**
119119
* The number of MSAA samples.
120120
*
121+
* @private
121122
* @type {number}
122123
* @default 0
123124
*/
124-
this.samples = samples || ( antialias === true ) ? 4 : 0;
125+
this._samples = samples || ( antialias === true ) ? 4 : 0;
125126

126127
/**
127128
* Whether the renderer should automatically clear the current rendering target
@@ -2229,6 +2230,59 @@ class Renderer {
22292230

22302231
}
22312232

2233+
/**
2234+
* Returns `true` if a framebuffer target is needed to perform tone mapping or color space conversion.
2235+
* If this is the case, the renderer allocates an internal render target for that purpose.
2236+
*
2237+
*/
2238+
get needsFrameBufferTarget() {
2239+
2240+
const useToneMapping = this.currentToneMapping !== NoToneMapping;
2241+
const useColorSpace = this.currentColorSpace !== ColorManagement.workingColorSpace;
2242+
2243+
return useToneMapping || useColorSpace;
2244+
2245+
}
2246+
2247+
/**
2248+
* The number of samples used for multi-sample anti-aliasing (MSAA).
2249+
*
2250+
* @type {number}
2251+
* @default 0
2252+
*/
2253+
get samples() {
2254+
2255+
return this._samples;
2256+
2257+
}
2258+
2259+
/**
2260+
* The current number of samples used for multi-sample anti-aliasing (MSAA).
2261+
*
2262+
* When rendering to a custom render target, the number of samples of that render target is used.
2263+
* If the renderer needs an internal framebuffer target for tone mapping or color space conversion,
2264+
* the number of samples is set to 0.
2265+
*
2266+
* @type {number}
2267+
*/
2268+
get currentSamples() {
2269+
2270+
let samples = this._samples;
2271+
2272+
if ( this._renderTarget !== null ) {
2273+
2274+
samples = this._renderTarget.samples;
2275+
2276+
} else if ( this.needsFrameBufferTarget ) {
2277+
2278+
samples = 0;
2279+
2280+
}
2281+
2282+
return samples;
2283+
2284+
}
2285+
22322286
/**
22332287
* The current tone mapping of the renderer. When not producing screen output,
22342288
* the tone mapping is always `NoToneMapping`.

src/renderers/common/Textures.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class Textures extends DataMap {
8585
depthTexture.image.width = mipWidth;
8686
depthTexture.image.height = mipHeight;
8787
depthTexture.image.depth = size.depth;
88+
depthTexture.renderTarget = renderTarget;
8889
depthTexture.isArrayTexture = renderTarget.multiview === true && size.depth > 1;
8990

9091
depthTextureMips[ activeMipmapLevel ] = depthTexture;

src/renderers/common/XRManager.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ class XRManager extends EventDispatcher {
10411041
// fallback to XRWebGLLayer
10421042

10431043
const layerInit = {
1044-
antialias: renderer.samples > 0,
1044+
antialias: renderer.currentSamples > 0,
10451045
alpha: true,
10461046
depth: renderer.depth,
10471047
stencil: renderer.stencil,

src/renderers/webgl-fallback/WebGLBackend.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class WebGLBackend extends Backend {
219219
const parameters = this.parameters;
220220

221221
const contextAttributes = {
222-
antialias: renderer.samples > 0,
222+
antialias: renderer.currentSamples > 0,
223223
alpha: true, // always true for performance reasons
224224
depth: renderer.depth,
225225
stencil: renderer.stencil

src/renderers/webgl-fallback/utils/WebGLState.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ class WebGLState {
755755

756756
this.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
757757

758-
material.alphaToCoverage === true && this.backend.renderer.samples > 1
758+
material.alphaToCoverage === true && this.backend.renderer.currentSamples > 0
759759
? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
760760
: this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
761761

src/renderers/webgpu/WebGPUBackend.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,6 @@ class WebGPUBackend extends Backend {
9292
*/
9393
this.context = null;
9494

95-
/**
96-
* A reference to the color attachment of the default framebuffer.
97-
*
98-
* @type {?GPUTexture}
99-
* @default null
100-
*/
101-
this.colorBuffer = null;
102-
10395
/**
10496
* A reference to the default render pass descriptor.
10597
*
@@ -328,9 +320,9 @@ class WebGPUBackend extends Backend {
328320

329321
const colorAttachment = descriptor.colorAttachments[ 0 ];
330322

331-
if ( this.renderer.samples > 0 ) {
323+
if ( this.renderer.currentSamples > 0 ) {
332324

333-
colorAttachment.view = this.colorBuffer.createView();
325+
colorAttachment.view = this.textureUtils.getColorBuffer().createView();
334326

335327
} else {
336328

@@ -344,7 +336,7 @@ class WebGPUBackend extends Backend {
344336

345337
const colorAttachment = descriptor.colorAttachments[ 0 ];
346338

347-
if ( this.renderer.samples > 0 ) {
339+
if ( this.renderer.currentSamples > 0 ) {
348340

349341
colorAttachment.resolveTarget = this.context.getCurrentTexture().createView();
350342

@@ -2193,7 +2185,6 @@ class WebGPUBackend extends Backend {
21932185
*/
21942186
updateSize() {
21952187

2196-
this.colorBuffer = this.textureUtils.getColorBuffer();
21972188
this.defaultRenderPassdescriptor = null;
21982189

21992190
}

src/renderers/webgpu/utils/WebGPUTextureUtils.js

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,22 @@ class WebGPUTextureUtils {
8787
*/
8888
this.defaultVideoFrame = null;
8989

90-
/**
91-
* Represents the color attachment of the default framebuffer.
92-
*
93-
* @type {?GPUTexture}
94-
* @default null
95-
*/
96-
this.colorBuffer = null;
97-
98-
/**
99-
* Represents the depth attachment of the default framebuffer.
100-
*
101-
* @type {DepthTexture}
102-
*/
103-
this.depthTexture = new DepthTexture();
104-
this.depthTexture.name = 'depthBuffer';
90+
this.frameBufferData = {
91+
color: {
92+
buffer: null, // TODO: Move to FramebufferTexture
93+
width: 0,
94+
height: 0,
95+
samples: 0
96+
},
97+
depth: {
98+
texture: new DepthTexture(),
99+
width: 0,
100+
height: 0,
101+
samples: 0,
102+
depth: false,
103+
stencil: false
104+
}
105+
};
105106

106107
/**
107108
* A cache of shared texture samplers.
@@ -396,24 +397,44 @@ class WebGPUTextureUtils {
396397
*/
397398
getColorBuffer() {
398399

399-
if ( this.colorBuffer ) this.colorBuffer.destroy();
400-
401400
const backend = this.backend;
402401
const { width, height } = backend.getDrawingBufferSize();
402+
const samples = backend.renderer.currentSamples;
403403

404-
this.colorBuffer = backend.device.createTexture( {
404+
const frameBufferColor = this.frameBufferData.color;
405+
406+
if ( frameBufferColor.width === width && frameBufferColor.height === height && frameBufferColor.samples === samples ) {
407+
408+
return frameBufferColor.buffer;
409+
410+
}
411+
412+
// recreate
413+
414+
let colorBuffer = frameBufferColor.buffer;
415+
416+
if ( colorBuffer ) colorBuffer.destroy();
417+
418+
colorBuffer = backend.device.createTexture( {
405419
label: 'colorBuffer',
406420
size: {
407421
width: width,
408422
height: height,
409423
depthOrArrayLayers: 1
410424
},
411-
sampleCount: backend.utils.getSampleCount( backend.renderer.samples ),
425+
sampleCount: backend.utils.getSampleCount( backend.renderer.currentSamples ),
412426
format: backend.utils.getPreferredCanvasFormat(),
413427
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
414428
} );
415429

416-
return this.colorBuffer;
430+
//
431+
432+
frameBufferColor.buffer = colorBuffer;
433+
frameBufferColor.width = width;
434+
frameBufferColor.height = height;
435+
frameBufferColor.samples = samples;
436+
437+
return colorBuffer;
417438

418439
}
419440

@@ -429,8 +450,23 @@ class WebGPUTextureUtils {
429450

430451
const backend = this.backend;
431452
const { width, height } = backend.getDrawingBufferSize();
453+
const samples = backend.renderer.currentSamples;
454+
455+
const frameBufferDepth = this.frameBufferData.depth;
456+
const depthTexture = frameBufferDepth.texture;
457+
458+
if ( depthTexture.width === width &&
459+
depthTexture.height === height &&
460+
depthTexture.samples === samples &&
461+
depthTexture.depth === depth &&
462+
depthTexture.stencil === stencil ) {
463+
464+
return backend.get( depthTexture ).texture;
465+
466+
}
467+
468+
//
432469

433-
const depthTexture = this.depthTexture;
434470
const depthTextureGPU = backend.get( depthTexture ).texture;
435471

436472
let format, type;
@@ -459,6 +495,8 @@ class WebGPUTextureUtils {
459495

460496
}
461497

498+
// recreate
499+
462500
depthTexture.name = 'depthBuffer';
463501
depthTexture.format = format;
464502
depthTexture.type = type;

0 commit comments

Comments
 (0)