mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
chore(ext/webgpu): include GPUCanvasContext in snapshot (#21773)
Part 1 of #21713 Changes: - Remove `.present()` and add a `presentGPUCanvasContext` (not exposed yet to users) - Move lazy load logic to `00_init.js`. This can be used to use webgpu on-demand from future code (OffScreenCanvas)
This commit is contained in:
parent
611993fbe0
commit
9f86705fa6
9 changed files with 141 additions and 139 deletions
|
@ -172,7 +172,7 @@ hkdf = "0.12.3"
|
||||||
|
|
||||||
# webgpu
|
# webgpu
|
||||||
raw-window-handle = "0.5.0"
|
raw-window-handle = "0.5.0"
|
||||||
wgpu-core = "=0.18"
|
wgpu-core = { version = "=0.18", features = ["raw-window-handle"] }
|
||||||
wgpu-types = "=0.18"
|
wgpu-types = "=0.18"
|
||||||
wgpu-hal = "=0.18"
|
wgpu-hal = "=0.18"
|
||||||
|
|
||||||
|
|
39
ext/webgpu/00_init.js
Normal file
39
ext/webgpu/00_init.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { core } from "ext:core/mod.js";
|
||||||
|
const ops = core.ops;
|
||||||
|
|
||||||
|
let webgpu;
|
||||||
|
|
||||||
|
function webGPUNonEnumerable(getter) {
|
||||||
|
let valueIsSet = false;
|
||||||
|
let value;
|
||||||
|
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
loadWebGPU();
|
||||||
|
|
||||||
|
if (valueIsSet) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
return getter();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set(v) {
|
||||||
|
loadWebGPU();
|
||||||
|
|
||||||
|
valueIsSet = true;
|
||||||
|
value = v;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadWebGPU() {
|
||||||
|
if (!webgpu) {
|
||||||
|
webgpu = ops.op_lazy_load_esm("ext:deno_webgpu/01_webgpu.js");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { loadWebGPU, webgpu, webGPUNonEnumerable };
|
|
@ -7036,6 +7036,78 @@ webidl.converters["GPUSignedOffset32"] = (V, opts) =>
|
||||||
// TYPEDEF: GPUFlagsConstant
|
// TYPEDEF: GPUFlagsConstant
|
||||||
webidl.converters["GPUFlagsConstant"] = webidl.converters["unsigned long"];
|
webidl.converters["GPUFlagsConstant"] = webidl.converters["unsigned long"];
|
||||||
|
|
||||||
|
// ENUM: GPUCanvasAlphaMode
|
||||||
|
webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter(
|
||||||
|
"GPUCanvasAlphaMode",
|
||||||
|
[
|
||||||
|
"opaque",
|
||||||
|
"premultiplied",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// NON-SPEC: ENUM: GPUPresentMode
|
||||||
|
webidl.converters["GPUPresentMode"] = webidl.createEnumConverter(
|
||||||
|
"GPUPresentMode",
|
||||||
|
[
|
||||||
|
"autoVsync",
|
||||||
|
"autoNoVsync",
|
||||||
|
"fifo",
|
||||||
|
"fifoRelaxed",
|
||||||
|
"immediate",
|
||||||
|
"mailbox",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// DICT: GPUCanvasConfiguration
|
||||||
|
const dictMembersGPUCanvasConfiguration = [
|
||||||
|
{ key: "device", converter: webidl.converters.GPUDevice, required: true },
|
||||||
|
{
|
||||||
|
key: "format",
|
||||||
|
converter: webidl.converters.GPUTextureFormat,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "usage",
|
||||||
|
converter: webidl.converters["GPUTextureUsageFlags"],
|
||||||
|
defaultValue: GPUTextureUsage.RENDER_ATTACHMENT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "alphaMode",
|
||||||
|
converter: webidl.converters["GPUCanvasAlphaMode"],
|
||||||
|
defaultValue: "opaque",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Extended from spec
|
||||||
|
{
|
||||||
|
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(
|
||||||
|
webidl.converters["GPUTextureFormat"],
|
||||||
|
),
|
||||||
|
get defaultValue() {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
webidl.converters["GPUCanvasConfiguration"] = webidl
|
||||||
|
.createDictionaryConverter(
|
||||||
|
"GPUCanvasConfiguration",
|
||||||
|
dictMembersGPUCanvasConfiguration,
|
||||||
|
);
|
||||||
|
|
||||||
const gpu = webidl.createBranded(GPU);
|
const gpu = webidl.createBranded(GPU);
|
||||||
export {
|
export {
|
||||||
_device,
|
_device,
|
||||||
|
|
|
@ -11,22 +11,16 @@ const ops = core.ops;
|
||||||
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
||||||
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
|
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
|
||||||
const { Symbol, SymbolFor, ObjectPrototypeIsPrototypeOf } = primordials;
|
const { Symbol, SymbolFor, ObjectPrototypeIsPrototypeOf } = primordials;
|
||||||
import {
|
import { loadWebGPU, webgpu } from "ext:deno_webgpu/00_init.js";
|
||||||
_device,
|
|
||||||
assertDevice,
|
|
||||||
createGPUTexture,
|
|
||||||
GPUTextureUsage,
|
|
||||||
} from "ext:deno_webgpu/01_webgpu.js";
|
|
||||||
|
|
||||||
const _surfaceRid = Symbol("[[surfaceRid]]");
|
const _surfaceRid = Symbol("[[surfaceRid]]");
|
||||||
const _configuration = Symbol("[[configuration]]");
|
const _configuration = Symbol("[[configuration]]");
|
||||||
const _canvas = Symbol("[[canvas]]");
|
const _canvas = Symbol("[[canvas]]");
|
||||||
const _currentTexture = Symbol("[[currentTexture]]");
|
const _currentTexture = Symbol("[[currentTexture]]");
|
||||||
|
const _present = Symbol("[[present]]");
|
||||||
class GPUCanvasContext {
|
class GPUCanvasContext {
|
||||||
/** @type {number} */
|
/** @type {number} */
|
||||||
[_surfaceRid];
|
[_surfaceRid];
|
||||||
/** @type {InnerGPUDevice} */
|
|
||||||
[_device];
|
|
||||||
[_configuration];
|
[_configuration];
|
||||||
[_canvas];
|
[_canvas];
|
||||||
/** @type {GPUTexture | undefined} */
|
/** @type {GPUTexture | undefined} */
|
||||||
|
@ -50,6 +44,7 @@ class GPUCanvasContext {
|
||||||
context: "Argument 1",
|
context: "Argument 1",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { _device, assertDevice } = webgpu;
|
||||||
this[_device] = configuration.device[_device];
|
this[_device] = configuration.device[_device];
|
||||||
this[_configuration] = configuration;
|
this[_configuration] = configuration;
|
||||||
const device = assertDevice(this, {
|
const device = assertDevice(this, {
|
||||||
|
@ -72,6 +67,8 @@ class GPUCanvasContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
unconfigure() {
|
unconfigure() {
|
||||||
|
const { _device } = webgpu;
|
||||||
|
|
||||||
webidl.assertBranded(this, GPUCanvasContextPrototype);
|
webidl.assertBranded(this, GPUCanvasContextPrototype);
|
||||||
|
|
||||||
this[_configuration] = null;
|
this[_configuration] = null;
|
||||||
|
@ -86,6 +83,7 @@ class GPUCanvasContext {
|
||||||
if (this[_configuration] === null) {
|
if (this[_configuration] === null) {
|
||||||
throw new DOMException("context is not configured.", "InvalidStateError");
|
throw new DOMException("context is not configured.", "InvalidStateError");
|
||||||
}
|
}
|
||||||
|
const { createGPUTexture, assertDevice } = webgpu;
|
||||||
|
|
||||||
const device = assertDevice(this, { prefix, context: "this" });
|
const device = assertDevice(this, { prefix, context: "this" });
|
||||||
|
|
||||||
|
@ -119,8 +117,10 @@ class GPUCanvasContext {
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extended from spec. Required to present the texture; browser don't need this.
|
// Required to present the texture; browser don't need this.
|
||||||
present() {
|
[_present]() {
|
||||||
|
const { assertDevice } = webgpu;
|
||||||
|
|
||||||
webidl.assertBranded(this, GPUCanvasContextPrototype);
|
webidl.assertBranded(this, GPUCanvasContextPrototype);
|
||||||
const prefix = "Failed to execute 'present' on 'GPUCanvasContext'";
|
const prefix = "Failed to execute 'present' on 'GPUCanvasContext'";
|
||||||
const device = assertDevice(this[_currentTexture], {
|
const device = assertDevice(this[_currentTexture], {
|
||||||
|
@ -148,88 +148,17 @@ class GPUCanvasContext {
|
||||||
const GPUCanvasContextPrototype = GPUCanvasContext.prototype;
|
const GPUCanvasContextPrototype = GPUCanvasContext.prototype;
|
||||||
|
|
||||||
function createCanvasContext(options) {
|
function createCanvasContext(options) {
|
||||||
|
// lazy load webgpu if needed
|
||||||
|
loadWebGPU();
|
||||||
|
|
||||||
const canvasContext = webidl.createBranded(GPUCanvasContext);
|
const canvasContext = webidl.createBranded(GPUCanvasContext);
|
||||||
canvasContext[_surfaceRid] = options.surfaceRid;
|
canvasContext[_surfaceRid] = options.surfaceRid;
|
||||||
canvasContext[_canvas] = options.canvas;
|
canvasContext[_canvas] = options.canvas;
|
||||||
return canvasContext;
|
return canvasContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converters
|
function presentGPUCanvasContext(ctx) {
|
||||||
|
ctx[_present]();
|
||||||
|
}
|
||||||
|
|
||||||
// ENUM: GPUCanvasAlphaMode
|
export { createCanvasContext, GPUCanvasContext, presentGPUCanvasContext };
|
||||||
webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter(
|
|
||||||
"GPUCanvasAlphaMode",
|
|
||||||
[
|
|
||||||
"opaque",
|
|
||||||
"premultiplied",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
// NON-SPEC: ENUM: GPUPresentMode
|
|
||||||
webidl.converters["GPUPresentMode"] = webidl.createEnumConverter(
|
|
||||||
"GPUPresentMode",
|
|
||||||
[
|
|
||||||
"autoVsync",
|
|
||||||
"autoNoVsync",
|
|
||||||
"fifo",
|
|
||||||
"fifoRelaxed",
|
|
||||||
"immediate",
|
|
||||||
"mailbox",
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
// DICT: GPUCanvasConfiguration
|
|
||||||
const dictMembersGPUCanvasConfiguration = [
|
|
||||||
{ key: "device", converter: webidl.converters.GPUDevice, required: true },
|
|
||||||
{
|
|
||||||
key: "format",
|
|
||||||
converter: webidl.converters.GPUTextureFormat,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "usage",
|
|
||||||
converter: webidl.converters["GPUTextureUsageFlags"],
|
|
||||||
defaultValue: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "alphaMode",
|
|
||||||
converter: webidl.converters["GPUCanvasAlphaMode"],
|
|
||||||
defaultValue: "opaque",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Extended from spec
|
|
||||||
{
|
|
||||||
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(
|
|
||||||
webidl.converters["GPUTextureFormat"],
|
|
||||||
),
|
|
||||||
get defaultValue() {
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
webidl.converters["GPUCanvasConfiguration"] = webidl
|
|
||||||
.createDictionaryConverter(
|
|
||||||
"GPUCanvasConfiguration",
|
|
||||||
dictMembersGPUCanvasConfiguration,
|
|
||||||
);
|
|
||||||
|
|
||||||
window.__bootstrap.webgpu = {
|
|
||||||
...window.__bootstrap.webgpu,
|
|
||||||
GPUCanvasContext,
|
|
||||||
createCanvasContext,
|
|
||||||
};
|
|
||||||
|
|
|
@ -13,9 +13,6 @@ description = "WebGPU implementation for Deno"
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[features]
|
|
||||||
surface = ["wgpu-core/raw-window-handle", "dep:raw-window-handle"]
|
|
||||||
|
|
||||||
# We make all dependencies conditional on not being wasm,
|
# We make all dependencies conditional on not being wasm,
|
||||||
# so the whole workspace can built as wasm.
|
# so the whole workspace can built as wasm.
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
|
|
@ -23,7 +23,6 @@ use wgpu_core::device::DeviceError;
|
||||||
use wgpu_core::pipeline::CreateComputePipelineError;
|
use wgpu_core::pipeline::CreateComputePipelineError;
|
||||||
use wgpu_core::pipeline::CreateRenderPipelineError;
|
use wgpu_core::pipeline::CreateRenderPipelineError;
|
||||||
use wgpu_core::pipeline::CreateShaderModuleError;
|
use wgpu_core::pipeline::CreateShaderModuleError;
|
||||||
#[cfg(feature = "surface")]
|
|
||||||
use wgpu_core::present::ConfigureSurfaceError;
|
use wgpu_core::present::ConfigureSurfaceError;
|
||||||
use wgpu_core::resource::BufferAccessError;
|
use wgpu_core::resource::BufferAccessError;
|
||||||
use wgpu_core::resource::CreateBufferError;
|
use wgpu_core::resource::CreateBufferError;
|
||||||
|
@ -282,7 +281,6 @@ impl From<ClearError> for WebGpuError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "surface")]
|
|
||||||
impl From<ConfigureSurfaceError> for WebGpuError {
|
impl From<ConfigureSurfaceError> for WebGpuError {
|
||||||
fn from(err: ConfigureSurfaceError) -> Self {
|
fn from(err: ConfigureSurfaceError) -> Self {
|
||||||
WebGpuError::Validation(fmt_err(&err))
|
WebGpuError::Validation(fmt_err(&err))
|
||||||
|
|
|
@ -75,7 +75,6 @@ pub mod queue;
|
||||||
pub mod render_pass;
|
pub mod render_pass;
|
||||||
pub mod sampler;
|
pub mod sampler;
|
||||||
pub mod shader;
|
pub mod shader;
|
||||||
#[cfg(feature = "surface")]
|
|
||||||
pub mod surface;
|
pub mod surface;
|
||||||
pub mod texture;
|
pub mod texture;
|
||||||
|
|
||||||
|
@ -212,7 +211,12 @@ deno_core::extension!(
|
||||||
queue::op_webgpu_write_texture,
|
queue::op_webgpu_write_texture,
|
||||||
// shader
|
// shader
|
||||||
shader::op_webgpu_create_shader_module,
|
shader::op_webgpu_create_shader_module,
|
||||||
|
// surface
|
||||||
|
surface::op_webgpu_surface_configure,
|
||||||
|
surface::op_webgpu_surface_get_current_texture,
|
||||||
|
surface::op_webgpu_surface_present
|
||||||
],
|
],
|
||||||
|
esm = ["00_init.js", "02_surface.js"],
|
||||||
lazy_loaded_esm = ["01_webgpu.js"],
|
lazy_loaded_esm = ["01_webgpu.js"],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -11,17 +11,6 @@ use std::borrow::Cow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wgpu_types::SurfaceStatus;
|
use wgpu_types::SurfaceStatus;
|
||||||
|
|
||||||
deno_core::extension!(
|
|
||||||
deno_webgpu_surface,
|
|
||||||
deps = [deno_webidl, deno_web, deno_webgpu],
|
|
||||||
ops = [
|
|
||||||
op_webgpu_surface_configure,
|
|
||||||
op_webgpu_surface_get_current_texture,
|
|
||||||
op_webgpu_surface_present,
|
|
||||||
],
|
|
||||||
esm = ["02_surface.js"],
|
|
||||||
);
|
|
||||||
|
|
||||||
pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId);
|
pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId);
|
||||||
impl Resource for WebGpuSurface {
|
impl Resource for WebGpuSurface {
|
||||||
fn name(&self) -> Cow<str> {
|
fn name(&self) -> Cow<str> {
|
||||||
|
|
|
@ -42,6 +42,12 @@ import * as globalInterfaces from "ext:deno_web/04_global_interfaces.js";
|
||||||
import * as webStorage from "ext:deno_webstorage/01_webstorage.js";
|
import * as webStorage from "ext:deno_webstorage/01_webstorage.js";
|
||||||
import * as prompt from "ext:runtime/41_prompt.js";
|
import * as prompt from "ext:runtime/41_prompt.js";
|
||||||
import * as imageData from "ext:deno_web/16_image_data.js";
|
import * as imageData from "ext:deno_web/16_image_data.js";
|
||||||
|
import {
|
||||||
|
loadWebGPU,
|
||||||
|
webgpu,
|
||||||
|
webGPUNonEnumerable,
|
||||||
|
} from "ext:deno_webgpu/00_init.js";
|
||||||
|
import * as webgpuSurface from "ext:deno_webgpu/02_surface.js";
|
||||||
import { unstableIds } from "ext:runtime/90_deno_ns.js";
|
import { unstableIds } from "ext:runtime/90_deno_ns.js";
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
|
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
|
||||||
|
@ -189,6 +195,7 @@ unstableForWindowOrWorkerGlobalScope[unstableIds.webgpu] = {
|
||||||
GPUError: webGPUNonEnumerable(() => webgpu.GPUError),
|
GPUError: webGPUNonEnumerable(() => webgpu.GPUError),
|
||||||
GPUValidationError: webGPUNonEnumerable(() => webgpu.GPUValidationError),
|
GPUValidationError: webGPUNonEnumerable(() => webgpu.GPUValidationError),
|
||||||
GPUOutOfMemoryError: webGPUNonEnumerable(() => webgpu.GPUOutOfMemoryError),
|
GPUOutOfMemoryError: webGPUNonEnumerable(() => webgpu.GPUOutOfMemoryError),
|
||||||
|
GPUCanvasContext: webGPUNonEnumerable(() => webgpuSurface.GPUCanvasContext),
|
||||||
};
|
};
|
||||||
|
|
||||||
class Navigator {
|
class Navigator {
|
||||||
|
@ -229,39 +236,6 @@ const numCpus = memoizeLazy(() => ops.op_bootstrap_numcpus());
|
||||||
const userAgent = memoizeLazy(() => ops.op_bootstrap_user_agent());
|
const userAgent = memoizeLazy(() => ops.op_bootstrap_user_agent());
|
||||||
const language = memoizeLazy(() => ops.op_bootstrap_language());
|
const language = memoizeLazy(() => ops.op_bootstrap_language());
|
||||||
|
|
||||||
let webgpu;
|
|
||||||
|
|
||||||
function webGPUNonEnumerable(getter) {
|
|
||||||
let valueIsSet = false;
|
|
||||||
let value;
|
|
||||||
|
|
||||||
return {
|
|
||||||
get() {
|
|
||||||
loadWebGPU();
|
|
||||||
|
|
||||||
if (valueIsSet) {
|
|
||||||
return value;
|
|
||||||
} else {
|
|
||||||
return getter();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set(v) {
|
|
||||||
loadWebGPU();
|
|
||||||
|
|
||||||
valueIsSet = true;
|
|
||||||
value = v;
|
|
||||||
},
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadWebGPU() {
|
|
||||||
if (!webgpu) {
|
|
||||||
webgpu = ops.op_lazy_load_esm("ext:deno_webgpu/01_webgpu.js");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectDefineProperties(Navigator.prototype, {
|
ObjectDefineProperties(Navigator.prototype, {
|
||||||
gpu: {
|
gpu: {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
|
|
Loading…
Reference in a new issue