experiment: wgpu sync (#13402)

This commit is contained in:
Aaron O'Mullan 2022-01-19 13:38:51 +01:00 committed by GitHub
parent 1259a3f48c
commit 2ab21dafa7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1348 additions and 1917 deletions

94
Cargo.lock generated
View file

@ -136,9 +136,9 @@ dependencies = [
[[package]] [[package]]
name = "ash" name = "ash"
version = "0.33.3+1.2.191" version = "0.35.0+1.2.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc4f1d82f164f838ae413296d1131aa6fa79b917d25bebaa7033d25620c09219" checksum = "5a7638ce84f8c84d6fd6faa63aa267574d345181ba591c0eeb5550d4c30cd600"
dependencies = [ dependencies = [
"libloading", "libloading",
] ]
@ -283,6 +283,16 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitflags_serde_shim"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25c3d626f0280ec39b33a6fc5c6c1067432b4c41e94aee40ded197a6649bf025"
dependencies = [
"bitflags",
"serde",
]
[[package]] [[package]]
name = "block" name = "block"
version = "0.1.6" version = "0.1.6"
@ -1428,12 +1438,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "fixedbitset"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
[[package]] [[package]]
name = "flaky_test" name = "flaky_test"
version = "0.1.0" version = "0.1.0"
@ -1797,6 +1801,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hexf-parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]] [[package]]
name = "hmac" name = "hmac"
version = "0.11.0" version = "0.11.0"
@ -2307,8 +2317,7 @@ dependencies = [
[[package]] [[package]]
name = "metal" name = "metal"
version = "0.23.1" version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/metal-rs?rev=140c8f4#140c8f4e39001ae154f153ffc767da6c0c9d7f06"
checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"block", "block",
@ -2358,17 +2367,17 @@ dependencies = [
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.6.3" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/naga?rev=a1840be#a1840beb1a96c9a49980fe3efa8e2f3dcd88abe6"
checksum = "8c5859e55c51da10b98e7a73068e0a0c5da7bbcae4fc38f86043d0c6d1b917cf"
dependencies = [ dependencies = [
"bit-set", "bit-set",
"bitflags", "bitflags",
"codespan-reporting", "codespan-reporting",
"fxhash", "hexf-parse",
"indexmap",
"log", "log",
"num-traits", "num-traits",
"petgraph 0.6.0", "rustc-hash",
"serde", "serde",
"spirv", "spirv",
"thiserror", "thiserror",
@ -2660,17 +2669,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
dependencies = [ dependencies = [
"fixedbitset 0.2.0", "fixedbitset",
"indexmap",
]
[[package]]
name = "petgraph"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f"
dependencies = [
"fixedbitset 0.4.1",
"indexmap", "indexmap",
] ]
@ -3038,16 +3037,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6"
[[package]]
name = "raw-window-handle"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76"
dependencies = [
"libc",
"raw-window-handle 0.4.2",
]
[[package]] [[package]]
name = "raw-window-handle" name = "raw-window-handle"
version = "0.4.2" version = "0.4.2"
@ -3183,9 +3172,9 @@ dependencies = [
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.6.6" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86018df177b1beef6c7c8ef949969c4f7cb9a9344181b92486b23c79995bdaa4" checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678"
dependencies = [ dependencies = [
"base64 0.13.0", "base64 0.13.0",
"bitflags", "bitflags",
@ -3730,7 +3719,7 @@ dependencies = [
"is-macro", "is-macro",
"once_cell", "once_cell",
"parking_lot", "parking_lot",
"petgraph 0.5.1", "petgraph",
"radix_fmt", "radix_fmt",
"relative-path", "relative-path",
"retain_mut", "retain_mut",
@ -4081,7 +4070,7 @@ checksum = "1d53bbcbb4b055c547f283af1f84211f425b95ac59e02d8b70c94b8a63a4704f"
dependencies = [ dependencies = [
"ahash", "ahash",
"indexmap", "indexmap",
"petgraph 0.5.1", "petgraph",
"swc_common", "swc_common",
] ]
@ -4093,7 +4082,7 @@ checksum = "83b42a8b13068dd90dec954ec44576d5922914687bc34277f3b0f8d0bbeb4e83"
dependencies = [ dependencies = [
"ahash", "ahash",
"auto_impl", "auto_impl",
"petgraph 0.5.1", "petgraph",
"swc_fast_graph", "swc_fast_graph",
"tracing", "tracing",
] ]
@ -4903,13 +4892,13 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-core" name = "wgpu-core"
version = "0.10.4" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/wgpu?rev=cdd480a89c9e3b681d9d174e65082d2bdbc903ef#cdd480a89c9e3b681d9d174e65082d2bdbc903ef"
checksum = "f963c62473a36e3cef6c58181f2ed6d0d38d2043d970dbed46cb197190090c99"
dependencies = [ dependencies = [
"arrayvec 0.7.2", "arrayvec 0.7.2",
"bitflags", "bitflags",
"cfg_aliases", "cfg_aliases",
"codespan-reporting",
"copyless", "copyless",
"fxhash", "fxhash",
"log", "log",
@ -4926,9 +4915,8 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-hal" name = "wgpu-hal"
version = "0.10.7" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/wgpu?rev=cdd480a89c9e3b681d9d174e65082d2bdbc903ef#cdd480a89c9e3b681d9d174e65082d2bdbc903ef"
checksum = "27cd894b17bff1958ee93da1cc991fd64bf99667746d4bd2a7403855f4d37fe2"
dependencies = [ dependencies = [
"arrayvec 0.7.2", "arrayvec 0.7.2",
"ash", "ash",
@ -4943,6 +4931,7 @@ dependencies = [
"gpu-alloc", "gpu-alloc",
"gpu-descriptor", "gpu-descriptor",
"inplace_it", "inplace_it",
"js-sys",
"khronos-egl", "khronos-egl",
"libloading", "libloading",
"log", "log",
@ -4950,21 +4939,24 @@ dependencies = [
"naga", "naga",
"objc", "objc",
"parking_lot", "parking_lot",
"profiling",
"range-alloc", "range-alloc",
"raw-window-handle 0.3.4", "raw-window-handle",
"renderdoc-sys", "renderdoc-sys",
"thiserror", "thiserror",
"wasm-bindgen",
"web-sys",
"wgpu-types", "wgpu-types",
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]] [[package]]
name = "wgpu-types" name = "wgpu-types"
version = "0.10.0" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/wgpu?rev=cdd480a89c9e3b681d9d174e65082d2bdbc903ef#cdd480a89c9e3b681d9d174e65082d2bdbc903ef"
checksum = "25feb2fbf24ab3219a9f10890ceb8e1ef02b13314ed89d64a9ae99dcad883e18"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"bitflags_serde_shim",
"serde", "serde",
] ]

View file

@ -82,7 +82,7 @@ fn create_compiler_snapshot(
op_crate_libs.insert("deno.url", deno_url::get_declaration()); op_crate_libs.insert("deno.url", deno_url::get_declaration());
op_crate_libs.insert("deno.web", deno_web::get_declaration()); op_crate_libs.insert("deno.web", deno_web::get_declaration());
op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration()); op_crate_libs.insert("deno.fetch", deno_fetch::get_declaration());
op_crate_libs.insert("deno.webgpu", deno_webgpu::get_declaration()); op_crate_libs.insert("deno.webgpu", deno_webgpu_get_declaration());
op_crate_libs.insert("deno.websocket", deno_websocket::get_declaration()); op_crate_libs.insert("deno.websocket", deno_websocket::get_declaration());
op_crate_libs.insert("deno.webstorage", deno_webstorage::get_declaration()); op_crate_libs.insert("deno.webstorage", deno_webstorage::get_declaration());
op_crate_libs.insert("deno.crypto", deno_crypto::get_declaration()); op_crate_libs.insert("deno.crypto", deno_crypto::get_declaration());
@ -322,7 +322,7 @@ fn main() {
); );
println!( println!(
"cargo:rustc-env=DENO_WEBGPU_LIB_PATH={}", "cargo:rustc-env=DENO_WEBGPU_LIB_PATH={}",
deno_webgpu::get_declaration().display() deno_webgpu_get_declaration().display()
); );
println!( println!(
"cargo:rustc-env=DENO_WEBSOCKET_LIB_PATH={}", "cargo:rustc-env=DENO_WEBSOCKET_LIB_PATH={}",
@ -369,6 +369,11 @@ fn main() {
} }
} }
fn deno_webgpu_get_declaration() -> PathBuf {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
manifest_dir.join("dts").join("lib.deno_webgpu.d.ts")
}
fn get_js_files(d: &str) -> Vec<PathBuf> { fn get_js_files(d: &str) -> Vec<PathBuf> {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let mut js_files = std::fs::read_dir(d) let mut js_files = std::fs::read_dir(d)

View file

@ -92,12 +92,15 @@ declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase {
} }
declare type GPUFeatureName = declare type GPUFeatureName =
| "depth-clamping" | "depth-clip-control"
| "depth24unorm-stencil8" | "depth24unorm-stencil8"
| "depth32float-stencil8" | "depth32float-stencil8"
| "pipeline-statistics-query" | "pipeline-statistics-query"
| "texture-compression-bc" | "texture-compression-bc"
| "texture-compression-etc2"
| "texture-compression-astc"
| "timestamp-query" | "timestamp-query"
| "indirect-first-instance"
// extended from spec // extended from spec
| "mappable-primary-buffers" | "mappable-primary-buffers"
| "sampled-texture-binding-array" | "sampled-texture-binding-array"
@ -108,9 +111,6 @@ declare type GPUFeatureName =
| "multi-draw-indirect-count" | "multi-draw-indirect-count"
| "push-constants" | "push-constants"
| "address-mode-clamp-to-border" | "address-mode-clamp-to-border"
| "non-fill-polygon-mode"
| "texture-compression-etc2"
| "texture-compression-astc-ldr"
| "texture-adapter-specific-format-features" | "texture-adapter-specific-format-features"
| "shader-float64" | "shader-float64"
| "vertex-attribute-64bit"; | "vertex-attribute-64bit";
@ -314,6 +314,44 @@ declare type GPUTextureFormat =
| "bc6h-rgb-float" | "bc6h-rgb-float"
| "bc7-rgba-unorm" | "bc7-rgba-unorm"
| "bc7-rgba-unorm-srgb" | "bc7-rgba-unorm-srgb"
| "etc2-rgb8unorm"
| "etc2-rgb8unorm-srgb"
| "etc2-rgb8a1unorm"
| "etc2-rgb8a1unorm-srgb"
| "etc2-rgba8unorm"
| "etc2-rgba8unorm-srgb"
| "eac-r11unorm"
| "eac-r11snorm"
| "eac-rg11unorm"
| "eac-rg11snorm"
| "astc-4x4-unorm"
| "astc-4x4-unorm-srgb"
| "astc-5x4-unorm"
| "astc-5x4-unorm-srgb"
| "astc-5x5-unorm"
| "astc-5x5-unorm-srgb"
| "astc-6x5-unorm"
| "astc-6x5-unorm-srgb"
| "astc-6x6-unorm"
| "astc-6x6-unorm-srgb"
| "astc-8x5-unorm"
| "astc-8x5-unorm-srgb"
| "astc-8x6-unorm"
| "astc-8x6-unorm-srgb"
| "astc-8x8-unorm"
| "astc-8x8-unorm-srgb"
| "astc-10x5-unorm"
| "astc-10x5-unorm-srgb"
| "astc-10x6-unorm"
| "astc-10x6-unorm-srgb"
| "astc-10x8-unorm"
| "astc-10x8-unorm-srgb"
| "astc-10x10-unorm"
| "astc-10x10-unorm-srgb"
| "astc-12x10-unorm"
| "astc-12x10-unorm-srgb"
| "astc-12x12-unorm"
| "astc-12x12-unorm-srgb"
| "depth24unorm-stencil8" | "depth24unorm-stencil8"
| "depth32float-stencil8"; | "depth32float-stencil8";
@ -519,7 +557,7 @@ declare interface GPUPrimitiveState {
stripIndexFormat?: GPUIndexFormat; stripIndexFormat?: GPUIndexFormat;
frontFace?: GPUFrontFace; frontFace?: GPUFrontFace;
cullMode?: GPUCullMode; cullMode?: GPUCullMode;
clampDepth?: boolean; unclippedDepth?: boolean;
} }
declare type GPUFrontFace = "ccw" | "cw"; declare type GPUFrontFace = "ccw" | "cw";
@ -558,9 +596,9 @@ declare class GPUColorWrite {
} }
declare interface GPUBlendComponent { declare interface GPUBlendComponent {
operation: GPUBlendOperation;
srcFactor: GPUBlendFactor; srcFactor: GPUBlendFactor;
dstFactor: GPUBlendFactor; dstFactor: GPUBlendFactor;
operation: GPUBlendOperation;
} }
declare type GPUBlendFactor = declare type GPUBlendFactor =
@ -673,8 +711,6 @@ declare interface GPUVertexAttribute {
declare class GPUCommandBuffer implements GPUObjectBase { declare class GPUCommandBuffer implements GPUObjectBase {
label: string | null; label: string | null;
readonly executionTime: Promise<number>;
} }
declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {} declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {}
@ -713,6 +749,12 @@ declare class GPUCommandEncoder implements GPUObjectBase {
copySize: GPUExtent3D, copySize: GPUExtent3D,
): undefined; ): undefined;
clearBuffer(
destination: GPUBuffer,
destinationOffset: number,
size: number,
): undefined;
pushDebugGroup(groupLabel: string): undefined; pushDebugGroup(groupLabel: string): undefined;
popDebugGroup(): undefined; popDebugGroup(): undefined;
insertDebugMarker(markerLabel: string): undefined; insertDebugMarker(markerLabel: string): undefined;
@ -730,9 +772,7 @@ declare class GPUCommandEncoder implements GPUObjectBase {
finish(descriptor?: GPUCommandBufferDescriptor): GPUCommandBuffer; finish(descriptor?: GPUCommandBufferDescriptor): GPUCommandBuffer;
} }
declare interface GPUCommandEncoderDescriptor extends GPUObjectDescriptorBase { declare interface GPUCommandEncoderDescriptor extends GPUObjectDescriptorBase {}
measureExecutionTime?: boolean;
}
declare interface GPUImageDataLayout { declare interface GPUImageDataLayout {
offset?: number; offset?: number;

View file

@ -1,9 +1,10 @@
[[block]]
struct PrimeIndices { struct PrimeIndices {
data: [[stride(4)]] array<u32>; data: [[stride(4)]] array<u32>;
}; // this is used as both input and output for convenience }; // this is used as both input and output for convenience
[[group(0), binding(0)]] [[group(0), binding(0)]]
var<storage, read_write> v_indices: PrimeIndices; var<storage, read_write> v_indices: PrimeIndices;
// The Collatz Conjecture states that for any integer n: // The Collatz Conjecture states that for any integer n:
// If n is even, n = n/2 // If n is even, n = n/2
// If n is odd, n = 3n+1 // If n is odd, n = 3n+1
@ -25,12 +26,14 @@ fn collatz_iterations(n_base: u32) -> u32{
if (n >= 1431655765u) { // 0x55555555u if (n >= 1431655765u) { // 0x55555555u
return 4294967295u; // 0xffffffffu return 4294967295u; // 0xffffffffu
} }
n = 3u * n + 1u; n = 3u * n + 1u;
} }
i = i + 1u; i = i + 1u;
} }
return i; return i;
} }
[[stage(compute), workgroup_size(1)]] [[stage(compute), workgroup_size(1)]]
fn main([[builtin(global_invocation_id)]] global_id: vec3<u32>) { fn main([[builtin(global_invocation_id)]] global_id: vec3<u32>) {
v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]); v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]);

View file

@ -33,13 +33,14 @@ Deno.test({
const stagingBuffer = device.createBuffer({ const stagingBuffer = device.createBuffer({
size: size, size: size,
usage: 1 | 8, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
}); });
const storageBuffer = device.createBuffer({ const storageBuffer = device.createBuffer({
label: "Storage Buffer", label: "Storage Buffer",
size: size, size: size,
usage: 0x80 | 8 | 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST |
GPUBufferUsage.COPY_SRC,
mappedAtCreation: true, mappedAtCreation: true,
}); });

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
// @ts-check // @ts-check
/// <reference path="../../core/lib.deno_core.d.ts" /> /// <reference path="../../core/lib.deno_core.d.ts" />
@ -3060,6 +3060,48 @@
device.pushError(err); device.pushError(err);
} }
/**
* @param {GPUBuffer} destination
* @param {GPUSize64} destinationOffset
* @param {GPUSize64} size
*/
clearBuffer(destination, destinationOffset, size) {
webidl.assertBranded(this, GPUCommandEncoder);
const prefix = "Failed to execute 'clearBuffer' on 'GPUCommandEncoder'";
webidl.requiredArguments(arguments.length, 3, { prefix });
destination = webidl.converters.GPUBuffer(destination, {
prefix,
context: "Argument 1",
});
destinationOffset = webidl.converters.GPUSize64(destinationOffset, {
prefix,
context: "Argument 2",
});
size = webidl.converters.GPUSize64(size, {
prefix,
context: "Argument 3",
});
const device = assertDevice(this, { prefix, context: "this" });
const commandEncoderRid = assertResource(this, {
prefix,
context: "this",
});
const destinationRid = assertResource(destination, {
prefix,
context: "Argument 1",
});
const { err } = core.opSync(
"op_webgpu_command_encoder_clear_buffer",
{
commandEncoderRid,
destinationRid,
destinationOffset,
size,
},
);
device.pushError(err);
}
/** /**
* @param {string} groupLabel * @param {string} groupLabel
*/ */
@ -3203,7 +3245,7 @@
prefix, prefix,
context: "Argument 3", context: "Argument 3",
}); });
destination = webidl.converters.GPUQuerySet(destination, { destination = webidl.converters.GPUBuffer(destination, {
prefix, prefix,
context: "Argument 4", context: "Argument 4",
}); });
@ -4527,15 +4569,10 @@
webidl.illegalConstructor(); webidl.illegalConstructor();
} }
get executionTime() {
throw new Error("Not yet implemented");
}
[SymbolFor("Deno.privateCustomInspect")](inspect) { [SymbolFor("Deno.privateCustomInspect")](inspect) {
return `${this.constructor.name} ${ return `${this.constructor.name} ${
inspect({ inspect({
label: this.label, label: this.label,
// TODO(crowlKats): executionTime
}) })
}`; }`;
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
// @ts-check // @ts-check
/// <reference path="../web/internal.d.ts" /> /// <reference path="../web/internal.d.ts" />
@ -111,28 +111,35 @@
webidl.converters["GPUFeatureName"] = webidl.createEnumConverter( webidl.converters["GPUFeatureName"] = webidl.createEnumConverter(
"GPUFeatureName", "GPUFeatureName",
[ [
"depth-clamping", "depth-clip-control",
"depth24unorm-stencil8", "depth24unorm-stencil8",
"depth32float-stencil8", "depth32float-stencil8",
"pipeline-statistics-query", "pipeline-statistics-query",
"texture-compression-bc", "texture-compression-bc",
"texture-compression-etc2",
"texture-compression-astc",
"timestamp-query", "timestamp-query",
"indirect-first-instance",
// extended from spec // extended from spec
"mappable-primary-buffers", "mappable-primary-buffers",
"sampled-texture-binding-array", "texture-binding-array",
"sampled-texture-array-dynamic-indexing", "buffer-binding-array",
"sampled-texture-array-non-uniform-indexing", "storage-resource-binding-array",
"sampled-texture-and-storage-buffer-array-non-uniform-indexing",
"uniform-buffer-and-storage-buffer-texture-non-uniform-indexing",
"unsized-binding-array", "unsized-binding-array",
"multi-draw-indirect", "multi-draw-indirect",
"multi-draw-indirect-count", "multi-draw-indirect-count",
"push-constants", "push-constants",
"address-mode-clamp-to-border", "address-mode-clamp-to-border",
"non-fill-polygon-mode",
"texture-compression-etc2",
"texture-compression-astc-ldr",
"texture-adapter-specific-format-features", "texture-adapter-specific-format-features",
"shader-float64", "shader-float64",
"vertex-attribute-64bit", "vertex-attribute-64bit",
"conservative-rasterization",
"vertex-writable-storage",
"clear-commands",
"spirv-shader-passthrough",
"shader-primitive-index",
], ],
); );
@ -348,6 +355,44 @@
"bc6h-rgb-float", "bc6h-rgb-float",
"bc7-rgba-unorm", "bc7-rgba-unorm",
"bc7-rgba-unorm-srgb", "bc7-rgba-unorm-srgb",
"etc2-rgb8unorm",
"etc2-rgb8unorm-srgb",
"etc2-rgb8a1unorm",
"etc2-rgb8a1unorm-srgb",
"etc2-rgba8unorm",
"etc2-rgba8unorm-srgb",
"eac-r11unorm",
"eac-r11snorm",
"eac-rg11unorm",
"eac-rg11snorm",
"astc-4x4-unorm",
"astc-4x4-unorm-srgb",
"astc-5x4-unorm",
"astc-5x4-unorm-srgb",
"astc-5x5-unorm",
"astc-5x5-unorm-srgb",
"astc-6x5-unorm",
"astc-6x5-unorm-srgb",
"astc-6x6-unorm",
"astc-6x6-unorm-srgb",
"astc-8x5-unorm",
"astc-8x5-unorm-srgb",
"astc-8x6-unorm",
"astc-8x6-unorm-srgb",
"astc-8x8-unorm",
"astc-8x8-unorm-srgb",
"astc-10x5-unorm",
"astc-10x5-unorm-srgb",
"astc-10x6-unorm",
"astc-10x6-unorm-srgb",
"astc-10x8-unorm",
"astc-10x8-unorm-srgb",
"astc-10x10-unorm",
"astc-10x10-unorm-srgb",
"astc-12x10-unorm",
"astc-12x10-unorm-srgb",
"astc-12x12-unorm",
"astc-12x12-unorm-srgb",
"depth24unorm-stencil8", "depth24unorm-stencil8",
"depth32float-stencil8", "depth32float-stencil8",
], ],
@ -1131,7 +1176,7 @@
defaultValue: "none", defaultValue: "none",
}, },
{ {
key: "clampDepth", key: "unclippedDepth",
converter: webidl.converters["boolean"], converter: webidl.converters["boolean"],
defaultValue: false, defaultValue: false,
}, },
@ -1458,13 +1503,7 @@
); );
// DICTIONARY: GPUCommandEncoderDescriptor // DICTIONARY: GPUCommandEncoderDescriptor
const dictMembersGPUCommandEncoderDescriptor = [ const dictMembersGPUCommandEncoderDescriptor = [];
{
key: "measureExecutionTime",
converter: webidl.converters["boolean"],
defaultValue: false,
},
];
webidl.converters["GPUCommandEncoderDescriptor"] = webidl webidl.converters["GPUCommandEncoderDescriptor"] = webidl
.createDictionaryConverter( .createDictionaryConverter(
"GPUCommandEncoderDescriptor", "GPUCommandEncoderDescriptor",

View file

@ -1,4 +1,4 @@
# Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. # Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
[package] [package]
name = "deno_webgpu" name = "deno_webgpu"
@ -7,15 +7,12 @@ authors = ["the Deno authors"]
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
repository = "https://github.com/denoland/deno" repository = "https://github.com/gfx-rs/wgpu"
description = "WebGPU implementation for Deno" description = "WebGPU implementation for Deno"
[lib]
path = "lib.rs"
[dependencies] [dependencies]
deno_core = { version = "0.114.0", path = "../../core" } deno_core = { version = "0.114.0", path = "../../core" }
serde = { version = "1.0.129", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.10.1", features = ["full"] } tokio = { version = "1.10", features = ["full"] }
wgpu-core = { version = "0.10.1", features = ["trace"] } wgpu-core = { git = "https://github.com/gfx-rs/wgpu", rev = "cdd480a89c9e3b681d9d174e65082d2bdbc903ef", features = ["trace", "replay", "serde"] }
wgpu-types = "0.10.0" wgpu-types = { git = "https://github.com/gfx-rs/wgpu", rev = "cdd480a89c9e3b681d9d174e65082d2bdbc903ef", features = ["trace", "replay", "serde"] }

20
ext/webgpu/LICENSE.md Normal file
View file

@ -0,0 +1,20 @@
MIT License
Copyright 2018-2021 the Deno authors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,791 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use crate::sampler::GpuCompareFunction;
use crate::texture::GpuTextureFormat;
use super::error::{WebGpuError, WebGpuResult};
const MAX_BIND_GROUPS: usize = 8;
pub(crate) struct WebGpuPipelineLayout(
pub(crate) wgpu_core::id::PipelineLayoutId,
);
impl Resource for WebGpuPipelineLayout {
fn name(&self) -> Cow<str> {
"webGPUPipelineLayout".into()
}
}
pub(crate) struct WebGpuComputePipeline(
pub(crate) wgpu_core::id::ComputePipelineId,
);
impl Resource for WebGpuComputePipeline {
fn name(&self) -> Cow<str> {
"webGPUComputePipeline".into()
}
}
pub(crate) struct WebGpuRenderPipeline(
pub(crate) wgpu_core::id::RenderPipelineId,
);
impl Resource for WebGpuRenderPipeline {
fn name(&self) -> Cow<str> {
"webGPURenderPipeline".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuIndexFormat {
Uint16,
Uint32,
}
impl From<GpuIndexFormat> for wgpu_types::IndexFormat {
fn from(value: GpuIndexFormat) -> wgpu_types::IndexFormat {
match value {
GpuIndexFormat::Uint16 => wgpu_types::IndexFormat::Uint16,
GpuIndexFormat::Uint32 => wgpu_types::IndexFormat::Uint32,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GPUStencilOperation {
Keep,
Zero,
Replace,
Invert,
IncrementClamp,
DecrementClamp,
IncrementWrap,
DecrementWrap,
}
impl From<GPUStencilOperation> for wgpu_types::StencilOperation {
fn from(value: GPUStencilOperation) -> wgpu_types::StencilOperation {
match value {
GPUStencilOperation::Keep => wgpu_types::StencilOperation::Keep,
GPUStencilOperation::Zero => wgpu_types::StencilOperation::Zero,
GPUStencilOperation::Replace => wgpu_types::StencilOperation::Replace,
GPUStencilOperation::Invert => wgpu_types::StencilOperation::Invert,
GPUStencilOperation::IncrementClamp => {
wgpu_types::StencilOperation::IncrementClamp
}
GPUStencilOperation::DecrementClamp => {
wgpu_types::StencilOperation::DecrementClamp
}
GPUStencilOperation::IncrementWrap => {
wgpu_types::StencilOperation::IncrementWrap
}
GPUStencilOperation::DecrementWrap => {
wgpu_types::StencilOperation::DecrementWrap
}
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuBlendFactor {
Zero,
One,
Src,
OneMinusSrc,
SrcAlpha,
OneMinusSrcAlpha,
Dst,
OneMinusDst,
DstAlpha,
OneMinusDstAlpha,
SrcAlphaSaturated,
Constant,
OneMinusConstant,
}
impl From<GpuBlendFactor> for wgpu_types::BlendFactor {
fn from(value: GpuBlendFactor) -> wgpu_types::BlendFactor {
match value {
GpuBlendFactor::Zero => wgpu_types::BlendFactor::Zero,
GpuBlendFactor::One => wgpu_types::BlendFactor::One,
GpuBlendFactor::Src => wgpu_types::BlendFactor::Src,
GpuBlendFactor::OneMinusSrc => wgpu_types::BlendFactor::OneMinusSrc,
GpuBlendFactor::SrcAlpha => wgpu_types::BlendFactor::SrcAlpha,
GpuBlendFactor::OneMinusSrcAlpha => {
wgpu_types::BlendFactor::OneMinusSrcAlpha
}
GpuBlendFactor::Dst => wgpu_types::BlendFactor::Dst,
GpuBlendFactor::OneMinusDst => wgpu_types::BlendFactor::OneMinusDst,
GpuBlendFactor::DstAlpha => wgpu_types::BlendFactor::DstAlpha,
GpuBlendFactor::OneMinusDstAlpha => {
wgpu_types::BlendFactor::OneMinusDstAlpha
}
GpuBlendFactor::SrcAlphaSaturated => {
wgpu_types::BlendFactor::SrcAlphaSaturated
}
GpuBlendFactor::Constant => wgpu_types::BlendFactor::Constant,
GpuBlendFactor::OneMinusConstant => {
wgpu_types::BlendFactor::OneMinusConstant
}
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuBlendOperation {
Add,
Subtract,
ReverseSubtract,
Min,
Max,
}
impl From<GpuBlendOperation> for wgpu_types::BlendOperation {
fn from(value: GpuBlendOperation) -> wgpu_types::BlendOperation {
match value {
GpuBlendOperation::Add => wgpu_types::BlendOperation::Add,
GpuBlendOperation::Subtract => wgpu_types::BlendOperation::Subtract,
GpuBlendOperation::ReverseSubtract => {
wgpu_types::BlendOperation::ReverseSubtract
}
GpuBlendOperation::Min => wgpu_types::BlendOperation::Min,
GpuBlendOperation::Max => wgpu_types::BlendOperation::Max,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuPrimitiveTopology {
PointList,
LineList,
LineStrip,
TriangleList,
TriangleStrip,
}
impl From<GpuPrimitiveTopology> for wgpu_types::PrimitiveTopology {
fn from(value: GpuPrimitiveTopology) -> wgpu_types::PrimitiveTopology {
match value {
GpuPrimitiveTopology::PointList => {
wgpu_types::PrimitiveTopology::PointList
}
GpuPrimitiveTopology::LineList => wgpu_types::PrimitiveTopology::LineList,
GpuPrimitiveTopology::LineStrip => {
wgpu_types::PrimitiveTopology::LineStrip
}
GpuPrimitiveTopology::TriangleList => {
wgpu_types::PrimitiveTopology::TriangleList
}
GpuPrimitiveTopology::TriangleStrip => {
wgpu_types::PrimitiveTopology::TriangleStrip
}
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuFrontFace {
Ccw,
Cw,
}
impl From<GpuFrontFace> for wgpu_types::FrontFace {
fn from(value: GpuFrontFace) -> wgpu_types::FrontFace {
match value {
GpuFrontFace::Ccw => wgpu_types::FrontFace::Ccw,
GpuFrontFace::Cw => wgpu_types::FrontFace::Cw,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuCullMode {
None,
Front,
Back,
}
impl From<GpuCullMode> for Option<wgpu_types::Face> {
fn from(value: GpuCullMode) -> Option<wgpu_types::Face> {
match value {
GpuCullMode::None => None,
GpuCullMode::Front => Some(wgpu_types::Face::Front),
GpuCullMode::Back => Some(wgpu_types::Face::Back),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuProgrammableStage {
module: ResourceId,
entry_point: String,
// constants: HashMap<String, GPUPipelineConstantValue>
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateComputePipelineArgs {
device_rid: ResourceId,
label: Option<String>,
layout: Option<ResourceId>,
compute: GpuProgrammableStage,
}
pub fn op_webgpu_create_compute_pipeline(
state: &mut OpState,
args: CreateComputePipelineArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let pipeline_layout = if let Some(rid) = args.layout {
let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
Some(id.0)
} else {
None
};
let compute_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(args.compute.module)?;
let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor {
label: args.label.map(Cow::from),
layout: pipeline_layout,
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: compute_shader_module_resource.0,
entry_point: Cow::from(args.compute.entry_point),
// TODO(lucacasonato): support args.compute.constants
},
};
let implicit_pipelines = match args.layout {
Some(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds {
root_id: std::marker::PhantomData,
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
}),
};
let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline(
device,
&descriptor,
std::marker::PhantomData,
implicit_pipelines
));
let rid = state
.resource_table
.add(WebGpuComputePipeline(compute_pipeline));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePipelineGetBindGroupLayoutArgs {
compute_pipeline_rid: ResourceId,
index: u32,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PipelineLayout {
rid: ResourceId,
label: String,
err: Option<WebGpuError>,
}
pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
state: &mut OpState,
args: ComputePipelineGetBindGroupLayoutArgs,
_: (),
) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>();
let compute_pipeline_resource = state
.resource_table
.get::<WebGpuComputePipeline>(args.compute_pipeline_rid)?;
let compute_pipeline = compute_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, args.index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));
let rid = state
.resource_table
.add(super::binding::WebGpuBindGroupLayout(bind_group_layout));
Ok(PipelineLayout {
rid,
label,
err: maybe_err.map(WebGpuError::from),
})
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuPrimitiveState {
topology: GpuPrimitiveTopology,
strip_index_format: Option<GpuIndexFormat>,
front_face: GpuFrontFace,
cull_mode: GpuCullMode,
clamp_depth: bool,
}
impl From<GpuPrimitiveState> for wgpu_types::PrimitiveState {
fn from(value: GpuPrimitiveState) -> wgpu_types::PrimitiveState {
wgpu_types::PrimitiveState {
topology: value.topology.into(),
strip_index_format: value.strip_index_format.map(Into::into),
front_face: value.front_face.into(),
cull_mode: value.cull_mode.into(),
clamp_depth: value.clamp_depth,
polygon_mode: Default::default(), // native-only
conservative: false, // native-only
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuBlendComponent {
src_factor: GpuBlendFactor,
dst_factor: GpuBlendFactor,
operation: GpuBlendOperation,
}
impl From<GpuBlendComponent> for wgpu_types::BlendComponent {
fn from(component: GpuBlendComponent) -> Self {
wgpu_types::BlendComponent {
src_factor: component.src_factor.into(),
dst_factor: component.dst_factor.into(),
operation: component.operation.into(),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuBlendState {
color: GpuBlendComponent,
alpha: GpuBlendComponent,
}
impl From<GpuBlendState> for wgpu_types::BlendState {
fn from(state: GpuBlendState) -> wgpu_types::BlendState {
wgpu_types::BlendState {
color: state.color.into(),
alpha: state.alpha.into(),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuColorTargetState {
format: GpuTextureFormat,
blend: Option<GpuBlendState>,
write_mask: u32,
}
impl TryFrom<GpuColorTargetState> for wgpu_types::ColorTargetState {
type Error = AnyError;
fn try_from(
state: GpuColorTargetState,
) -> Result<wgpu_types::ColorTargetState, AnyError> {
Ok(wgpu_types::ColorTargetState {
format: state.format.try_into()?,
blend: state.blend.map(Into::into),
write_mask: wgpu_types::ColorWrites::from_bits_truncate(state.write_mask),
})
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuStencilFaceState {
compare: GpuCompareFunction,
fail_op: GPUStencilOperation,
depth_fail_op: GPUStencilOperation,
pass_op: GPUStencilOperation,
}
impl From<GpuStencilFaceState> for wgpu_types::StencilFaceState {
fn from(state: GpuStencilFaceState) -> Self {
wgpu_types::StencilFaceState {
compare: state.compare.into(),
fail_op: state.fail_op.into(),
depth_fail_op: state.depth_fail_op.into(),
pass_op: state.pass_op.into(),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuDepthStencilState {
format: GpuTextureFormat,
depth_write_enabled: bool,
depth_compare: GpuCompareFunction,
stencil_front: GpuStencilFaceState,
stencil_back: GpuStencilFaceState,
stencil_read_mask: u32,
stencil_write_mask: u32,
depth_bias: i32,
depth_bias_slope_scale: f32,
depth_bias_clamp: f32,
}
impl TryFrom<GpuDepthStencilState> for wgpu_types::DepthStencilState {
type Error = AnyError;
fn try_from(
state: GpuDepthStencilState,
) -> Result<wgpu_types::DepthStencilState, AnyError> {
Ok(wgpu_types::DepthStencilState {
format: state.format.try_into()?,
depth_write_enabled: state.depth_write_enabled,
depth_compare: state.depth_compare.into(),
stencil: wgpu_types::StencilState {
front: state.stencil_front.into(),
back: state.stencil_back.into(),
read_mask: state.stencil_read_mask,
write_mask: state.stencil_write_mask,
},
bias: wgpu_types::DepthBiasState {
constant: state.depth_bias,
slope_scale: state.depth_bias_slope_scale,
clamp: state.depth_bias_clamp,
},
})
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexAttribute {
format: GpuVertexFormat,
offset: u64,
shader_location: u32,
}
impl From<GpuVertexAttribute> for wgpu_types::VertexAttribute {
fn from(attribute: GpuVertexAttribute) -> Self {
wgpu_types::VertexAttribute {
format: attribute.format.into(),
offset: attribute.offset,
shader_location: attribute.shader_location,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum GpuVertexFormat {
Uint8x2,
Uint8x4,
Sint8x2,
Sint8x4,
Unorm8x2,
Unorm8x4,
Snorm8x2,
Snorm8x4,
Uint16x2,
Uint16x4,
Sint16x2,
Sint16x4,
Unorm16x2,
Unorm16x4,
Snorm16x2,
Snorm16x4,
Float16x2,
Float16x4,
Float32,
Float32x2,
Float32x3,
Float32x4,
Uint32,
Uint32x2,
Uint32x3,
Uint32x4,
Sint32,
Sint32x2,
Sint32x3,
Sint32x4,
Float64,
Float64x2,
Float64x3,
Float64x4,
}
impl From<GpuVertexFormat> for wgpu_types::VertexFormat {
fn from(vf: GpuVertexFormat) -> wgpu_types::VertexFormat {
use wgpu_types::VertexFormat;
match vf {
GpuVertexFormat::Uint8x2 => VertexFormat::Uint8x2,
GpuVertexFormat::Uint8x4 => VertexFormat::Uint8x4,
GpuVertexFormat::Sint8x2 => VertexFormat::Sint8x2,
GpuVertexFormat::Sint8x4 => VertexFormat::Sint8x4,
GpuVertexFormat::Unorm8x2 => VertexFormat::Unorm8x2,
GpuVertexFormat::Unorm8x4 => VertexFormat::Unorm8x4,
GpuVertexFormat::Snorm8x2 => VertexFormat::Snorm8x2,
GpuVertexFormat::Snorm8x4 => VertexFormat::Snorm8x4,
GpuVertexFormat::Uint16x2 => VertexFormat::Uint16x2,
GpuVertexFormat::Uint16x4 => VertexFormat::Uint16x4,
GpuVertexFormat::Sint16x2 => VertexFormat::Sint16x2,
GpuVertexFormat::Sint16x4 => VertexFormat::Sint16x4,
GpuVertexFormat::Unorm16x2 => VertexFormat::Unorm16x2,
GpuVertexFormat::Unorm16x4 => VertexFormat::Unorm16x4,
GpuVertexFormat::Snorm16x2 => VertexFormat::Snorm16x2,
GpuVertexFormat::Snorm16x4 => VertexFormat::Snorm16x4,
GpuVertexFormat::Float16x2 => VertexFormat::Float16x2,
GpuVertexFormat::Float16x4 => VertexFormat::Float16x4,
GpuVertexFormat::Float32 => VertexFormat::Float32,
GpuVertexFormat::Float32x2 => VertexFormat::Float32x2,
GpuVertexFormat::Float32x3 => VertexFormat::Float32x3,
GpuVertexFormat::Float32x4 => VertexFormat::Float32x4,
GpuVertexFormat::Uint32 => VertexFormat::Uint32,
GpuVertexFormat::Uint32x2 => VertexFormat::Uint32x2,
GpuVertexFormat::Uint32x3 => VertexFormat::Uint32x3,
GpuVertexFormat::Uint32x4 => VertexFormat::Uint32x4,
GpuVertexFormat::Sint32 => VertexFormat::Sint32,
GpuVertexFormat::Sint32x2 => VertexFormat::Sint32x2,
GpuVertexFormat::Sint32x3 => VertexFormat::Sint32x3,
GpuVertexFormat::Sint32x4 => VertexFormat::Sint32x4,
GpuVertexFormat::Float64 => VertexFormat::Float64,
GpuVertexFormat::Float64x2 => VertexFormat::Float64x2,
GpuVertexFormat::Float64x3 => VertexFormat::Float64x3,
GpuVertexFormat::Float64x4 => VertexFormat::Float64x4,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
enum GpuVertexStepMode {
Vertex,
Instance,
}
impl From<GpuVertexStepMode> for wgpu_types::VertexStepMode {
fn from(vsm: GpuVertexStepMode) -> wgpu_types::VertexStepMode {
use wgpu_types::VertexStepMode;
match vsm {
GpuVertexStepMode::Vertex => VertexStepMode::Vertex,
GpuVertexStepMode::Instance => VertexStepMode::Instance,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexBufferLayout {
array_stride: u64,
step_mode: GpuVertexStepMode,
attributes: Vec<GpuVertexAttribute>,
}
impl<'a> From<GpuVertexBufferLayout>
for wgpu_core::pipeline::VertexBufferLayout<'a>
{
fn from(
layout: GpuVertexBufferLayout,
) -> wgpu_core::pipeline::VertexBufferLayout<'a> {
wgpu_core::pipeline::VertexBufferLayout {
array_stride: layout.array_stride,
step_mode: layout.step_mode.into(),
attributes: Cow::Owned(
layout.attributes.into_iter().map(Into::into).collect(),
),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexState {
module: ResourceId,
entry_point: String,
buffers: Vec<Option<GpuVertexBufferLayout>>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuMultisampleState {
count: u32,
mask: u64,
alpha_to_coverage_enabled: bool,
}
impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
fn from(gms: GpuMultisampleState) -> wgpu_types::MultisampleState {
wgpu_types::MultisampleState {
count: gms.count,
mask: gms.mask,
alpha_to_coverage_enabled: gms.alpha_to_coverage_enabled,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuFragmentState {
targets: Vec<GpuColorTargetState>,
module: u32,
entry_point: String,
// TODO(lucacasonato): constants
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateRenderPipelineArgs {
device_rid: ResourceId,
label: Option<String>,
layout: Option<ResourceId>,
vertex: GpuVertexState,
primitive: GpuPrimitiveState,
depth_stencil: Option<GpuDepthStencilState>,
multisample: GpuMultisampleState,
fragment: Option<GpuFragmentState>,
}
pub fn op_webgpu_create_render_pipeline(
state: &mut OpState,
args: CreateRenderPipelineArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let layout = if let Some(rid) = args.layout {
let pipeline_layout_resource =
state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
Some(pipeline_layout_resource.0)
} else {
None
};
let vertex_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(args.vertex.module)?;
let fragment = if let Some(fragment) = args.fragment {
let fragment_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(fragment.module)?;
let mut targets = Vec::with_capacity(fragment.targets.len());
for target in fragment.targets {
targets.push(target.try_into()?);
}
Some(wgpu_core::pipeline::FragmentState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: fragment_shader_module_resource.0,
entry_point: Cow::from(fragment.entry_point),
},
targets: Cow::from(targets),
})
} else {
None
};
let vertex_buffers = args
.vertex
.buffers
.into_iter()
.flatten()
.map(Into::into)
.collect();
let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor {
label: args.label.map(Cow::Owned),
layout,
vertex: wgpu_core::pipeline::VertexState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: vertex_shader_module_resource.0,
entry_point: Cow::Owned(args.vertex.entry_point),
},
buffers: Cow::Owned(vertex_buffers),
},
primitive: args.primitive.into(),
depth_stencil: args.depth_stencil.map(TryInto::try_into).transpose()?,
multisample: args.multisample.into(),
fragment,
};
let implicit_pipelines = match args.layout {
Some(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds {
root_id: std::marker::PhantomData,
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
}),
};
let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline(
device,
&descriptor,
std::marker::PhantomData,
implicit_pipelines
));
let rid = state
.resource_table
.add(WebGpuRenderPipeline(render_pipeline));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPipelineGetBindGroupLayoutArgs {
render_pipeline_rid: ResourceId,
index: u32,
}
pub fn op_webgpu_render_pipeline_get_bind_group_layout(
state: &mut OpState,
args: RenderPipelineGetBindGroupLayoutArgs,
_: (),
) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>();
let render_pipeline_resource = state
.resource_table
.get::<WebGpuRenderPipeline>(args.render_pipeline_rid)?;
let render_pipeline = render_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, args.index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));
let rid = state
.resource_table
.add(super::binding::WebGpuBindGroupLayout(bind_group_layout));
Ok(PipelineLayout {
rid,
label,
err: maybe_err.map(WebGpuError::from),
})
}

View file

@ -1,132 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use super::error::WebGpuResult;
pub(crate) struct WebGpuSampler(pub(crate) wgpu_core::id::SamplerId);
impl Resource for WebGpuSampler {
fn name(&self) -> Cow<str> {
"webGPUSampler".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuAddressMode {
ClampToEdge,
Repeat,
MirrorRepeat,
}
impl From<GpuAddressMode> for wgpu_types::AddressMode {
fn from(value: GpuAddressMode) -> wgpu_types::AddressMode {
match value {
GpuAddressMode::ClampToEdge => wgpu_types::AddressMode::ClampToEdge,
GpuAddressMode::Repeat => wgpu_types::AddressMode::Repeat,
GpuAddressMode::MirrorRepeat => wgpu_types::AddressMode::MirrorRepeat,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuFilterMode {
Nearest,
Linear,
}
impl From<GpuFilterMode> for wgpu_types::FilterMode {
fn from(value: GpuFilterMode) -> wgpu_types::FilterMode {
match value {
GpuFilterMode::Nearest => wgpu_types::FilterMode::Nearest,
GpuFilterMode::Linear => wgpu_types::FilterMode::Linear,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuCompareFunction {
Never,
Less,
Equal,
LessEqual,
Greater,
NotEqual,
GreaterEqual,
Always,
}
impl From<GpuCompareFunction> for wgpu_types::CompareFunction {
fn from(value: GpuCompareFunction) -> wgpu_types::CompareFunction {
match value {
GpuCompareFunction::Never => wgpu_types::CompareFunction::Never,
GpuCompareFunction::Less => wgpu_types::CompareFunction::Less,
GpuCompareFunction::Equal => wgpu_types::CompareFunction::Equal,
GpuCompareFunction::LessEqual => wgpu_types::CompareFunction::LessEqual,
GpuCompareFunction::Greater => wgpu_types::CompareFunction::Greater,
GpuCompareFunction::NotEqual => wgpu_types::CompareFunction::NotEqual,
GpuCompareFunction::GreaterEqual => {
wgpu_types::CompareFunction::GreaterEqual
}
GpuCompareFunction::Always => wgpu_types::CompareFunction::Always,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateSamplerArgs {
device_rid: ResourceId,
label: Option<String>,
address_mode_u: GpuAddressMode,
address_mode_v: GpuAddressMode,
address_mode_w: GpuAddressMode,
mag_filter: GpuFilterMode,
min_filter: GpuFilterMode,
mipmap_filter: GpuFilterMode,
lod_min_clamp: f32,
lod_max_clamp: f32,
compare: Option<GpuCompareFunction>,
max_anisotropy: u8,
}
pub fn op_webgpu_create_sampler(
state: &mut OpState,
args: CreateSamplerArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let descriptor = wgpu_core::resource::SamplerDescriptor {
label: args.label.map(Cow::from),
address_modes: [
args.address_mode_u.into(),
args.address_mode_v.into(),
args.address_mode_w.into(),
],
mag_filter: args.mag_filter.into(),
min_filter: args.min_filter.into(),
mipmap_filter: args.mipmap_filter.into(),
lod_min_clamp: args.lod_min_clamp,
lod_max_clamp: args.lod_max_clamp,
compare: args.compare.map(Into::into),
anisotropy_clamp: std::num::NonZeroU8::new(args.max_anisotropy),
border_color: None, // native-only
};
gfx_put!(device => instance.device_create_sampler(
device,
&descriptor,
std::marker::PhantomData
) => state, WebGpuSampler)
}

View file

@ -1,12 +1,11 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
use deno_core::{OpState, Resource}; use deno_core::{OpState, Resource};
use serde::Deserialize; use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use crate::texture::{GpuTextureFormat, GpuTextureViewDimension};
use super::error::WebGpuResult; use super::error::WebGpuResult;
@ -59,41 +58,14 @@ impl From<GpuBufferBindingType> for wgpu_types::BufferBindingType {
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuSamplerBindingLayout { struct GpuSamplerBindingLayout {
r#type: GpuSamplerBindingType, r#type: wgpu_types::SamplerBindingType,
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuSamplerBindingType {
Filtering,
NonFiltering,
Comparison,
}
impl From<GpuSamplerBindingType> for wgpu_types::BindingType {
fn from(binding_type: GpuSamplerBindingType) -> Self {
match binding_type {
GpuSamplerBindingType::Filtering => wgpu_types::BindingType::Sampler {
filtering: true,
comparison: false,
},
GpuSamplerBindingType::NonFiltering => wgpu_types::BindingType::Sampler {
filtering: false,
comparison: false,
},
GpuSamplerBindingType::Comparison => wgpu_types::BindingType::Sampler {
filtering: true,
comparison: true,
},
}
}
} }
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuTextureBindingLayout { struct GpuTextureBindingLayout {
sample_type: GpuTextureSampleType, sample_type: GpuTextureSampleType,
view_dimension: GpuTextureViewDimension, view_dimension: wgpu_types::TextureViewDimension,
multisampled: bool, multisampled: bool,
} }
@ -127,8 +99,8 @@ impl From<GpuTextureSampleType> for wgpu_types::TextureSampleType {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuStorageTextureBindingLayout { struct GpuStorageTextureBindingLayout {
access: GpuStorageTextureAccess, access: GpuStorageTextureAccess,
format: GpuTextureFormat, format: wgpu_types::TextureFormat,
view_dimension: GpuTextureViewDimension, view_dimension: wgpu_types::TextureViewDimension,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -177,17 +149,19 @@ impl TryFrom<GpuBindingType> for wgpu_types::BindingType {
has_dynamic_offset: buffer.has_dynamic_offset, has_dynamic_offset: buffer.has_dynamic_offset,
min_binding_size: std::num::NonZeroU64::new(buffer.min_binding_size), min_binding_size: std::num::NonZeroU64::new(buffer.min_binding_size),
}, },
GpuBindingType::Sampler(sampler) => sampler.r#type.into(), GpuBindingType::Sampler(sampler) => {
wgpu_types::BindingType::Sampler(sampler.r#type)
}
GpuBindingType::Texture(texture) => wgpu_types::BindingType::Texture { GpuBindingType::Texture(texture) => wgpu_types::BindingType::Texture {
sample_type: texture.sample_type.into(), sample_type: texture.sample_type.into(),
view_dimension: texture.view_dimension.into(), view_dimension: texture.view_dimension,
multisampled: texture.multisampled, multisampled: texture.multisampled,
}, },
GpuBindingType::StorageTexture(storage_texture) => { GpuBindingType::StorageTexture(storage_texture) => {
wgpu_types::BindingType::StorageTexture { wgpu_types::BindingType::StorageTexture {
access: storage_texture.access.into(), access: storage_texture.access.into(),
format: storage_texture.format.try_into()?, format: storage_texture.format,
view_dimension: storage_texture.view_dimension.into(), view_dimension: storage_texture.view_dimension,
} }
} }
}; };

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -9,9 +9,6 @@ use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use crate::pipeline::GpuIndexFormat;
use crate::texture::GpuTextureFormat;
use super::error::WebGpuResult; use super::error::WebGpuResult;
struct WebGpuRenderBundleEncoder( struct WebGpuRenderBundleEncoder(
@ -35,8 +32,8 @@ impl Resource for WebGpuRenderBundle {
pub struct CreateRenderBundleEncoderArgs { pub struct CreateRenderBundleEncoderArgs {
device_rid: ResourceId, device_rid: ResourceId,
label: Option<String>, label: Option<String>,
color_formats: Vec<GpuTextureFormat>, color_formats: Vec<wgpu_types::TextureFormat>,
depth_stencil_format: Option<GpuTextureFormat>, depth_stencil_format: Option<wgpu_types::TextureFormat>,
sample_count: u32, sample_count: u32,
depth_read_only: bool, depth_read_only: bool,
stencil_read_only: bool, stencil_read_only: bool,
@ -55,12 +52,12 @@ pub fn op_webgpu_create_render_bundle_encoder(
let mut color_formats = vec![]; let mut color_formats = vec![];
for format in args.color_formats { for format in args.color_formats {
color_formats.push(format.try_into()?); color_formats.push(format);
} }
let depth_stencil = if let Some(format) = args.depth_stencil_format { let depth_stencil = if let Some(format) = args.depth_stencil_format {
Some(wgpu_types::RenderBundleDepthStencil { Some(wgpu_types::RenderBundleDepthStencil {
format: format.try_into()?, format,
depth_read_only: args.depth_read_only, depth_read_only: args.depth_read_only,
stencil_read_only: args.stencil_read_only, stencil_read_only: args.stencil_read_only,
}) })
@ -73,6 +70,7 @@ pub fn op_webgpu_create_render_bundle_encoder(
color_formats: Cow::from(color_formats), color_formats: Cow::from(color_formats),
sample_count: args.sample_count, sample_count: args.sample_count,
depth_stencil, depth_stencil,
multiview: None,
}; };
let res = let res =
@ -301,7 +299,7 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline(
pub struct RenderBundleEncoderSetIndexBufferArgs { pub struct RenderBundleEncoderSetIndexBufferArgs {
render_bundle_encoder_rid: ResourceId, render_bundle_encoder_rid: ResourceId,
buffer: ResourceId, buffer: ResourceId,
index_format: GpuIndexFormat, index_format: wgpu_types::IndexFormat,
offset: u64, offset: u64,
size: u64, size: u64,
} }
@ -324,7 +322,7 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
.borrow_mut() .borrow_mut()
.set_index_buffer( .set_index_buffer(
buffer_resource.0, buffer_resource.0,
args.index_format.into(), args.index_format,
args.offset, args.offset,
std::num::NonZeroU64::new(args.size), std::num::NonZeroU64::new(args.size),
); );

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -8,8 +8,6 @@ use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use crate::texture::GpuTextureAspect;
use super::error::WebGpuResult; use super::error::WebGpuResult;
pub(crate) struct WebGpuCommandEncoder( pub(crate) struct WebGpuCommandEncoder(
@ -65,8 +63,8 @@ pub fn op_webgpu_create_command_encoder(
pub struct GpuRenderPassColorAttachment { pub struct GpuRenderPassColorAttachment {
view: ResourceId, view: ResourceId,
resolve_target: Option<ResourceId>, resolve_target: Option<ResourceId>,
load_op: GpuLoadOp<super::render_pass::GpuColor>, load_op: GpuLoadOp<wgpu_types::Color>,
store_op: GpuStoreOp, store_op: wgpu_core::command::StoreOp,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -76,31 +74,15 @@ enum GpuLoadOp<T> {
Clear(T), Clear(T),
} }
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuStoreOp {
Store,
Discard,
}
impl From<GpuStoreOp> for wgpu_core::command::StoreOp {
fn from(value: GpuStoreOp) -> wgpu_core::command::StoreOp {
match value {
GpuStoreOp::Store => wgpu_core::command::StoreOp::Store,
GpuStoreOp::Discard => wgpu_core::command::StoreOp::Discard,
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuRenderPassDepthStencilAttachment { struct GpuRenderPassDepthStencilAttachment {
view: ResourceId, view: ResourceId,
depth_load_op: GpuLoadOp<f32>, depth_load_op: GpuLoadOp<f32>,
depth_store_op: GpuStoreOp, depth_store_op: wgpu_core::command::StoreOp,
depth_read_only: bool, depth_read_only: bool,
stencil_load_op: GpuLoadOp<u32>, stencil_load_op: GpuLoadOp<u32>,
stencil_store_op: GpuStoreOp, stencil_store_op: wgpu_core::command::StoreOp,
stencil_read_only: bool, stencil_read_only: bool,
} }
@ -147,19 +129,14 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
channel: match color_attachment.load_op { channel: match color_attachment.load_op {
GpuLoadOp::Load => wgpu_core::command::PassChannel { GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load, load_op: wgpu_core::command::LoadOp::Load,
store_op: color_attachment.store_op.into(), store_op: color_attachment.store_op,
clear_value: Default::default(), clear_value: Default::default(),
read_only: false, read_only: false,
}, },
GpuLoadOp::Clear(color) => wgpu_core::command::PassChannel { GpuLoadOp::Clear(color) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear, load_op: wgpu_core::command::LoadOp::Clear,
store_op: color_attachment.store_op.into(), store_op: color_attachment.store_op,
clear_value: wgpu_types::Color { clear_value: color,
r: color.r,
g: color.g,
b: color.b,
a: color.a,
},
read_only: false, read_only: false,
}, },
}, },
@ -182,13 +159,13 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
depth: match attachment.depth_load_op { depth: match attachment.depth_load_op {
GpuLoadOp::Load => wgpu_core::command::PassChannel { GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load, load_op: wgpu_core::command::LoadOp::Load,
store_op: attachment.depth_store_op.into(), store_op: attachment.depth_store_op,
clear_value: 0.0, clear_value: 0.0,
read_only: attachment.depth_read_only, read_only: attachment.depth_read_only,
}, },
GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel { GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear, load_op: wgpu_core::command::LoadOp::Clear,
store_op: attachment.depth_store_op.into(), store_op: attachment.depth_store_op,
clear_value: value, clear_value: value,
read_only: attachment.depth_read_only, read_only: attachment.depth_read_only,
}, },
@ -196,13 +173,13 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
stencil: match attachment.stencil_load_op { stencil: match attachment.stencil_load_op {
GpuLoadOp::Load => wgpu_core::command::PassChannel { GpuLoadOp::Load => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Load, load_op: wgpu_core::command::LoadOp::Load,
store_op: attachment.stencil_store_op.into(), store_op: attachment.stencil_store_op,
clear_value: 0, clear_value: 0,
read_only: attachment.stencil_read_only, read_only: attachment.stencil_read_only,
}, },
GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel { GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel {
load_op: wgpu_core::command::LoadOp::Clear, load_op: wgpu_core::command::LoadOp::Clear,
store_op: attachment.stencil_store_op.into(), store_op: attachment.stencil_store_op,
clear_value: value, clear_value: value,
read_only: attachment.stencil_read_only, read_only: attachment.stencil_read_only,
}, },
@ -315,31 +292,13 @@ pub struct GpuImageCopyBuffer {
rows_per_image: Option<u32>, rows_per_image: Option<u32>,
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuOrigin3D {
pub x: u32,
pub y: u32,
pub z: u32,
}
impl From<GpuOrigin3D> for wgpu_types::Origin3d {
fn from(origin: GpuOrigin3D) -> wgpu_types::Origin3d {
wgpu_types::Origin3d {
x: origin.x,
y: origin.y,
z: origin.z,
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct GpuImageCopyTexture { pub struct GpuImageCopyTexture {
pub texture: ResourceId, pub texture: ResourceId,
pub mip_level: u32, pub mip_level: u32,
pub origin: GpuOrigin3D, pub origin: wgpu_types::Origin3d,
pub aspect: GpuTextureAspect, pub aspect: wgpu_types::TextureAspect,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -348,7 +307,7 @@ pub struct CommandEncoderCopyBufferToTextureArgs {
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
source: GpuImageCopyBuffer, source: GpuImageCopyBuffer,
destination: GpuImageCopyTexture, destination: GpuImageCopyTexture,
copy_size: super::texture::GpuExtent3D, copy_size: wgpu_types::Extent3d,
} }
pub fn op_webgpu_command_encoder_copy_buffer_to_texture( pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
@ -381,14 +340,14 @@ pub fn op_webgpu_command_encoder_copy_buffer_to_texture(
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0, texture: destination_texture_resource.0,
mip_level: args.destination.mip_level, mip_level: args.destination.mip_level,
origin: args.destination.origin.into(), origin: args.destination.origin,
aspect: args.destination.aspect.into(), aspect: args.destination.aspect,
}; };
gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture( gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size.into() &args.copy_size
)) ))
} }
@ -398,7 +357,7 @@ pub struct CommandEncoderCopyTextureToBufferArgs {
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
source: GpuImageCopyTexture, source: GpuImageCopyTexture,
destination: GpuImageCopyBuffer, destination: GpuImageCopyBuffer,
copy_size: super::texture::GpuExtent3D, copy_size: wgpu_types::Extent3d,
} }
pub fn op_webgpu_command_encoder_copy_texture_to_buffer( pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
@ -423,8 +382,8 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
let source = wgpu_core::command::ImageCopyTexture { let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0, texture: source_texture_resource.0,
mip_level: args.source.mip_level, mip_level: args.source.mip_level,
origin: args.source.origin.into(), origin: args.source.origin,
aspect: args.source.aspect.into(), aspect: args.source.aspect,
}; };
let destination = wgpu_core::command::ImageCopyBuffer { let destination = wgpu_core::command::ImageCopyBuffer {
buffer: destination_buffer_resource.0, buffer: destination_buffer_resource.0,
@ -442,7 +401,7 @@ pub fn op_webgpu_command_encoder_copy_texture_to_buffer(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size.into() &args.copy_size
)) ))
} }
@ -452,7 +411,7 @@ pub struct CommandEncoderCopyTextureToTextureArgs {
command_encoder_rid: ResourceId, command_encoder_rid: ResourceId,
source: GpuImageCopyTexture, source: GpuImageCopyTexture,
destination: GpuImageCopyTexture, destination: GpuImageCopyTexture,
copy_size: super::texture::GpuExtent3D, copy_size: wgpu_types::Extent3d,
} }
pub fn op_webgpu_command_encoder_copy_texture_to_texture( pub fn op_webgpu_command_encoder_copy_texture_to_texture(
@ -477,20 +436,51 @@ pub fn op_webgpu_command_encoder_copy_texture_to_texture(
let source = wgpu_core::command::ImageCopyTexture { let source = wgpu_core::command::ImageCopyTexture {
texture: source_texture_resource.0, texture: source_texture_resource.0,
mip_level: args.source.mip_level, mip_level: args.source.mip_level,
origin: args.source.origin.into(), origin: args.source.origin,
aspect: args.source.aspect.into(), aspect: args.source.aspect,
}; };
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: destination_texture_resource.0, texture: destination_texture_resource.0,
mip_level: args.destination.mip_level, mip_level: args.destination.mip_level,
origin: args.destination.origin.into(), origin: args.destination.origin,
aspect: args.destination.aspect.into(), aspect: args.destination.aspect,
}; };
gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture( gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture(
command_encoder, command_encoder,
&source, &source,
&destination, &destination,
&args.copy_size.into() &args.copy_size
))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommandEncoderClearBufferArgs {
command_encoder_rid: u32,
destination_rid: u32,
destination_offset: u64,
size: u64,
}
pub fn op_webgpu_command_encoder_clear_buffer(
state: &mut OpState,
args: CommandEncoderClearBufferArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let command_encoder_resource = state
.resource_table
.get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
let command_encoder = command_encoder_resource.0;
let destination_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(args.destination_rid)?;
gfx_ok!(command_encoder => instance.command_encoder_clear_buffer(
command_encoder,
destination_resource.0,
args.destination_offset,
std::num::NonZeroU64::new(args.size)
)) ))
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -125,10 +125,10 @@ pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query(
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(args.query_set)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query( wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
query_set_resource.0, query_set_resource.0,
args.query_index, args.query_index,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -149,8 +149,8 @@ pub fn op_webgpu_compute_pass_end_pipeline_statistics_query(
.get::<WebGpuComputePass>(args.compute_pass_rid)?; .get::<WebGpuComputePass>(args.compute_pass_rid)?;
wgpu_core::command::compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query( wgpu_core::command::compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query(
&mut compute_pass_resource.0.borrow_mut(), &mut compute_pass_resource.0.borrow_mut(),
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
use serde::Serialize; use serde::Serialize;
@ -8,6 +8,7 @@ use wgpu_core::binding_model::CreateBindGroupError;
use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreateBindGroupLayoutError;
use wgpu_core::binding_model::CreatePipelineLayoutError; use wgpu_core::binding_model::CreatePipelineLayoutError;
use wgpu_core::binding_model::GetBindGroupLayoutError; use wgpu_core::binding_model::GetBindGroupLayoutError;
use wgpu_core::command::ClearError;
use wgpu_core::command::CommandEncoderError; use wgpu_core::command::CommandEncoderError;
use wgpu_core::command::ComputePassError; use wgpu_core::command::ComputePassError;
use wgpu_core::command::CopyError; use wgpu_core::command::CopyError;
@ -258,6 +259,12 @@ impl From<QueueWriteError> for WebGpuError {
} }
} }
impl From<ClearError> for WebGpuError {
fn from(err: ClearError) -> Self {
WebGpuError::Validation(err.to_string())
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct DomExceptionOperationError { pub struct DomExceptionOperationError {
pub msg: String, pub msg: String,

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::include_js_files; use deno_core::include_js_files;
@ -14,7 +14,6 @@ use serde::Serialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
pub use wgpu_core; pub use wgpu_core;
pub use wgpu_types; pub use wgpu_types;
@ -125,15 +124,11 @@ pub fn init(unstable: bool) -> Extension {
.build() .build()
} }
pub fn get_declaration() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_webgpu.d.ts")
}
fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
let mut return_features: Vec<&'static str> = vec![]; let mut return_features: Vec<&'static str> = vec![];
if features.contains(wgpu_types::Features::DEPTH_CLAMPING) { if features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL) {
return_features.push("depth-clamping"); return_features.push("depth-clip-control");
} }
if features.contains(wgpu_types::Features::PIPELINE_STATISTICS_QUERY) { if features.contains(wgpu_types::Features::PIPELINE_STATISTICS_QUERY) {
return_features.push("pipeline-statistics-query"); return_features.push("pipeline-statistics-query");
@ -141,9 +136,18 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_BC) { if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_BC) {
return_features.push("texture-compression-bc"); return_features.push("texture-compression-bc");
} }
if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2) {
return_features.push("texture-compression-etc2");
}
if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR) {
return_features.push("texture-compression-astc");
}
if features.contains(wgpu_types::Features::TIMESTAMP_QUERY) { if features.contains(wgpu_types::Features::TIMESTAMP_QUERY) {
return_features.push("timestamp-query"); return_features.push("timestamp-query");
} }
if features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) {
return_features.push("indirect-first-instance");
}
// extended from spec // extended from spec
if features.contains(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS) { if features.contains(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS) {
@ -158,12 +162,16 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY) { if features.contains(wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY) {
return_features.push("storage-resource-binding-array"); return_features.push("storage-resource-binding-array");
} }
if features.contains(wgpu_types::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING) { if features.contains(
return_features.push("sampled-texture-and-storage-buffer-array-non-uniform-indexing"); wgpu_types::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
} ) {
if features.contains(wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING) { return_features.push("sampled-texture-and-storage-buffer-array-non-uniform-indexing");
return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"); }
} if features.contains(
wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
) {
return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing");
}
if features.contains(wgpu_types::Features::UNSIZED_BINDING_ARRAY) { if features.contains(wgpu_types::Features::UNSIZED_BINDING_ARRAY) {
return_features.push("unsized-binding-array"); return_features.push("unsized-binding-array");
} }
@ -179,15 +187,6 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) { if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) {
return_features.push("address-mode-clamp-to-border"); return_features.push("address-mode-clamp-to-border");
} }
if features.contains(wgpu_types::Features::NON_FILL_POLYGON_MODE) {
return_features.push("non-fill-polygon-mode");
}
if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2) {
return_features.push("texture-compression-etc2");
}
if features.contains(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR) {
return_features.push("texture-compression-astc-ldr");
}
if features if features
.contains(wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES) .contains(wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES)
{ {
@ -205,8 +204,8 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
if features.contains(wgpu_types::Features::VERTEX_WRITABLE_STORAGE) { if features.contains(wgpu_types::Features::VERTEX_WRITABLE_STORAGE) {
return_features.push("vertex-writable-storage"); return_features.push("vertex-writable-storage");
} }
if features.contains(wgpu_types::Features::CLEAR_COMMANDS) { if features.contains(wgpu_types::Features::CLEAR_TEXTURE) {
return_features.push("clear-commands"); return_features.push("clear-texture");
} }
if features.contains(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH) { if features.contains(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH) {
return_features.push("spirv-shader-passthrough"); return_features.push("spirv-shader-passthrough");
@ -218,28 +217,11 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
return_features return_features
} }
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
enum GpuPowerPreference {
LowPower,
HighPerformance,
}
impl From<GpuPowerPreference> for wgpu_types::PowerPreference {
fn from(value: GpuPowerPreference) -> wgpu_types::PowerPreference {
match value {
GpuPowerPreference::LowPower => wgpu_types::PowerPreference::LowPower,
GpuPowerPreference::HighPerformance => {
wgpu_types::PowerPreference::HighPerformance
}
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RequestAdapterArgs { pub struct RequestAdapterArgs {
power_preference: Option<GpuPowerPreference>, power_preference: Option<wgpu_types::PowerPreference>,
force_fallback_adapter: bool,
} }
#[derive(Serialize)] #[derive(Serialize)]
@ -266,31 +248,35 @@ pub async fn op_webgpu_request_adapter(
) -> Result<GpuAdapterDeviceOrErr, AnyError> { ) -> Result<GpuAdapterDeviceOrErr, AnyError> {
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
check_unstable(&state, "navigator.gpu.requestAdapter"); check_unstable(&state, "navigator.gpu.requestAdapter");
let backends = std::env::var("DENO_WEBGPU_BACKEND")
.ok()
.map_or_else(wgpu_types::Backends::all, |s| {
wgpu_core::instance::parse_backends_from_comma_list(&s)
});
let instance = if let Some(instance) = state.try_borrow::<Instance>() { let instance = if let Some(instance) = state.try_borrow::<Instance>() {
instance instance
} else { } else {
state.put(wgpu_core::hub::Global::new( state.put(wgpu_core::hub::Global::new(
"webgpu", "webgpu",
wgpu_core::hub::IdentityManagerFactory, wgpu_core::hub::IdentityManagerFactory,
wgpu_types::Backends::PRIMARY, backends,
)); ));
state.borrow::<Instance>() state.borrow::<Instance>()
}; };
let descriptor = wgpu_core::instance::RequestAdapterOptions { let descriptor = wgpu_core::instance::RequestAdapterOptions {
power_preference: match args.power_preference { power_preference: match args.power_preference {
Some(power_preference) => power_preference.into(), Some(power_preference) => power_preference,
None => PowerPreference::default(), None => PowerPreference::default(),
}, },
// TODO(lucacasonato): respect forceFallbackAdapter force_fallback_adapter: args.force_fallback_adapter,
compatible_surface: None, // windowless compatible_surface: None, // windowless
}; };
let res = instance.request_adapter( let res = instance.request_adapter(
&descriptor, &descriptor,
wgpu_core::instance::AdapterInputs::Mask( wgpu_core::instance::AdapterInputs::Mask(backends, |_| {
wgpu_types::Backends::PRIMARY, std::marker::PhantomData
|_| std::marker::PhantomData, }),
),
); );
let adapter = match res { let adapter = match res {
@ -319,116 +305,13 @@ pub async fn op_webgpu_request_adapter(
})) }))
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuLimits {
max_texture_dimension_1d: Option<u32>,
max_texture_dimension_2d: Option<u32>,
max_texture_dimension_3d: Option<u32>,
max_texture_array_layers: Option<u32>,
max_bind_groups: Option<u32>,
max_dynamic_uniform_buffers_per_pipeline_layout: Option<u32>,
max_dynamic_storage_buffers_per_pipeline_layout: Option<u32>,
max_sampled_textures_per_shader_stage: Option<u32>,
max_samplers_per_shader_stage: Option<u32>,
max_storage_buffers_per_shader_stage: Option<u32>,
max_storage_textures_per_shader_stage: Option<u32>,
max_uniform_buffers_per_shader_stage: Option<u32>,
max_uniform_buffer_binding_size: Option<u32>, // TODO(@crowlkats): u64
max_storage_buffer_binding_size: Option<u32>, // TODO(@crowlkats): u64
// min_uniform_buffer_offset_alignment: Option<u32>,
// min_storage_buffer_offset_alignment: Option<u32>,
max_vertex_buffers: Option<u32>,
max_vertex_attributes: Option<u32>,
max_vertex_buffer_array_stride: Option<u32>,
// max_inter_stage_shader_components: Option<u32>,
// max_compute_workgroup_storage_size: Option<u32>,
// max_compute_invocations_per_workgroup: Option<u32>,
// max_compute_workgroup_size_x: Option<u32>,
// max_compute_workgroup_size_y: Option<u32>,
// max_compute_workgroup_size_z: Option<u32>,
// max_compute_workgroups_per_dimension: Option<u32>,
}
impl From<GpuLimits> for wgpu_types::Limits {
fn from(limits: GpuLimits) -> wgpu_types::Limits {
wgpu_types::Limits {
max_texture_dimension_1d: limits.max_texture_dimension_1d.unwrap_or(8192),
max_texture_dimension_2d: limits.max_texture_dimension_2d.unwrap_or(8192),
max_texture_dimension_3d: limits.max_texture_dimension_3d.unwrap_or(2048),
max_texture_array_layers: limits.max_texture_array_layers.unwrap_or(2048),
max_bind_groups: limits.max_bind_groups.unwrap_or(4),
max_dynamic_uniform_buffers_per_pipeline_layout: limits
.max_dynamic_uniform_buffers_per_pipeline_layout
.unwrap_or(8),
max_dynamic_storage_buffers_per_pipeline_layout: limits
.max_dynamic_storage_buffers_per_pipeline_layout
.unwrap_or(4),
max_sampled_textures_per_shader_stage: limits
.max_sampled_textures_per_shader_stage
.unwrap_or(16),
max_samplers_per_shader_stage: limits
.max_samplers_per_shader_stage
.unwrap_or(16),
max_storage_buffers_per_shader_stage: limits
.max_storage_buffers_per_shader_stage
.unwrap_or(4),
max_storage_textures_per_shader_stage: limits
.max_storage_textures_per_shader_stage
.unwrap_or(4),
max_uniform_buffers_per_shader_stage: limits
.max_uniform_buffers_per_shader_stage
.unwrap_or(12),
max_uniform_buffer_binding_size: limits
.max_uniform_buffer_binding_size
.unwrap_or(16384),
max_storage_buffer_binding_size: limits
.max_storage_buffer_binding_size
.unwrap_or(134217728),
// min_uniform_buffer_offset_alignment: limits
// .min_uniform_buffer_offset_alignment
// .unwrap_or(default),
// min_storage_buffer_offset_alignment: limits
// .min_storage_buffer_offset_alignment
// .unwrap_or(default),
max_vertex_buffers: limits.max_vertex_buffers.unwrap_or(8),
max_vertex_attributes: limits.max_vertex_attributes.unwrap_or(16),
max_vertex_buffer_array_stride: limits
.max_vertex_buffer_array_stride
.unwrap_or(2048),
// max_inter_stage_shader_components: limits
// .max_inter_stage_shader_components
// .unwrap_or(default),
// max_compute_workgroup_storage_size: limits
// .max_compute_workgroup_storage_size
// .unwrap_or(default),
// max_compute_invocations_per_workgroup: limits
// .max_compute_invocations_per_workgroup
// .unwrap_or(default),
// max_compute_workgroup_size_x: limits
// .max_compute_workgroup_size_x
// .unwrap_or(default),
// max_compute_workgroup_size_y: limits
// .max_compute_workgroup_size_y
// .unwrap_or(default),
// max_compute_workgroup_size_z: limits
// .max_compute_workgroup_size_z
// .unwrap_or(default),
// max_compute_workgroups_per_dimension: limits
// .max_compute_workgroups_per_dimension
// .unwrap_or(default),
max_push_constant_size: 0,
}
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RequestDeviceArgs { pub struct RequestDeviceArgs {
adapter_rid: ResourceId, adapter_rid: ResourceId,
label: Option<String>, label: Option<String>,
required_features: Option<GpuRequiredFeatures>, required_features: Option<GpuRequiredFeatures>,
required_limits: Option<GpuLimits>, required_limits: Option<wgpu_types::Limits>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -437,101 +320,120 @@ pub struct GpuRequiredFeatures(HashSet<String>);
impl From<GpuRequiredFeatures> for wgpu_types::Features { impl From<GpuRequiredFeatures> for wgpu_types::Features {
fn from(required_features: GpuRequiredFeatures) -> wgpu_types::Features { fn from(required_features: GpuRequiredFeatures) -> wgpu_types::Features {
let mut features: wgpu_types::Features = wgpu_types::Features::empty(); let mut features: wgpu_types::Features = wgpu_types::Features::empty();
features.set(
if required_features.0.contains("depth-clamping") { wgpu_types::Features::DEPTH_CLIP_CONTROL,
features.set(wgpu_types::Features::DEPTH_CLAMPING, true); required_features.0.contains("depth-clip-control"),
} );
if required_features.0.contains("pipeline-statistics-query") { features.set(
features.set(wgpu_types::Features::PIPELINE_STATISTICS_QUERY, true); wgpu_types::Features::PIPELINE_STATISTICS_QUERY,
} required_features.0.contains("pipeline-statistics-query"),
if required_features.0.contains("texture-compression-bc") { );
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_BC, true); features.set(
} wgpu_types::Features::TEXTURE_COMPRESSION_BC,
if required_features.0.contains("timestamp-query") { required_features.0.contains("texture-compression-bc"),
features.set(wgpu_types::Features::TIMESTAMP_QUERY, true); );
} features.set(
wgpu_types::Features::TEXTURE_COMPRESSION_ETC2,
required_features.0.contains("texture-compression-etc2"),
);
features.set(
wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR,
required_features.0.contains("texture-compression-astc"),
);
features.set(
wgpu_types::Features::TIMESTAMP_QUERY,
required_features.0.contains("timestamp-query"),
);
features.set(
wgpu_types::Features::INDIRECT_FIRST_INSTANCE,
required_features.0.contains("indirect-first-instance"),
);
// extended from spec // extended from spec
if required_features.0.contains("mappable-primary-buffers") { features.set(
features.set(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS, true); wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS,
} required_features.0.contains("mappable-primary-buffers"),
if required_features.0.contains("texture-binding-array") { );
features.set(wgpu_types::Features::TEXTURE_BINDING_ARRAY, true); features.set(
} wgpu_types::Features::TEXTURE_BINDING_ARRAY,
if required_features.0.contains("buffer-binding-array") { required_features.0.contains("texture-binding-array"),
features.set(wgpu_types::Features::BUFFER_BINDING_ARRAY, true); );
} features.set(
if required_features wgpu_types::Features::BUFFER_BINDING_ARRAY,
.0 required_features.0.contains("buffer-binding-array"),
.contains("storage-resource-binding-array") );
{ features.set(
features.set(wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY, true); wgpu_types::Features::STORAGE_RESOURCE_BINDING_ARRAY,
} required_features
if required_features .0
.0 .contains("storage-resource-binding-array"),
.contains("sampled-texture-and-storage-buffer-array-non-uniform-indexing") );
{ features.set(
features.set(wgpu_types::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, true); wgpu_types::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
} required_features
if required_features.0.contains( .0
"uniform-buffer-and-storage-buffer-texture-non-uniform-indexing", .contains("sampled-texture-and-storage-buffer-array-non-uniform-indexing"),
) { );
features.set(wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, true); features.set(
} wgpu_types::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
if required_features.0.contains("unsized-binding-array") { required_features
features.set(wgpu_types::Features::UNSIZED_BINDING_ARRAY, true); .0
} .contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"),
if required_features.0.contains("multi-draw-indirect") { );
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT, true); features.set(
} wgpu_types::Features::UNSIZED_BINDING_ARRAY,
if required_features.0.contains("multi-draw-indirect-count") { required_features.0.contains("unsized-binding-array"),
features.set(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT, true); );
} features.set(
if required_features.0.contains("push-constants") { wgpu_types::Features::MULTI_DRAW_INDIRECT,
features.set(wgpu_types::Features::PUSH_CONSTANTS, true); required_features.0.contains("multi-draw-indirect"),
} );
if required_features.0.contains("address-mode-clamp-to-border") { features.set(
features.set(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, true); wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT,
} required_features.0.contains("multi-draw-indirect-count"),
if required_features.0.contains("non-fill-polygon-mode") { );
features.set(wgpu_types::Features::NON_FILL_POLYGON_MODE, true); features.set(
} wgpu_types::Features::PUSH_CONSTANTS,
if required_features.0.contains("texture-compression-etc2") { required_features.0.contains("push-constants"),
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ETC2, true); );
} features.set(
if required_features.0.contains("texture-compression-astc-ldr") { wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
features.set(wgpu_types::Features::TEXTURE_COMPRESSION_ASTC_LDR, true); required_features.0.contains("address-mode-clamp-to-border"),
} );
if required_features features.set(
.0 wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
.contains("texture-adapter-specific-format-features") required_features
{ .0
features.set( .contains("texture-adapter-specific-format-features"),
wgpu_types::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, );
true, features.set(
); wgpu_types::Features::SHADER_FLOAT64,
} required_features.0.contains("shader-float64"),
if required_features.0.contains("shader-float64") { );
features.set(wgpu_types::Features::SHADER_FLOAT64, true); features.set(
} wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT,
if required_features.0.contains("vertex-attribute-64bit") { required_features.0.contains("vertex-attribute-64bit"),
features.set(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, true); );
} features.set(
if required_features.0.contains("conservative-rasterization") { wgpu_types::Features::CONSERVATIVE_RASTERIZATION,
features.set(wgpu_types::Features::CONSERVATIVE_RASTERIZATION, true); required_features.0.contains("conservative-rasterization"),
} );
if required_features.0.contains("vertex-writable-storage") { features.set(
features.set(wgpu_types::Features::VERTEX_WRITABLE_STORAGE, true); wgpu_types::Features::VERTEX_WRITABLE_STORAGE,
} required_features.0.contains("vertex-writable-storage"),
if required_features.0.contains("clear-commands") { );
features.set(wgpu_types::Features::CLEAR_COMMANDS, true); features.set(
} wgpu_types::Features::CLEAR_TEXTURE,
if required_features.0.contains("spirv-shader-passthrough") { required_features.0.contains("clear-commands"),
features.set(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH, true); );
} features.set(
if required_features.0.contains("shader-primitive-index") { wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH,
features.set(wgpu_types::Features::SHADER_PRIMITIVE_INDEX, true); required_features.0.contains("spirv-shader-passthrough"),
} );
features.set(
wgpu_types::Features::SHADER_PRIMITIVE_INDEX,
required_features.0.contains("shader-primitive-index"),
);
features features
} }
@ -775,6 +677,10 @@ fn declare_webgpu_ops() -> Vec<(&'static str, Box<OpFn>)> {
command_encoder::op_webgpu_command_encoder_copy_texture_to_texture, command_encoder::op_webgpu_command_encoder_copy_texture_to_texture,
), ),
), ),
(
"op_webgpu_command_encoder_clear_buffer",
op_sync(command_encoder::op_webgpu_command_encoder_clear_buffer),
),
( (
"op_webgpu_command_encoder_push_debug_group", "op_webgpu_command_encoder_push_debug_group",
op_sync(command_encoder::op_webgpu_command_encoder_push_debug_group), op_sync(command_encoder::op_webgpu_command_encoder_push_debug_group),
@ -895,6 +801,22 @@ fn declare_webgpu_ops() -> Vec<(&'static str, Box<OpFn>)> {
"op_webgpu_compute_pass_dispatch_indirect", "op_webgpu_compute_pass_dispatch_indirect",
op_sync(compute_pass::op_webgpu_compute_pass_dispatch_indirect), op_sync(compute_pass::op_webgpu_compute_pass_dispatch_indirect),
), ),
(
"op_webgpu_compute_pass_begin_pipeline_statistics_query",
op_sync(
compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query,
),
),
(
"op_webgpu_compute_pass_end_pipeline_statistics_query",
op_sync(
compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query,
),
),
(
"op_webgpu_compute_pass_write_timestamp",
op_sync(compute_pass::op_webgpu_compute_pass_write_timestamp),
),
( (
"op_webgpu_compute_pass_end_pass", "op_webgpu_compute_pass_end_pass",
op_sync(compute_pass::op_webgpu_compute_pass_end_pass), op_sync(compute_pass::op_webgpu_compute_pass_end_pass),

431
ext/webgpu/src/pipeline.rs Normal file
View file

@ -0,0 +1,431 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
use super::error::WebGpuError;
use super::error::WebGpuResult;
const MAX_BIND_GROUPS: usize = 8;
pub(crate) struct WebGpuPipelineLayout(
pub(crate) wgpu_core::id::PipelineLayoutId,
);
impl Resource for WebGpuPipelineLayout {
fn name(&self) -> Cow<str> {
"webGPUPipelineLayout".into()
}
}
pub(crate) struct WebGpuComputePipeline(
pub(crate) wgpu_core::id::ComputePipelineId,
);
impl Resource for WebGpuComputePipeline {
fn name(&self) -> Cow<str> {
"webGPUComputePipeline".into()
}
}
pub(crate) struct WebGpuRenderPipeline(
pub(crate) wgpu_core::id::RenderPipelineId,
);
impl Resource for WebGpuRenderPipeline {
fn name(&self) -> Cow<str> {
"webGPURenderPipeline".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuProgrammableStage {
module: ResourceId,
entry_point: String,
// constants: HashMap<String, GPUPipelineConstantValue>
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateComputePipelineArgs {
device_rid: ResourceId,
label: Option<String>,
layout: Option<ResourceId>,
compute: GpuProgrammableStage,
}
pub fn op_webgpu_create_compute_pipeline(
state: &mut OpState,
args: CreateComputePipelineArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let pipeline_layout = if let Some(rid) = args.layout {
let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
Some(id.0)
} else {
None
};
let compute_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(args.compute.module)?;
let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor {
label: args.label.map(Cow::from),
layout: pipeline_layout,
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: compute_shader_module_resource.0,
entry_point: Cow::from(args.compute.entry_point),
// TODO(lucacasonato): support args.compute.constants
},
};
let implicit_pipelines = match args.layout {
Some(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds {
root_id: std::marker::PhantomData,
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
}),
};
let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline(
device,
&descriptor,
std::marker::PhantomData,
implicit_pipelines
));
let rid = state
.resource_table
.add(WebGpuComputePipeline(compute_pipeline));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ComputePipelineGetBindGroupLayoutArgs {
compute_pipeline_rid: ResourceId,
index: u32,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PipelineLayout {
rid: ResourceId,
label: String,
err: Option<WebGpuError>,
}
pub fn op_webgpu_compute_pipeline_get_bind_group_layout(
state: &mut OpState,
args: ComputePipelineGetBindGroupLayoutArgs,
_: (),
) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>();
let compute_pipeline_resource = state
.resource_table
.get::<WebGpuComputePipeline>(args.compute_pipeline_rid)?;
let compute_pipeline = compute_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, args.index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));
let rid = state
.resource_table
.add(super::binding::WebGpuBindGroupLayout(bind_group_layout));
Ok(PipelineLayout {
rid,
label,
err: maybe_err.map(WebGpuError::from),
})
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuCullMode {
None,
Front,
Back,
}
impl From<GpuCullMode> for Option<wgpu_types::Face> {
fn from(value: GpuCullMode) -> Option<wgpu_types::Face> {
match value {
GpuCullMode::None => None,
GpuCullMode::Front => Some(wgpu_types::Face::Front),
GpuCullMode::Back => Some(wgpu_types::Face::Back),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuPrimitiveState {
topology: wgpu_types::PrimitiveTopology,
strip_index_format: Option<wgpu_types::IndexFormat>,
front_face: wgpu_types::FrontFace,
cull_mode: GpuCullMode,
unclipped_depth: bool,
}
impl From<GpuPrimitiveState> for wgpu_types::PrimitiveState {
fn from(value: GpuPrimitiveState) -> wgpu_types::PrimitiveState {
wgpu_types::PrimitiveState {
topology: value.topology,
strip_index_format: value.strip_index_format,
front_face: value.front_face,
cull_mode: value.cull_mode.into(),
unclipped_depth: value.unclipped_depth,
polygon_mode: Default::default(), // native-only
conservative: false, // native-only
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuDepthStencilState {
format: wgpu_types::TextureFormat,
depth_write_enabled: bool,
depth_compare: wgpu_types::CompareFunction,
stencil_front: wgpu_types::StencilFaceState,
stencil_back: wgpu_types::StencilFaceState,
stencil_read_mask: u32,
stencil_write_mask: u32,
depth_bias: i32,
depth_bias_slope_scale: f32,
depth_bias_clamp: f32,
}
impl TryFrom<GpuDepthStencilState> for wgpu_types::DepthStencilState {
type Error = AnyError;
fn try_from(
state: GpuDepthStencilState,
) -> Result<wgpu_types::DepthStencilState, AnyError> {
Ok(wgpu_types::DepthStencilState {
format: state.format,
depth_write_enabled: state.depth_write_enabled,
depth_compare: state.depth_compare,
stencil: wgpu_types::StencilState {
front: state.stencil_front,
back: state.stencil_back,
read_mask: state.stencil_read_mask,
write_mask: state.stencil_write_mask,
},
bias: wgpu_types::DepthBiasState {
constant: state.depth_bias,
slope_scale: state.depth_bias_slope_scale,
clamp: state.depth_bias_clamp,
},
})
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexBufferLayout {
array_stride: u64,
step_mode: wgpu_types::VertexStepMode,
attributes: Vec<wgpu_types::VertexAttribute>,
}
impl<'a> From<GpuVertexBufferLayout>
for wgpu_core::pipeline::VertexBufferLayout<'a>
{
fn from(
layout: GpuVertexBufferLayout,
) -> wgpu_core::pipeline::VertexBufferLayout<'a> {
wgpu_core::pipeline::VertexBufferLayout {
array_stride: layout.array_stride,
step_mode: layout.step_mode,
attributes: Cow::Owned(layout.attributes),
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuVertexState {
module: ResourceId,
entry_point: String,
buffers: Vec<Option<GpuVertexBufferLayout>>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuMultisampleState {
count: u32,
mask: u64,
alpha_to_coverage_enabled: bool,
}
impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
fn from(gms: GpuMultisampleState) -> wgpu_types::MultisampleState {
wgpu_types::MultisampleState {
count: gms.count,
mask: gms.mask,
alpha_to_coverage_enabled: gms.alpha_to_coverage_enabled,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct GpuFragmentState {
targets: Vec<wgpu_types::ColorTargetState>,
module: u32,
entry_point: String,
// TODO(lucacasonato): constants
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateRenderPipelineArgs {
device_rid: ResourceId,
label: Option<String>,
layout: Option<ResourceId>,
vertex: GpuVertexState,
primitive: GpuPrimitiveState,
depth_stencil: Option<GpuDepthStencilState>,
multisample: wgpu_types::MultisampleState,
fragment: Option<GpuFragmentState>,
}
pub fn op_webgpu_create_render_pipeline(
state: &mut OpState,
args: CreateRenderPipelineArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let layout = if let Some(rid) = args.layout {
let pipeline_layout_resource =
state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
Some(pipeline_layout_resource.0)
} else {
None
};
let vertex_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(args.vertex.module)?;
let fragment = if let Some(fragment) = args.fragment {
let fragment_shader_module_resource =
state
.resource_table
.get::<super::shader::WebGpuShaderModule>(fragment.module)?;
let mut targets = Vec::with_capacity(fragment.targets.len());
for target in fragment.targets {
targets.push(target);
}
Some(wgpu_core::pipeline::FragmentState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: fragment_shader_module_resource.0,
entry_point: Cow::from(fragment.entry_point),
},
targets: Cow::from(targets),
})
} else {
None
};
let vertex_buffers = args
.vertex
.buffers
.into_iter()
.flatten()
.map(Into::into)
.collect();
let descriptor = wgpu_core::pipeline::RenderPipelineDescriptor {
label: args.label.map(Cow::Owned),
layout,
vertex: wgpu_core::pipeline::VertexState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: vertex_shader_module_resource.0,
entry_point: Cow::Owned(args.vertex.entry_point),
},
buffers: Cow::Owned(vertex_buffers),
},
primitive: args.primitive.into(),
depth_stencil: args.depth_stencil.map(TryInto::try_into).transpose()?,
multisample: args.multisample,
fragment,
multiview: None,
};
let implicit_pipelines = match args.layout {
Some(_) => None,
None => Some(wgpu_core::device::ImplicitPipelineIds {
root_id: std::marker::PhantomData,
group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS],
}),
};
let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline(
device,
&descriptor,
std::marker::PhantomData,
implicit_pipelines
));
let rid = state
.resource_table
.add(WebGpuRenderPipeline(render_pipeline));
Ok(WebGpuResult::rid_err(rid, maybe_err))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RenderPipelineGetBindGroupLayoutArgs {
render_pipeline_rid: ResourceId,
index: u32,
}
pub fn op_webgpu_render_pipeline_get_bind_group_layout(
state: &mut OpState,
args: RenderPipelineGetBindGroupLayoutArgs,
_: (),
) -> Result<PipelineLayout, AnyError> {
let instance = state.borrow::<super::Instance>();
let render_pipeline_resource = state
.resource_table
.get::<WebGpuRenderPipeline>(args.render_pipeline_rid)?;
let render_pipeline = render_pipeline_resource.0;
let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, args.index, std::marker::PhantomData));
let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout));
let rid = state
.resource_table
.add(super::binding::WebGpuBindGroupLayout(bind_group_layout));
Ok(PipelineLayout {
rid,
label,
err: maybe_err.map(WebGpuError::from),
})
}

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use std::num::NonZeroU32; use std::num::NonZeroU32;
@ -108,7 +108,7 @@ pub struct QueueWriteTextureArgs {
queue_rid: ResourceId, queue_rid: ResourceId,
destination: super::command_encoder::GpuImageCopyTexture, destination: super::command_encoder::GpuImageCopyTexture,
data_layout: GpuImageDataLayout, data_layout: GpuImageDataLayout,
size: super::texture::GpuExtent3D, size: wgpu_types::Extent3d,
} }
pub fn op_webgpu_write_texture( pub fn op_webgpu_write_texture(
@ -127,8 +127,8 @@ pub fn op_webgpu_write_texture(
let destination = wgpu_core::command::ImageCopyTexture { let destination = wgpu_core::command::ImageCopyTexture {
texture: texture_resource.0, texture: texture_resource.0,
mip_level: args.destination.mip_level, mip_level: args.destination.mip_level,
origin: args.destination.origin.into(), origin: args.destination.origin,
aspect: args.destination.aspect.into(), aspect: args.destination.aspect,
}; };
let data_layout = args.data_layout.into(); let data_layout = args.data_layout.into();
@ -137,6 +137,6 @@ pub fn op_webgpu_write_texture(
&destination, &destination,
&*zero_copy, &*zero_copy,
&data_layout, &data_layout,
&args.size.into() &args.size
)) ))
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error; use deno_core::error::type_error;
use deno_core::error::AnyError; use deno_core::error::AnyError;
@ -9,8 +9,6 @@ use serde::Deserialize;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use crate::pipeline::GpuIndexFormat;
use super::error::WebGpuResult; use super::error::WebGpuResult;
pub(crate) struct WebGpuRenderPass( pub(crate) struct WebGpuRenderPass(
@ -86,20 +84,11 @@ pub fn op_webgpu_render_pass_set_scissor_rect(
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuColor {
pub r: f64,
pub g: f64,
pub b: f64,
pub a: f64,
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RenderPassSetBlendConstantArgs { pub struct RenderPassSetBlendConstantArgs {
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
color: GpuColor, color: wgpu_types::Color,
} }
pub fn op_webgpu_render_pass_set_blend_constant( pub fn op_webgpu_render_pass_set_blend_constant(
@ -113,12 +102,7 @@ pub fn op_webgpu_render_pass_set_blend_constant(
wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant( wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
&wgpu_types::Color { &args.color,
r: args.color.r,
g: args.color.g,
b: args.color.b,
a: args.color.a,
},
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
@ -169,10 +153,10 @@ pub fn op_webgpu_render_pass_begin_pipeline_statistics_query(
.get::<super::WebGpuQuerySet>(args.query_set)?; .get::<super::WebGpuQuerySet>(args.query_set)?;
wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query( wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
query_set_resource.0, query_set_resource.0,
args.query_index, args.query_index,
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -193,8 +177,8 @@ pub fn op_webgpu_render_pass_end_pipeline_statistics_query(
.get::<WebGpuRenderPass>(args.render_pass_rid)?; .get::<WebGpuRenderPass>(args.render_pass_rid)?;
wgpu_core::command::render_ffi::wgpu_render_pass_end_pipeline_statistics_query( wgpu_core::command::render_ffi::wgpu_render_pass_end_pipeline_statistics_query(
&mut render_pass_resource.0.borrow_mut(), &mut render_pass_resource.0.borrow_mut(),
); );
Ok(WebGpuResult::empty()) Ok(WebGpuResult::empty())
} }
@ -466,7 +450,7 @@ pub fn op_webgpu_render_pass_set_pipeline(
pub struct RenderPassSetIndexBufferArgs { pub struct RenderPassSetIndexBufferArgs {
render_pass_rid: ResourceId, render_pass_rid: ResourceId,
buffer: u32, buffer: u32,
index_format: GpuIndexFormat, index_format: wgpu_types::IndexFormat,
offset: u64, offset: u64,
size: Option<u64>, size: Option<u64>,
} }
@ -494,7 +478,7 @@ pub fn op_webgpu_render_pass_set_index_buffer(
render_pass_resource.0.borrow_mut().set_index_buffer( render_pass_resource.0.borrow_mut().set_index_buffer(
buffer_resource.0, buffer_resource.0,
args.index_format.into(), args.index_format,
args.offset, args.offset,
size, size,
); );

68
ext/webgpu/src/sampler.rs Normal file
View file

@ -0,0 +1,68 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use super::error::WebGpuResult;
pub(crate) struct WebGpuSampler(pub(crate) wgpu_core::id::SamplerId);
impl Resource for WebGpuSampler {
fn name(&self) -> Cow<str> {
"webGPUSampler".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateSamplerArgs {
device_rid: ResourceId,
label: Option<String>,
address_mode_u: wgpu_types::AddressMode,
address_mode_v: wgpu_types::AddressMode,
address_mode_w: wgpu_types::AddressMode,
mag_filter: wgpu_types::FilterMode,
min_filter: wgpu_types::FilterMode,
mipmap_filter: wgpu_types::FilterMode,
lod_min_clamp: f32,
lod_max_clamp: f32,
compare: Option<wgpu_types::CompareFunction>,
max_anisotropy: u8,
}
pub fn op_webgpu_create_sampler(
state: &mut OpState,
args: CreateSamplerArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let descriptor = wgpu_core::resource::SamplerDescriptor {
label: args.label.map(Cow::from),
address_modes: [
args.address_mode_u,
args.address_mode_v,
args.address_mode_w,
],
mag_filter: args.mag_filter,
min_filter: args.min_filter,
mipmap_filter: args.mipmap_filter,
lod_min_clamp: args.lod_min_clamp,
lod_max_clamp: args.lod_max_clamp,
compare: args.compare,
anisotropy_clamp: std::num::NonZeroU8::new(args.max_anisotropy),
border_color: None, // native-only
};
gfx_put!(device => instance.device_create_sampler(
device,
&descriptor,
std::marker::PhantomData
) => state, WebGpuSampler)
}

View file

@ -1,4 +1,4 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ResourceId; use deno_core::ResourceId;
@ -40,6 +40,7 @@ pub fn op_webgpu_create_shader_module(
let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor { let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor {
label: args.label.map(Cow::from), label: args.label.map(Cow::from),
shader_bound_checks: wgpu_types::ShaderBoundChecks::default(),
}; };
gfx_put!(device => instance.device_create_shader_module( gfx_put!(device => instance.device_create_shader_module(

112
ext/webgpu/src/texture.rs Normal file
View file

@ -0,0 +1,112 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use super::error::WebGpuResult;
pub(crate) struct WebGpuTexture(pub(crate) wgpu_core::id::TextureId);
impl Resource for WebGpuTexture {
fn name(&self) -> Cow<str> {
"webGPUTexture".into()
}
}
pub(crate) struct WebGpuTextureView(pub(crate) wgpu_core::id::TextureViewId);
impl Resource for WebGpuTextureView {
fn name(&self) -> Cow<str> {
"webGPUTextureView".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTextureArgs {
device_rid: ResourceId,
label: Option<String>,
size: wgpu_types::Extent3d,
mip_level_count: u32,
sample_count: u32,
dimension: wgpu_types::TextureDimension,
format: wgpu_types::TextureFormat,
usage: u32,
}
pub fn op_webgpu_create_texture(
state: &mut OpState,
args: CreateTextureArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let descriptor = wgpu_core::resource::TextureDescriptor {
label: args.label.map(Cow::from),
size: args.size,
mip_level_count: args.mip_level_count,
sample_count: args.sample_count,
dimension: args.dimension,
format: args.format,
usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage),
};
gfx_put!(device => instance.device_create_texture(
device,
&descriptor,
std::marker::PhantomData
) => state, WebGpuTexture)
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTextureViewArgs {
texture_rid: ResourceId,
label: Option<String>,
format: Option<wgpu_types::TextureFormat>,
dimension: Option<wgpu_types::TextureViewDimension>,
aspect: wgpu_types::TextureAspect,
base_mip_level: u32,
mip_level_count: Option<u32>,
base_array_layer: u32,
array_layer_count: Option<u32>,
}
pub fn op_webgpu_create_texture_view(
state: &mut OpState,
args: CreateTextureViewArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let texture_resource = state
.resource_table
.get::<WebGpuTexture>(args.texture_rid)?;
let texture = texture_resource.0;
let descriptor = wgpu_core::resource::TextureViewDescriptor {
label: args.label.map(Cow::from),
format: args.format,
dimension: args.dimension,
range: wgpu_types::ImageSubresourceRange {
aspect: args.aspect,
base_mip_level: args.base_mip_level,
mip_level_count: std::num::NonZeroU32::new(
args.mip_level_count.unwrap_or(0),
),
base_array_layer: args.base_array_layer,
array_layer_count: std::num::NonZeroU32::new(
args.array_layer_count.unwrap_or(0),
),
},
};
gfx_put!(texture => instance.texture_create_view(
texture,
&descriptor,
std::marker::PhantomData
) => state, WebGpuTextureView)
}

View file

@ -1,419 +0,0 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use deno_core::error::not_supported;
use deno_core::error::AnyError;
use deno_core::ResourceId;
use deno_core::{OpState, Resource};
use serde::Deserialize;
use std::borrow::Cow;
use super::error::WebGpuResult;
pub(crate) struct WebGpuTexture(pub(crate) wgpu_core::id::TextureId);
impl Resource for WebGpuTexture {
fn name(&self) -> Cow<str> {
"webGPUTexture".into()
}
}
pub(crate) struct WebGpuTextureView(pub(crate) wgpu_core::id::TextureViewId);
impl Resource for WebGpuTextureView {
fn name(&self) -> Cow<str> {
"webGPUTextureView".into()
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuTextureFormat {
// 8-bit formats
#[serde(rename = "r8unorm")]
R8Unorm,
#[serde(rename = "r8snorm")]
R8Snorm,
#[serde(rename = "r8uint")]
R8Uint,
#[serde(rename = "r8sint")]
R8Sint,
// 16-bit formats
#[serde(rename = "r16uint")]
R16Uint,
#[serde(rename = "r16sint")]
R16Sint,
#[serde(rename = "r16float")]
R16Float,
#[serde(rename = "rg8unorm")]
Rg8Unorm,
#[serde(rename = "rg8snorm")]
Rg8Snorm,
#[serde(rename = "rg8uint")]
Rg8Uint,
#[serde(rename = "rg8sint")]
Rg8Sint,
// 32-bit formats
#[serde(rename = "r32uint")]
R32Uint,
#[serde(rename = "r32sint")]
R32Sint,
#[serde(rename = "r32float")]
R32Float,
#[serde(rename = "rg16uint")]
Rg16Uint,
#[serde(rename = "rg16sint")]
Rg16Sint,
#[serde(rename = "rg16float")]
Rg16Float,
#[serde(rename = "rgba8unorm")]
Rgba8Unorm,
#[serde(rename = "rgba8unorm-srgb")]
Rgba8UnormSrgb,
#[serde(rename = "rgba8snorm")]
Rgba8Snorm,
#[serde(rename = "rgba8uint")]
Rgba8Uint,
#[serde(rename = "rgba8sint")]
Rgba8Sint,
#[serde(rename = "bgra8unorm")]
Bgra8Unorm,
#[serde(rename = "bgra8unorm-srgb")]
Bgra8UnormSrgb,
// Packed 32-bit formats
#[serde(rename = "rgb9e5ufloat")]
RgB9E5UFloat,
#[serde(rename = "rgb10a2unorm")]
Rgb10a2Unorm,
#[serde(rename = "rg11b10ufloat")]
Rg11b10Float,
// 64-bit formats
#[serde(rename = "rg32uint")]
Rg32Uint,
#[serde(rename = "rg32sint")]
Rg32Sint,
#[serde(rename = "rg32float")]
Rg32Float,
#[serde(rename = "rgba16uint")]
Rgba16Uint,
#[serde(rename = "rgba16sint")]
Rgba16Sint,
#[serde(rename = "rgba16float")]
Rgba16Float,
// 128-bit formats
#[serde(rename = "rgba32uint")]
Rgba32Uint,
#[serde(rename = "rgba32sint")]
Rgba32Sint,
#[serde(rename = "rgba32float")]
Rgba32Float,
// Depth and stencil formats
#[serde(rename = "stencil8")]
Stencil8,
#[serde(rename = "depth16unorm")]
Depth16Unorm,
#[serde(rename = "depth24plus")]
Depth24Plus,
#[serde(rename = "depth24plus-stencil8")]
Depth24PlusStencil8,
#[serde(rename = "depth32float")]
Depth32Float,
// BC compressed formats usable if "texture-compression-bc" is both
// supported by the device/user agent and enabled in requestDevice.
#[serde(rename = "bc1-rgba-unorm")]
Bc1RgbaUnorm,
#[serde(rename = "bc1-rgba-unorm-srgb")]
Bc1RgbaUnormSrgb,
#[serde(rename = "bc2-rgba-unorm")]
Bc2RgbaUnorm,
#[serde(rename = "bc2-rgba-unorm-srgb")]
Bc2RgbaUnormSrgb,
#[serde(rename = "bc3-rgba-unorm")]
Bc3RgbaUnorm,
#[serde(rename = "bc3-rgba-unorm-srgb")]
Bc3RgbaUnormSrgb,
#[serde(rename = "bc4-r-unorm")]
Bc4RUnorm,
#[serde(rename = "bc4-r-snorm")]
Bc4RSnorm,
#[serde(rename = "bc5-rg-unorm")]
Bc5RgUnorm,
#[serde(rename = "bc5-rg-snorm")]
Bc5RgSnorm,
#[serde(rename = "bc6h-rgb-ufloat")]
Bc6hRgbUfloat,
#[serde(rename = "bc6h-rgb-float")]
Bc6HRgbFloat,
#[serde(rename = "bc7-rgba-unorm")]
Bc7RgbaUnorm,
#[serde(rename = "bc7-rgba-unorm-srgb")]
Bc7RgbaUnormSrgb,
// "depth24unorm-stencil8" feature
#[serde(rename = "depth24unorm-stencil8")]
Depth24UnormStencil8,
// "depth32float-stencil8" feature
#[serde(rename = "depth32float-stencil8")]
Depth32FloatStencil8,
}
impl TryFrom<GpuTextureFormat> for wgpu_types::TextureFormat {
type Error = AnyError;
fn try_from(value: GpuTextureFormat) -> Result<Self, Self::Error> {
use wgpu_types::TextureFormat;
match value {
GpuTextureFormat::R8Unorm => Ok(TextureFormat::R8Unorm),
GpuTextureFormat::R8Snorm => Ok(TextureFormat::R8Snorm),
GpuTextureFormat::R8Uint => Ok(TextureFormat::R8Uint),
GpuTextureFormat::R8Sint => Ok(TextureFormat::R8Sint),
GpuTextureFormat::R16Uint => Ok(TextureFormat::R16Uint),
GpuTextureFormat::R16Sint => Ok(TextureFormat::R16Sint),
GpuTextureFormat::R16Float => Ok(TextureFormat::R16Float),
GpuTextureFormat::Rg8Unorm => Ok(TextureFormat::Rg8Unorm),
GpuTextureFormat::Rg8Snorm => Ok(TextureFormat::Rg8Snorm),
GpuTextureFormat::Rg8Uint => Ok(TextureFormat::Rg8Uint),
GpuTextureFormat::Rg8Sint => Ok(TextureFormat::Rg8Sint),
GpuTextureFormat::R32Uint => Ok(TextureFormat::R32Uint),
GpuTextureFormat::R32Sint => Ok(TextureFormat::R32Sint),
GpuTextureFormat::R32Float => Ok(TextureFormat::R32Float),
GpuTextureFormat::Rg16Uint => Ok(TextureFormat::Rg16Uint),
GpuTextureFormat::Rg16Sint => Ok(TextureFormat::Rg16Sint),
GpuTextureFormat::Rg16Float => Ok(TextureFormat::Rg16Float),
GpuTextureFormat::Rgba8Unorm => Ok(TextureFormat::Rgba8Unorm),
GpuTextureFormat::Rgba8UnormSrgb => Ok(TextureFormat::Rgba8UnormSrgb),
GpuTextureFormat::Rgba8Snorm => Ok(TextureFormat::Rgba8Snorm),
GpuTextureFormat::Rgba8Uint => Ok(TextureFormat::Rgba8Uint),
GpuTextureFormat::Rgba8Sint => Ok(TextureFormat::Rgba8Sint),
GpuTextureFormat::Bgra8Unorm => Ok(TextureFormat::Bgra8Unorm),
GpuTextureFormat::Bgra8UnormSrgb => Ok(TextureFormat::Bgra8UnormSrgb),
GpuTextureFormat::RgB9E5UFloat => Err(not_supported()), // wgpu#967
GpuTextureFormat::Rgb10a2Unorm => Ok(TextureFormat::Rgb10a2Unorm),
GpuTextureFormat::Rg11b10Float => Ok(TextureFormat::Rg11b10Float),
GpuTextureFormat::Rg32Uint => Ok(TextureFormat::Rg32Uint),
GpuTextureFormat::Rg32Sint => Ok(TextureFormat::Rg32Sint),
GpuTextureFormat::Rg32Float => Ok(TextureFormat::Rg32Float),
GpuTextureFormat::Rgba16Uint => Ok(TextureFormat::Rgba16Uint),
GpuTextureFormat::Rgba16Sint => Ok(TextureFormat::Rgba16Sint),
GpuTextureFormat::Rgba16Float => Ok(TextureFormat::Rgba16Float),
GpuTextureFormat::Rgba32Uint => Ok(TextureFormat::Rgba32Uint),
GpuTextureFormat::Rgba32Sint => Ok(TextureFormat::Rgba32Sint),
GpuTextureFormat::Rgba32Float => Ok(TextureFormat::Rgba32Float),
GpuTextureFormat::Stencil8 => Err(not_supported()), // wgpu#967
GpuTextureFormat::Depth16Unorm => Err(not_supported()), // wgpu#967
GpuTextureFormat::Depth24Plus => Ok(TextureFormat::Depth24Plus),
GpuTextureFormat::Depth24PlusStencil8 => {
Ok(TextureFormat::Depth24PlusStencil8)
}
GpuTextureFormat::Depth32Float => Ok(TextureFormat::Depth32Float),
GpuTextureFormat::Bc1RgbaUnorm => Ok(TextureFormat::Bc1RgbaUnorm),
GpuTextureFormat::Bc1RgbaUnormSrgb => Ok(TextureFormat::Bc1RgbaUnormSrgb),
GpuTextureFormat::Bc2RgbaUnorm => Ok(TextureFormat::Bc2RgbaUnorm),
GpuTextureFormat::Bc2RgbaUnormSrgb => Ok(TextureFormat::Bc2RgbaUnormSrgb),
GpuTextureFormat::Bc3RgbaUnorm => Ok(TextureFormat::Bc3RgbaUnorm),
GpuTextureFormat::Bc3RgbaUnormSrgb => Ok(TextureFormat::Bc3RgbaUnormSrgb),
GpuTextureFormat::Bc4RUnorm => Ok(TextureFormat::Bc4RUnorm),
GpuTextureFormat::Bc4RSnorm => Ok(TextureFormat::Bc4RSnorm),
GpuTextureFormat::Bc5RgUnorm => Ok(TextureFormat::Bc5RgUnorm),
GpuTextureFormat::Bc5RgSnorm => Ok(TextureFormat::Bc5RgSnorm),
GpuTextureFormat::Bc6hRgbUfloat => Ok(TextureFormat::Bc6hRgbUfloat),
GpuTextureFormat::Bc6HRgbFloat => Ok(TextureFormat::Bc6hRgbSfloat), // wgpu#967
GpuTextureFormat::Bc7RgbaUnorm => Ok(TextureFormat::Bc7RgbaUnorm),
GpuTextureFormat::Bc7RgbaUnormSrgb => Ok(TextureFormat::Bc7RgbaUnormSrgb),
GpuTextureFormat::Depth24UnormStencil8 => Err(not_supported()), // wgpu#967,
GpuTextureFormat::Depth32FloatStencil8 => Err(not_supported()), // wgpu#967
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuTextureViewDimension {
#[serde(rename = "1d")]
D1,
#[serde(rename = "2d")]
D2,
#[serde(rename = "2d-array")]
D2Array,
#[serde(rename = "cube")]
Cube,
#[serde(rename = "cube-array")]
CubeArray,
#[serde(rename = "3d")]
D3,
}
impl From<GpuTextureViewDimension> for wgpu_types::TextureViewDimension {
fn from(view_dimension: GpuTextureViewDimension) -> Self {
match view_dimension {
GpuTextureViewDimension::D1 => wgpu_types::TextureViewDimension::D1,
GpuTextureViewDimension::D2 => wgpu_types::TextureViewDimension::D2,
GpuTextureViewDimension::D2Array => {
wgpu_types::TextureViewDimension::D2Array
}
GpuTextureViewDimension::Cube => wgpu_types::TextureViewDimension::Cube,
GpuTextureViewDimension::CubeArray => {
wgpu_types::TextureViewDimension::CubeArray
}
GpuTextureViewDimension::D3 => wgpu_types::TextureViewDimension::D3,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuTextureDimension {
#[serde(rename = "1d")]
D1,
#[serde(rename = "2d")]
D2,
#[serde(rename = "3d")]
D3,
}
impl From<GpuTextureDimension> for wgpu_types::TextureDimension {
fn from(texture_dimension: GpuTextureDimension) -> Self {
match texture_dimension {
GpuTextureDimension::D1 => wgpu_types::TextureDimension::D1,
GpuTextureDimension::D2 => wgpu_types::TextureDimension::D2,
GpuTextureDimension::D3 => wgpu_types::TextureDimension::D3,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum GpuTextureAspect {
All,
StencilOnly,
DepthOnly,
}
impl From<GpuTextureAspect> for wgpu_types::TextureAspect {
fn from(aspect: GpuTextureAspect) -> wgpu_types::TextureAspect {
match aspect {
GpuTextureAspect::All => wgpu_types::TextureAspect::All,
GpuTextureAspect::StencilOnly => wgpu_types::TextureAspect::StencilOnly,
GpuTextureAspect::DepthOnly => wgpu_types::TextureAspect::DepthOnly,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GpuExtent3D {
pub width: u32,
pub height: u32,
pub depth_or_array_layers: u32,
}
impl From<GpuExtent3D> for wgpu_types::Extent3d {
fn from(extent: GpuExtent3D) -> Self {
wgpu_types::Extent3d {
width: extent.width,
height: extent.height,
depth_or_array_layers: extent.depth_or_array_layers,
}
}
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTextureArgs {
device_rid: ResourceId,
label: Option<String>,
size: GpuExtent3D,
mip_level_count: u32,
sample_count: u32,
dimension: GpuTextureDimension,
format: GpuTextureFormat,
usage: u32,
}
pub fn op_webgpu_create_texture(
state: &mut OpState,
args: CreateTextureArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
let device = device_resource.0;
let descriptor = wgpu_core::resource::TextureDescriptor {
label: args.label.map(Cow::from),
size: args.size.into(),
mip_level_count: args.mip_level_count,
sample_count: args.sample_count,
dimension: args.dimension.into(),
format: args.format.try_into()?,
usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage),
};
gfx_put!(device => instance.device_create_texture(
device,
&descriptor,
std::marker::PhantomData
) => state, WebGpuTexture)
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateTextureViewArgs {
texture_rid: ResourceId,
label: Option<String>,
format: Option<GpuTextureFormat>,
dimension: Option<GpuTextureViewDimension>,
aspect: GpuTextureAspect,
base_mip_level: u32,
mip_level_count: Option<u32>,
base_array_layer: u32,
array_layer_count: Option<u32>,
}
pub fn op_webgpu_create_texture_view(
state: &mut OpState,
args: CreateTextureViewArgs,
_: (),
) -> Result<WebGpuResult, AnyError> {
let instance = state.borrow::<super::Instance>();
let texture_resource = state
.resource_table
.get::<WebGpuTexture>(args.texture_rid)?;
let texture = texture_resource.0;
let descriptor = wgpu_core::resource::TextureViewDescriptor {
label: args.label.map(Cow::from),
format: args.format.map(|s| s.try_into()).transpose()?,
dimension: args.dimension.map(|s| s.into()),
range: wgpu_types::ImageSubresourceRange {
aspect: args.aspect.into(),
base_mip_level: args.base_mip_level,
mip_level_count: std::num::NonZeroU32::new(
args.mip_level_count.unwrap_or(0),
),
base_array_layer: args.base_array_layer,
array_layer_count: std::num::NonZeroU32::new(
args.array_layer_count.unwrap_or(0),
),
},
};
gfx_put!(texture => instance.texture_create_view(
texture,
&descriptor,
std::marker::PhantomData
) => state, WebGpuTextureView)
}

View file

@ -6,7 +6,7 @@ dictionary GPUObjectDescriptorBase {
USVString label; USVString label;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUSupportedLimits { interface GPUSupportedLimits {
readonly attribute unsigned long maxTextureDimension1D; readonly attribute unsigned long maxTextureDimension1D;
readonly attribute unsigned long maxTextureDimension2D; readonly attribute unsigned long maxTextureDimension2D;
@ -36,7 +36,7 @@ interface GPUSupportedLimits {
readonly attribute unsigned long maxComputeWorkgroupsPerDimension; readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUSupportedFeatures { interface GPUSupportedFeatures {
readonly setlike<DOMString>; readonly setlike<DOMString>;
}; };
@ -46,12 +46,12 @@ enum GPUPredefinedColorSpace {
}; };
interface mixin NavigatorGPU { interface mixin NavigatorGPU {
[SameObject] readonly attribute GPU gpu; [SameObject, SecureContext] readonly attribute GPU gpu;
}; };
Navigator includes NavigatorGPU; Navigator includes NavigatorGPU;
WorkerNavigator includes NavigatorGPU; WorkerNavigator includes NavigatorGPU;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPU { interface GPU {
Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {}); Promise<GPUAdapter?> requestAdapter(optional GPURequestAdapterOptions options = {});
}; };
@ -63,10 +63,10 @@ dictionary GPURequestAdapterOptions {
enum GPUPowerPreference { enum GPUPowerPreference {
"low-power", "low-power",
"high-performance" "high-performance",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUAdapter { interface GPUAdapter {
readonly attribute DOMString name; readonly attribute DOMString name;
[SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedFeatures features;
@ -82,15 +82,18 @@ dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
}; };
enum GPUFeatureName { enum GPUFeatureName {
"depth-clamping", "depth-clip-control",
"depth24unorm-stencil8", "depth24unorm-stencil8",
"depth32float-stencil8", "depth32float-stencil8",
"pipeline-statistics-query", "pipeline-statistics-query",
"texture-compression-bc", "texture-compression-bc",
"texture-compression-etc2",
"texture-compression-astc",
"timestamp-query", "timestamp-query",
"indirect-first-instance",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUDevice : EventTarget { interface GPUDevice : EventTarget {
[SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedFeatures features;
[SameObject] readonly attribute GPUSupportedLimits limits; [SameObject] readonly attribute GPUSupportedLimits limits;
@ -120,7 +123,7 @@ interface GPUDevice : EventTarget {
}; };
GPUDevice includes GPUObjectBase; GPUDevice includes GPUObjectBase;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUBuffer { interface GPUBuffer {
Promise<undefined> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size); Promise<undefined> mapAsync(GPUMapModeFlags mode, optional GPUSize64 offset = 0, optional GPUSize64 size);
ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size); ArrayBuffer getMappedRange(optional GPUSize64 offset = 0, optional GPUSize64 size);
@ -158,7 +161,7 @@ interface GPUMapMode {
const GPUFlagsConstant WRITE = 0x0002; const GPUFlagsConstant WRITE = 0x0002;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUTexture { interface GPUTexture {
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {}); GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
@ -191,7 +194,7 @@ interface GPUTextureUsage {
const GPUFlagsConstant RENDER_ATTACHMENT = 0x10; const GPUFlagsConstant RENDER_ATTACHMENT = 0x10;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUTextureView { interface GPUTextureView {
}; };
GPUTextureView includes GPUObjectBase; GPUTextureView includes GPUObjectBase;
@ -212,13 +215,13 @@ enum GPUTextureViewDimension {
"2d-array", "2d-array",
"cube", "cube",
"cube-array", "cube-array",
"3d" "3d",
}; };
enum GPUTextureAspect { enum GPUTextureAspect {
"all", "all",
"stencil-only", "stencil-only",
"depth-only" "depth-only",
}; };
enum GPUTextureFormat { enum GPUTextureFormat {
@ -293,6 +296,50 @@ enum GPUTextureFormat {
"bc7-rgba-unorm", "bc7-rgba-unorm",
"bc7-rgba-unorm-srgb", "bc7-rgba-unorm-srgb",
// ETC2 compressed formats usable if "texture-compression-etc2" is both
// supported by the device/user agent and enabled in requestDevice.
"etc2-rgb8unorm",
"etc2-rgb8unorm-srgb",
"etc2-rgb8a1unorm",
"etc2-rgb8a1unorm-srgb",
"etc2-rgba8unorm",
"etc2-rgba8unorm-srgb",
"eac-r11unorm",
"eac-r11snorm",
"eac-rg11unorm",
"eac-rg11snorm",
// ASTC compressed formats usable if "texture-compression-astc" is both
// supported by the device/user agent and enabled in requestDevice.
"astc-4x4-unorm",
"astc-4x4-unorm-srgb",
"astc-5x4-unorm",
"astc-5x4-unorm-srgb",
"astc-5x5-unorm",
"astc-5x5-unorm-srgb",
"astc-6x5-unorm",
"astc-6x5-unorm-srgb",
"astc-6x6-unorm",
"astc-6x6-unorm-srgb",
"astc-8x5-unorm",
"astc-8x5-unorm-srgb",
"astc-8x6-unorm",
"astc-8x6-unorm-srgb",
"astc-8x8-unorm",
"astc-8x8-unorm-srgb",
"astc-10x5-unorm",
"astc-10x5-unorm-srgb",
"astc-10x6-unorm",
"astc-10x6-unorm-srgb",
"astc-10x8-unorm",
"astc-10x8-unorm-srgb",
"astc-10x10-unorm",
"astc-10x10-unorm-srgb",
"astc-12x10-unorm",
"astc-12x10-unorm-srgb",
"astc-12x12-unorm",
"astc-12x12-unorm-srgb",
// "depth24unorm-stencil8" feature // "depth24unorm-stencil8" feature
"depth24unorm-stencil8", "depth24unorm-stencil8",
@ -300,7 +347,7 @@ enum GPUTextureFormat {
"depth32float-stencil8", "depth32float-stencil8",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUSampler { interface GPUSampler {
}; };
GPUSampler includes GPUObjectBase; GPUSampler includes GPUObjectBase;
@ -321,12 +368,12 @@ dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
enum GPUAddressMode { enum GPUAddressMode {
"clamp-to-edge", "clamp-to-edge",
"repeat", "repeat",
"mirror-repeat" "mirror-repeat",
}; };
enum GPUFilterMode { enum GPUFilterMode {
"nearest", "nearest",
"linear" "linear",
}; };
enum GPUCompareFunction { enum GPUCompareFunction {
@ -337,10 +384,10 @@ enum GPUCompareFunction {
"greater", "greater",
"not-equal", "not-equal",
"greater-equal", "greater-equal",
"always" "always",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUBindGroupLayout { interface GPUBindGroupLayout {
}; };
GPUBindGroupLayout includes GPUObjectBase; GPUBindGroupLayout includes GPUObjectBase;
@ -390,11 +437,11 @@ dictionary GPUSamplerBindingLayout {
}; };
enum GPUTextureSampleType { enum GPUTextureSampleType {
"float", "float",
"unfilterable-float", "unfilterable-float",
"depth", "depth",
"sint", "sint",
"uint", "uint",
}; };
dictionary GPUTextureBindingLayout { dictionary GPUTextureBindingLayout {
@ -413,7 +460,7 @@ dictionary GPUStorageTextureBindingLayout {
GPUTextureViewDimension viewDimension = "2d"; GPUTextureViewDimension viewDimension = "2d";
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUBindGroup { interface GPUBindGroup {
}; };
GPUBindGroup includes GPUObjectBase; GPUBindGroup includes GPUObjectBase;
@ -436,7 +483,7 @@ dictionary GPUBufferBinding {
GPUSize64 size; GPUSize64 size;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUPipelineLayout { interface GPUPipelineLayout {
}; };
GPUPipelineLayout includes GPUObjectBase; GPUPipelineLayout includes GPUObjectBase;
@ -445,7 +492,7 @@ dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupLayout> bindGroupLayouts; required sequence<GPUBindGroupLayout> bindGroupLayouts;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUShaderModule { interface GPUShaderModule {
Promise<GPUCompilationInfo> compilationInfo(); Promise<GPUCompilationInfo> compilationInfo();
}; };
@ -459,10 +506,10 @@ dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
enum GPUCompilationMessageType { enum GPUCompilationMessageType {
"error", "error",
"warning", "warning",
"info" "info",
}; };
[Exposed=(Window, DedicatedWorker), Serializable] [Exposed=(Window, DedicatedWorker), Serializable, SecureContext]
interface GPUCompilationMessage { interface GPUCompilationMessage {
readonly attribute DOMString message; readonly attribute DOMString message;
readonly attribute GPUCompilationMessageType type; readonly attribute GPUCompilationMessageType type;
@ -472,7 +519,7 @@ interface GPUCompilationMessage {
readonly attribute unsigned long long length; readonly attribute unsigned long long length;
}; };
[Exposed=(Window, DedicatedWorker), Serializable] [Exposed=(Window, DedicatedWorker), Serializable, SecureContext]
interface GPUCompilationInfo { interface GPUCompilationInfo {
readonly attribute FrozenArray<GPUCompilationMessage> messages; readonly attribute FrozenArray<GPUCompilationMessage> messages;
}; };
@ -493,7 +540,7 @@ dictionary GPUProgrammableStage {
typedef double GPUPipelineConstantValue; // May represent WGSLs bool, f32, i32, u32. typedef double GPUPipelineConstantValue; // May represent WGSLs bool, f32, i32, u32.
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUComputePipeline { interface GPUComputePipeline {
}; };
GPUComputePipeline includes GPUObjectBase; GPUComputePipeline includes GPUObjectBase;
@ -503,7 +550,7 @@ dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
required GPUProgrammableStage compute; required GPUProgrammableStage compute;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderPipeline { interface GPURenderPipeline {
}; };
GPURenderPipeline includes GPUObjectBase; GPURenderPipeline includes GPUObjectBase;
@ -522,7 +569,7 @@ enum GPUPrimitiveTopology {
"line-list", "line-list",
"line-strip", "line-strip",
"triangle-list", "triangle-list",
"triangle-strip" "triangle-strip",
}; };
dictionary GPUPrimitiveState { dictionary GPUPrimitiveState {
@ -531,19 +578,19 @@ dictionary GPUPrimitiveState {
GPUFrontFace frontFace = "ccw"; GPUFrontFace frontFace = "ccw";
GPUCullMode cullMode = "none"; GPUCullMode cullMode = "none";
// Enable depth clamping (requires "depth-clamping" feature) // Requires "depth-clip-control" feature.
boolean clampDepth = false; boolean unclippedDepth = false;
}; };
enum GPUFrontFace { enum GPUFrontFace {
"ccw", "ccw",
"cw" "cw",
}; };
enum GPUCullMode { enum GPUCullMode {
"none", "none",
"front", "front",
"back" "back",
}; };
dictionary GPUMultisampleState { dictionary GPUMultisampleState {
@ -552,7 +599,7 @@ dictionary GPUMultisampleState {
boolean alphaToCoverageEnabled = false; boolean alphaToCoverageEnabled = false;
}; };
dictionary GPUFragmentState: GPUProgrammableStage { dictionary GPUFragmentState : GPUProgrammableStage {
required sequence<GPUColorTargetState> targets; required sequence<GPUColorTargetState> targets;
}; };
@ -579,9 +626,9 @@ interface GPUColorWrite {
}; };
dictionary GPUBlendComponent { dictionary GPUBlendComponent {
GPUBlendOperation operation = "add";
GPUBlendFactor srcFactor = "one"; GPUBlendFactor srcFactor = "one";
GPUBlendFactor dstFactor = "zero"; GPUBlendFactor dstFactor = "zero";
GPUBlendOperation operation = "add";
}; };
enum GPUBlendFactor { enum GPUBlendFactor {
@ -597,7 +644,7 @@ enum GPUBlendFactor {
"one-minus-dst-alpha", "one-minus-dst-alpha",
"src-alpha-saturated", "src-alpha-saturated",
"constant", "constant",
"one-minus-constant" "one-minus-constant",
}; };
enum GPUBlendOperation { enum GPUBlendOperation {
@ -605,7 +652,7 @@ enum GPUBlendOperation {
"subtract", "subtract",
"reverse-subtract", "reverse-subtract",
"min", "min",
"max" "max",
}; };
dictionary GPUDepthStencilState { dictionary GPUDepthStencilState {
@ -640,12 +687,12 @@ enum GPUStencilOperation {
"increment-clamp", "increment-clamp",
"decrement-clamp", "decrement-clamp",
"increment-wrap", "increment-wrap",
"decrement-wrap" "decrement-wrap",
}; };
enum GPUIndexFormat { enum GPUIndexFormat {
"uint16", "uint16",
"uint32" "uint32",
}; };
enum GPUVertexFormat { enum GPUVertexFormat {
@ -683,10 +730,10 @@ enum GPUVertexFormat {
enum GPUVertexStepMode { enum GPUVertexStepMode {
"vertex", "vertex",
"instance" "instance",
}; };
dictionary GPUVertexState: GPUProgrammableStage { dictionary GPUVertexState : GPUProgrammableStage {
sequence<GPUVertexBufferLayout?> buffers = []; sequence<GPUVertexBufferLayout?> buffers = [];
}; };
@ -703,16 +750,15 @@ dictionary GPUVertexAttribute {
required GPUIndex32 shaderLocation; required GPUIndex32 shaderLocation;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUCommandBuffer { interface GPUCommandBuffer {
readonly attribute Promise<double> executionTime;
}; };
GPUCommandBuffer includes GPUObjectBase; GPUCommandBuffer includes GPUObjectBase;
dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase { dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUCommandEncoder { interface GPUCommandEncoder {
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {}); GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});
@ -739,6 +785,11 @@ interface GPUCommandEncoder {
GPUImageCopyTexture destination, GPUImageCopyTexture destination,
GPUExtent3D copySize); GPUExtent3D copySize);
undefined clearBuffer(
GPUBuffer destination,
GPUSize64 destinationOffset,
GPUSize64 size);
undefined pushDebugGroup(USVString groupLabel); undefined pushDebugGroup(USVString groupLabel);
undefined popDebugGroup(); undefined popDebugGroup();
undefined insertDebugMarker(USVString markerLabel); undefined insertDebugMarker(USVString markerLabel);
@ -757,7 +808,6 @@ interface GPUCommandEncoder {
GPUCommandEncoder includes GPUObjectBase; GPUCommandEncoder includes GPUObjectBase;
dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase { dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {
boolean measureExecutionTime = false;
}; };
dictionary GPUImageDataLayout { dictionary GPUImageDataLayout {
@ -791,7 +841,7 @@ interface mixin GPUProgrammablePassEncoder {
undefined insertDebugMarker(USVString markerLabel); undefined insertDebugMarker(USVString markerLabel);
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUComputePassEncoder { interface GPUComputePassEncoder {
undefined setPipeline(GPUComputePipeline pipeline); undefined setPipeline(GPUComputePipeline pipeline);
undefined dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1); undefined dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1);
@ -827,7 +877,7 @@ interface mixin GPURenderEncoderBase {
undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderPassEncoder { interface GPURenderPassEncoder {
undefined setViewport(float x, float y, undefined setViewport(float x, float y,
float width, float height, float width, float height,
@ -881,12 +931,12 @@ dictionary GPURenderPassDepthStencilAttachment {
}; };
enum GPULoadOp { enum GPULoadOp {
"load" "load",
}; };
enum GPUStoreOp { enum GPUStoreOp {
"store", "store",
"discard" "discard",
}; };
dictionary GPURenderPassLayout: GPUObjectDescriptorBase { dictionary GPURenderPassLayout: GPUObjectDescriptorBase {
@ -895,7 +945,7 @@ dictionary GPURenderPassLayout: GPUObjectDescriptorBase {
GPUSize32 sampleCount = 1; GPUSize32 sampleCount = 1;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderBundle { interface GPURenderBundle {
}; };
GPURenderBundle includes GPUObjectBase; GPURenderBundle includes GPUObjectBase;
@ -903,7 +953,7 @@ GPURenderBundle includes GPUObjectBase;
dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase { dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase {
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderBundleEncoder { interface GPURenderBundleEncoder {
GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {}); GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
}; };
@ -916,7 +966,7 @@ dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout {
boolean stencilReadOnly = false; boolean stencilReadOnly = false;
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUQueue { interface GPUQueue {
undefined submit(sequence<GPUCommandBuffer> commandBuffers); undefined submit(sequence<GPUCommandBuffer> commandBuffers);
@ -930,14 +980,14 @@ interface GPUQueue {
optional GPUSize64 size); optional GPUSize64 size);
undefined writeTexture( undefined writeTexture(
GPUImageCopyTexture destination, GPUImageCopyTexture destination,
[AllowShared] BufferSource data, [AllowShared] BufferSource data,
GPUImageDataLayout dataLayout, GPUImageDataLayout dataLayout,
GPUExtent3D size); GPUExtent3D size);
}; };
GPUQueue includes GPUObjectBase; GPUQueue includes GPUObjectBase;
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUQuerySet { interface GPUQuerySet {
undefined destroy(); undefined destroy();
}; };
@ -952,7 +1002,7 @@ dictionary GPUQuerySetDescriptor : GPUObjectDescriptorBase {
enum GPUQueryType { enum GPUQueryType {
"occlusion", "occlusion",
"pipeline-statistics", "pipeline-statistics",
"timestamp" "timestamp",
}; };
enum GPUPipelineStatisticName { enum GPUPipelineStatisticName {
@ -960,14 +1010,14 @@ enum GPUPipelineStatisticName {
"clipper-invocations", "clipper-invocations",
"clipper-primitives-out", "clipper-primitives-out",
"fragment-shader-invocations", "fragment-shader-invocations",
"compute-shader-invocations" "compute-shader-invocations",
}; };
enum GPUDeviceLostReason { enum GPUDeviceLostReason {
"destroyed", "destroyed",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUDeviceLostInfo { interface GPUDeviceLostInfo {
readonly attribute (GPUDeviceLostReason or undefined) reason; readonly attribute (GPUDeviceLostReason or undefined) reason;
readonly attribute DOMString message; readonly attribute DOMString message;
@ -979,15 +1029,15 @@ partial interface GPUDevice {
enum GPUErrorFilter { enum GPUErrorFilter {
"out-of-memory", "out-of-memory",
"validation" "validation",
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUOutOfMemoryError { interface GPUOutOfMemoryError {
constructor(); constructor();
}; };
[Exposed=(Window, DedicatedWorker)] [Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUValidationError { interface GPUValidationError {
constructor(DOMString message); constructor(DOMString message);
readonly attribute DOMString message; readonly attribute DOMString message;
@ -1000,9 +1050,7 @@ partial interface GPUDevice {
Promise<GPUError?> popErrorScope(); Promise<GPUError?> popErrorScope();
}; };
[ [Exposed=(Window, DedicatedWorker), SecureContext]
Exposed=(Window, DedicatedWorker)
]
interface GPUUncapturedErrorEvent : Event { interface GPUUncapturedErrorEvent : Event {
constructor( constructor(
DOMString type, DOMString type,
@ -1060,3 +1108,4 @@ dictionary GPUExtent3DDict {
GPUIntegerCoordinate depthOrArrayLayers = 1; GPUIntegerCoordinate depthOrArrayLayers = 1;
}; };
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D; typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;

View file

@ -59,3 +59,16 @@ So you can simply run `./tools/flamebench.js op_baseline bench_op_async` or
Tip: the `[bench_filter]` argument doesn't have to be an exact bench name, you Tip: the `[bench_filter]` argument doesn't have to be an exact bench name, you
can use a shorthand or a partial match to profile a group of benches, e.g: can use a shorthand or a partial match to profile a group of benches, e.g:
`./tools/flamebench.js de v8` `./tools/flamebench.js de v8`
## wgpu_sync.js
`wgpu_sync.js` streamlines updating `deno_webgpu` from
[gfx-rs/wgpu](https://github.com/gfx-rs/wgpu/).
It essentially vendors the `deno_webgpu` tree with a few minor patches applied
on top, somewhat similar to `git subtree`.
1. Update `COMMIT` in `./tools/wgpu_sync.js`
2. Run `./tools/wgpu_sync.js`
3. Double check changes, possibly patch
4. Commit & send a PR with the updates

90
tools/wgpu_sync.js Executable file
View file

@ -0,0 +1,90 @@
#!/usr/bin/env -S deno run --unstable --allow-read --allow-write --allow-run
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
import { join, ROOT_PATH } from "./util.js";
// const COMMIT = "c00e471274b6c21acda89b4b13d41742c0285d71"; // Release 12
const COMMIT = "cdd480a89c9e3b681d9d174e65082d2bdbc903ef"; // tip
const REPO = "gfx-rs/wgpu";
// const V_WGPU = "0.12.0";
const TARGET_DIR = join(ROOT_PATH, "ext", "webgpu");
async function bash(subcmd, opts = {}) {
const p = Deno.run({ ...opts, cmd: ["bash", "-c", subcmd] });
// Exit process on failure
const { success, code } = await p.status();
if (!success) {
Deno.exit(code);
}
// Cleanup
p.close();
}
async function clearTargetDir() {
await bash(`rm -r ${TARGET_DIR}/*`);
}
async function checkoutUpstream() {
// Path of deno_webgpu inside the TAR
const tarPrefix = `gfx-rs-wgpu-${COMMIT.slice(0, 7)}/deno_webgpu/`;
const cmd =
`curl -L https://api.github.com/repos/${REPO}/tarball/${COMMIT} | tar -C '${TARGET_DIR}' -xzvf - --strip=2 '${tarPrefix}'`;
// console.log(cmd);
await bash(cmd);
}
async function denoCoreVersion() {
const coreCargo = join(ROOT_PATH, "core", "Cargo.toml");
const contents = await Deno.readTextFile(coreCargo);
return contents.match(/^version = "(\d+\.\d+\.\d+)"$/m)[1];
}
async function patchCargo() {
const vDenoCore = await denoCoreVersion();
const webgpuCargo = join(ROOT_PATH, "ext", "webgpu", "Cargo.toml");
const data = await Deno.readTextFile(webgpuCargo);
// Patch ext/webgpu/Cargo.toml's contents
const patched = data
.replace(`version = "0.17.0"`, `version = "0.33.0"`)
.replace(`edition = "2018"`, `edition = "2021"`)
.replace(
/^deno_core \= .*$/gm,
`deno_core = { version = "${vDenoCore}", path = "../../core" }`,
)
// .replace(/^wgpu-core \= .*$/gm, `wgpu-core = { version = "${V_WGPU}", features = ["trace", "replay", "serde"] }`)
// .replace(/^wgpu-types \= .*$/gm, `wgpu-types = { version = "${V_WGPU}", features = ["trace", "replay", "serde"] }`)
.replace(
/^wgpu-core \= .*$/gm,
`wgpu-core = { git = "https://github.com/${REPO}", rev = "${COMMIT}", features = ["trace", "replay", "serde"] }`,
)
.replace(
/^wgpu-types \= .*$/gm,
`wgpu-types = { git = "https://github.com/${REPO}", rev = "${COMMIT}", features = ["trace", "replay", "serde"] }`,
);
await Deno.writeTextFile(webgpuCargo, patched);
}
async function patchSrcLib() {
const srcLib = join(ROOT_PATH, "ext", "webgpu", "src", "lib.rs");
const data = await Deno.readTextFile(srcLib);
// Patch ext/webgpu/src/lib.rs's contents
const patched = data
.replace(`prefix "deno:deno_webgpu",`, `prefix "deno:ext/webgpu",`);
await Deno.writeTextFile(srcLib, patched);
}
async function main() {
await clearTargetDir();
await checkoutUpstream();
await patchCargo();
await patchSrcLib();
await bash(join(ROOT_PATH, "tools", "format.js"));
}
await main();