Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/core/p5.Renderer3D.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,14 +387,17 @@ export class Renderer3D extends Renderer {
!isPGraphics,
this._pInst.canvas
);
this._pInst._renderer = renderer;

renderer._applyDefaults();
renderer.pixelDensity(this._pixelDensity);

if (renderer.contextReady) {
await renderer.contextReady
}

this._pInst._renderer = renderer;

renderer._applyDefaults();

if (typeof callback === "function") {
//setTimeout with 0 forces the task to the back of the queue, this ensures that
//we finish switching out the renderer
Expand Down
2 changes: 2 additions & 0 deletions src/webgpu/p5.RendererWebGPU.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ function rendererWebGPU(p5, fn) {
}

_updateSize() {
if (!this.device) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, is this added just to methods that get called automatically when you reinitialize the context?

if (this.depthTexture && this.depthTexture.destroy) {
this.flushDraw();
const textureToDestroy = this.depthTexture;
Expand Down Expand Up @@ -279,6 +280,7 @@ function rendererWebGPU(p5, fn) {
}

clear(...args) {
if (!this.device) return;
const _r = args[0] || 0;
const _g = args[1] || 0;
const _b = args[2] || 0;
Expand Down
51 changes: 51 additions & 0 deletions test/unit/webgpu/issue_repro.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import p5 from '../../../src/app.js';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new file called issue_repro.js is not really readable for future contributors trying to understand the structure of our code and tests. Could this just be a test in the existing WebGPU renderer tests?

import rendererWebGPU from "../../../src/webgpu/p5.RendererWebGPU";

p5.registerAddon(rendererWebGPU);

suite('WebGPU Issue Repro (pixelDensity after setAttributes)', function() {
let myp5;

afterEach(function() {
if (myp5) {
myp5.remove();
}
});

test('pixelDensity(1) after setAttributes() should not crash', async function() {
// This test simulates the issue where a synchronous call (pixelDensity)
// happens before an asynchronous initialization (setAttributes -> _resetContext)
// is complete.

await new Promise((resolve, reject) => {
try {
myp5 = new p5(function(p) {
p.setup = async function() {
try {
await p.createCanvas(100, 100, 'webgpu');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use p.WEBGPU rather than the value of the constant?


// This triggers an asynchronous _resetContext
p.setAttributes({ powerPreference: 'low-power' });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure that we'll do something with this, can we try changing antialias as a more normal example?


// This triggers a synchronous resize() -> _updateSize()
// before the new renderer's device is ready.
p.pixelDensity(1);

resolve();
} catch (err) {
reject(err);
}
};
});
} catch (err) {
reject(err);
}
});

// If we reach here, no immediate crash occurred.
// Let's wait for the context to finish resetting to be sure everything is stable.
await new Promise(resolve => setTimeout(resolve, 100));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeouts in tests are fairly brittle, we can use expect(() => { ... }).not.toThrow() or something like that as an alternative.

expect(myp5._renderer).to.exist;
expect(myp5._renderer.device).to.exist;
});
});