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
3 changes: 3 additions & 0 deletions src/webgpu/p5.RendererWebGPU.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ function rendererWebGPU(p5, fn) {
}

_updateSize() {
if (!this.device) return;
if (this.depthTexture && this.depthTexture.destroy) {
this.depthTexture.destroy();
}
Expand All @@ -175,6 +176,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 Expand Up @@ -231,6 +233,7 @@ function rendererWebGPU(p5, fn) {
* occlude anything subsequently drawn.
*/
clearDepth(depth = 1) {
if (!this.device) return;
const commandEncoder = this.device.createCommandEncoder();

// Use framebuffer texture if active, otherwise use canvas texture
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';
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');

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

// 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));
expect(myp5._renderer).to.exist;
expect(myp5._renderer.device).to.exist;
});
});