[WebGPU] Occlusion query with 2 cameras

Hello,

When I use 2 cameras and the occlusion query, it works with WebGL,
but with WebGPU nothing happens.

I tried with a single camera and it works, but not with multiple cameras.

On my project I have feedback in the console which tells me: is written to twice in a render pass.

As you can see on this PG using WebGPU, nothing happens and on my project it completely crashes (but works with WebGL)

And I also notice that when the object is marked (using WebGL), it remains visible on the second camera. I don’t know if this is normal ?

Actually, occlusion queries are unsupported for multiple cameras: we can only have a single occlusion query running for a given mesh (the isOccluded property is not per-camera).

It happens that WebGL uses the first camera (but depending on GPU timings, it could be another one) and WebGPU the last one (or at least not necessarily the first one).

I created a PR to make it consistent, and all engines will now use the first camera for the occlusion query:

1 Like

Thanks Evgeni

@Evgeni_Popov The problem is still present when using a mesh with ImportMesh (WebGPU engine) nothing happens.

And in the console I notice this error which I also have on my project:

a.getContext(...).drawWindow is not a function

I have the same error on my project repeat 250 times :

Query index 49 of [QuerySet] is written to twice in a render pass.
 - While validating the occlusion query index (49) in [QuerySet]
 - While encoding [RenderPassEncoder].BeginOcclusionQuery(49).
[Invalid CommandBuffer from CommandEncoder "render"] is invalid.
 - While calling [Queue].Submit([[CommandBuffer from CommandEncoder "upload"], [CommandBuffer from CommandEncoder "renderTarget"], [Invalid CommandBuffer from CommandEncoder "render"]])

Your PG does work for me in WebGL and WebGPU, I have no errors in the console?

However, for the clear color to change correctly, you should replace mesh.clearColor with scene.clearColor.

Oh, yes I hadn’t paid attention to the scene.clearColor. It works like this.

But when are there errors in the console :
a.getContext(...).drawWindow is not a function

And why on my project do I have these two errors repeating when I use occlusions? What could be causing these errors?

Query index 49 of [QuerySet] is written to twice in a render pass.
 - While validating the occlusion query index (49) in [QuerySet]
 - While encoding [RenderPassEncoder].BeginOcclusionQuery(49).

[Invalid CommandBuffer from CommandEncoder "render"] is invalid.
 - While calling [Queue].Submit([[CommandBuffer from CommandEncoder "upload"], [CommandBuffer from CommandEncoder "renderTarget"], [Invalid CommandBuffer from CommandEncoder "render"]])

I don’t have the error a.getContext(...).drawWindow is not a function in the PG you provided(?)

This error means that a.getContext(...) doesn’t return a proper context, whatever a could be. But without a repro, it will be hard to find the root cause.

Regarding the second error, it’s what you get before the PR is merged: are you sure to use the latest version of Babylon.js, or at least a version with the fix?

For the getContext error I wonder if in this case it would not come from an extension of my browser.

For the second error, I am using the latest version 6.20. I’m trying to figure out why, but I don’t know what’s going on? what could produce this?

In fact, we didn’t have the second error before the PR, so it’s specific to your project…

I tried to reproduce it in a PG with a custom RTT + shadows, but couldn’t (https://playground.babylonjs.com/#QDAZ80#453).

Without a repro, it’s going to be hard to find the root cause. I’ll ask the people who implemented WebGPU in Chrome if they can shed some light on the error message.

In the meantime, are you able in your project to comment out code (such as shadows, additional rendering effects, etc.) until you no longer get the error? The idea is to be able to pinpoint more precisely what led to this error message.

Yes, that’s what I’m doing at the moment, I’m gradually deactivating everything to understand what’s wrong, when.

I realized that on the editor side it works (WebGPU and WebGL), but on the game generated, I the error in WebGPU and not WebGL). So I’m trying to understand where I’m going wrong.

As for the error I suspected to be from an extension for the a.getContext. This is indeed one of my extensions which is creating this error.

You probably don’t do anything wrong, it’s most probably on us :slight_smile:

:+1:

Just to be sure: you don’t write to engine.frameId or don’t call engine.endFrame() more than once per frame?

No, nothing with frameId or endFrame

I do this:

async initEngineBabylon()
    {		
		try {            
			if (navigator.gpu) {				
				this.engine = new BABYLON.WebGPUEngine(this.canvas, {stencil: true, antialias: true}); 
				await this.engine.initAsync();	
			} else {
				this.engine = new BABYLON.Engine(this.canvas, true, {stencil: true, preserveDrawingBuffer: true, useWebGL2: true}, true);
			}
		}
		catch(e) {
			try {
				this.engine = new BABYLON.Engine(this.canvas, true, {stencil: true, preserveDrawingBuffer: true, useWebGL2: true}, true);
			}
			catch(e) {
				jAlert('Sorry, your browser is not recent enough. it does not support <b>WebGL</b>. Try updating it or using a recent browser like <a href="https:\/\/www.google.fr/chrome\/?brand=CHBD&gclid=EAIaIQobChMI7IDfncHC6QIV0u5RCh3szA9IEAAYASAAEgKDJvD_BwE&gclsrc=aw.ds" target="_blank">Google Chrome</a>');
			}			
        }		

		this.engine.runRenderLoop(() => {
			if (this.sceneName) {
				if (this.scenes[this.sceneName]) {				
					this.scenes[this.sceneName].render();
				}
			}
		});
    }
	
	settinsEngine()
	{
		BABYLON.Engine.audioEngine.setGlobalVolume(1.0);
        BABYLON.Engine.audioEngine.useCustomUnlockedButton = true;
		
		this.engine.disableContextMenu = true;
        this.engine.enableOfflineSupport = false;
        this.engine.disableManifestCheck = true;
        this.engine.disablePerformanceMonitorInBackground = false;
        this.engine.renderEvenInBackground = true;        
        this.engine.setHardwareScalingLevel(window.devicePixelRatio);		

        window.addEventListener('resize', () => {
            this.engine.resize();
            this.canvas.focus();
        });
	}

Ok, I may have found the problem.

Can you add this code just after you created and initialized the engine:

    if (engine._occlusionQuery) {
        engine._occlusionQuery._allocateNewIndices(10);
    }

You should replace the 10 value with the number of meshes for which occlusion queries are enabled. You don’t have to pass the exact number, this number only has to be equal or greater to the number of meshes with occlusion queries.

Let me know if you still have the error after this change.

This doesn’t seem to have any effect.

Ah, too bad!

I will still make a PR because there is a small bug in the occlusion query code in WebGPU ([EDIT] PR: WebGPU: Fix warnings when using occlusion queries by Popov72 Ā· Pull Request #14272 Ā· BabylonJS/Babylon.js Ā· GitHub)

Let’s hope you are able to locate more precisely where the problem comes.

I will continue to try to find something on my end.

1 Like

Thank you very much Evgeni for your help.
Looks like I managed to reproduce the errors in the console. Although on the screen it seems to work.

The warnings are not related to occlusion queries.

You get them because you mix your own engine with the one provided with the Playground.

PG fixed: