Skip to content

Commit

Permalink
BREAKING(webgpu/unstable): move width and height options to `Unsa…
Browse files Browse the repository at this point in the history
…feWindowSurface` constructor (#24200)

Fixes #23508

`width` and `height` are required to configure the wgpu surface because
Deno is headless and depends on user to create a window. The options
were non-standard extension of `GPUCanvasConfiguration#configure`.

This PR adds a required options parameter with the `width` and `height`
options to `Deno.UnsafeWindowSurface` constructor.

```typescript
// Old, non-standard extension of GPUCanvasConfiguration
const surface = new Deno.UnsafeWindowSurface("x11", displayHandle, windowHandle);

const context  = surface.getContext();
context.configure({ width: 600, height: 800, /* ... */ });
```

```typescript
// New
const surface = new Deno.UnsafeWindowSurface({
  system: "x11",
  windowHandle,
  displayHandle,
  width: 600,
  height: 800,
});

const context  = surface.getContext();
context.configure({ /* ... */ });
```
  • Loading branch information
littledivy authored Sep 22, 2024
1 parent 9be8dce commit 0cb00a6
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 23 deletions.
10 changes: 7 additions & 3 deletions cli/tsc/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ declare namespace Deno {
*/
export class UnsafeWindowSurface {
constructor(
system: "cocoa" | "win32" | "x11" | "wayland",
windowHandle: Deno.PointerValue<unknown>,
displayHandle: Deno.PointerValue<unknown>,
options: {
system: "cocoa" | "win32" | "x11" | "wayland";
windowHandle: Deno.PointerValue<unknown>;
displayHandle: Deno.PointerValue<unknown>;
width: number;
height: number;
},
);
getContext(context: "webgpu"): GPUCanvasContext;
present(): void;
Expand Down
2 changes: 0 additions & 2 deletions cli/tsc/dts/lib.deno_webgpu.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1372,8 +1372,6 @@ declare interface GPUCanvasConfiguration {
viewFormats?: GPUTextureFormat[];
colorSpace?: "srgb" | "display-p3";
alphaMode?: GPUCanvasAlphaMode;
width: number;
height: number;
}
/** @category GPU */
declare interface GPUCanvasContext {
Expand Down
10 changes: 0 additions & 10 deletions ext/webgpu/01_webgpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -7434,16 +7434,6 @@ const dictMembersGPUCanvasConfiguration = [
key: "presentMode",
converter: webidl.converters["GPUPresentMode"],
},
{
key: "width",
converter: webidl.converters["long"],
required: true,
},
{
key: "height",
converter: webidl.converters["long"],
required: true,
},
{
key: "viewFormats",
converter: webidl.createSequenceConverter(
Expand Down
37 changes: 30 additions & 7 deletions ext/webgpu/02_surface.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ const _configuration = Symbol("[[configuration]]");
const _canvas = Symbol("[[canvas]]");
const _currentTexture = Symbol("[[currentTexture]]");
const _present = Symbol("[[present]]");
const _dim = Symbol("[[dimensions]]");

class GPUCanvasContext {
/** @type {number} */
[_surfaceRid];
[_configuration];
[_canvas];
/** @type {GPUTexture | undefined} */
[_currentTexture];
[_dim];

get canvas() {
webidl.assertBranded(this, GPUCanvasContextPrototype);
Expand Down Expand Up @@ -69,8 +72,8 @@ class GPUCanvasContext {
format: configuration.format,
viewFormats: configuration.viewFormats,
usage: configuration.usage,
width: configuration.width,
height: configuration.height,
width: this[_dim].width,
height: this[_dim].height,
alphaMode: configuration.alphaMode,
});

Expand Down Expand Up @@ -110,8 +113,8 @@ class GPUCanvasContext {
const texture = createGPUTexture(
{
size: {
width: this[_configuration].width,
height: this[_configuration].height,
width: this[_dim].width,
height: this[_dim].height,
depthOrArrayLayers: 1,
},
mipLevelCount: 1,
Expand Down Expand Up @@ -163,6 +166,8 @@ function createCanvasContext(options) {
const canvasContext = webidl.createBranded(GPUCanvasContext);
canvasContext[_surfaceRid] = options.surfaceRid;
canvasContext[_canvas] = options.canvas;
canvasContext[_dim] = { width: options.width, height: options.height };

return canvasContext;
}

Expand All @@ -172,16 +177,34 @@ function createCanvasContext(options) {
class UnsafeWindowSurface {
#ctx;
#surfaceRid;
#options;

constructor(system, win, display) {
this.#surfaceRid = op_webgpu_surface_create(system, win, display);
constructor(options) {
if (typeof options !== "object") {
throw new TypeError("options must be provided.");
}
if (
typeof options.width !== "number" || typeof options.height !== "number"
) {
throw new TypeError("width and height must be provided.");
}

this.#surfaceRid = op_webgpu_surface_create(
options.system,
options.windowHandle,
options.displayHandle,
);
this.#options = options;
}

getContext(context) {
if (context !== "webgpu") {
throw new TypeError("Only 'webgpu' context is supported");
}
this.#ctx = createCanvasContext({ surfaceRid: this.#surfaceRid });
this.#ctx = createCanvasContext({
surfaceRid: this.#surfaceRid,
...this.#options,
});
return this.#ctx;
}

Expand Down
21 changes: 20 additions & 1 deletion tests/unit/webgpu_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,32 @@ Deno.test({

assertThrows(
() => {
new Deno.UnsafeWindowSurface("cocoa", null, null);
new Deno.UnsafeWindowSurface({
system: "cocoa",
windowHandle: null,
displayHandle: null,
width: 0,
height: 0,
});
},
);

device.destroy();
});

Deno.test(function webgpuWindowSurfaceNoWidthHeight() {
assertThrows(
() => {
// @ts-expect-error width and height are required
new Deno.UnsafeWindowSurface({
system: "x11",
windowHandle: null,
displayHandle: null,
});
},
);
});

Deno.test(function getPreferredCanvasFormat() {
const preferredFormat = navigator.gpu.getPreferredCanvasFormat();
assert(preferredFormat === "bgra8unorm" || preferredFormat === "rgba8unorm");
Expand Down

0 comments on commit 0cb00a6

Please sign in to comment.