From 9404dfc8cbf5929f2f422a5fec143f2a9cbb0a48 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Fri, 17 Jan 2025 23:45:55 +0100 Subject: [PATCH] move surface and byow to objectwrap --- Cargo.lock | 225 ++++++++++--------- ext/webgpu/01_webgpu.js | 78 +------ ext/webgpu/02_surface.js | 194 +---------------- ext/webgpu/byow.rs | 213 +++++++++++++----- ext/webgpu/device.rs | 5 + ext/webgpu/lib.rs | 9 +- ext/webgpu/surface.rs | 309 +++++++++++++++++---------- runtime/js/90_deno_ns.js | 4 +- runtime/js/98_global_scope_shared.js | 4 +- 9 files changed, 505 insertions(+), 536 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd16ac1b7e..b83f3b4425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,11 +212,11 @@ dependencies = [ [[package]] name = "ash" -version = "0.37.3+1.3.251" +version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.7.4", + "libloading 0.8.5", ] [[package]] @@ -231,7 +231,7 @@ dependencies = [ "nom 7.1.3", "num-traits", "rusticata-macros", - "thiserror 1.0.64", + "thiserror 1.0.69", "time", ] @@ -525,7 +525,16 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "bit-vec", + "bit-vec 0.6.3", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec 0.8.0", ] [[package]] @@ -534,6 +543,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -646,9 +661,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -1155,17 +1170,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "d3d12" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" -dependencies = [ - "bitflags 2.6.0", - "libloading 0.8.5", - "winapi", -] - [[package]] name = "darling" version = "0.20.10" @@ -1480,7 +1484,7 @@ dependencies = [ "serde_json", "sha2", "sys_traits", - "thiserror 1.0.64", + "thiserror 1.0.69", "url", ] @@ -1533,14 +1537,12 @@ dependencies = [ [[package]] name = "deno_core" version = "0.331.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2d1779358cad2bc56d71176298767be628d707bb75585f6f8a4be2da8ccda1" dependencies = [ "anyhow", "az", "bincode", - "bit-set", - "bit-vec", + "bit-set 0.5.3", + "bit-vec 0.6.3", "bytes", "capacity_builder 0.1.3", "cooked-waker", @@ -2152,8 +2154,6 @@ dependencies = [ [[package]] name = "deno_ops" version = "0.207.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96f000a21f6969b4c945bc8e9e785aa439f11ca4fd3fbddcd5bebc102167eb37" dependencies = [ "indexmap 2.3.0", "proc-macro-rules", @@ -2392,7 +2392,7 @@ dependencies = [ "nix", "os_pipe", "path-dedot", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", "windows-sys 0.59.0", ] @@ -2533,8 +2533,10 @@ version = "0.153.0" dependencies = [ "deno_core", "deno_error", + "indexmap 2.3.0", "raw-window-handle", "serde", + "serde_json", "thiserror 2.0.3", "tokio", "wgpu-core", @@ -2864,9 +2866,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] @@ -3103,7 +3105,7 @@ dependencies = [ "debug-ignore", "indexmap 2.3.0", "log", - "thiserror 1.0.64", + "thiserror 1.0.69", "zerocopy", ] @@ -3250,7 +3252,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0678ab2d46fa5195aaf59ad034c083d351377d4af57f3e073c074d0da3e3c766" dependencies = [ - "bit-set", + "bit-set 0.5.3", "regex", ] @@ -3263,7 +3265,7 @@ dependencies = [ "anyhow", "async-trait", "log", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", "tokio-stream", ] @@ -3298,7 +3300,7 @@ dependencies = [ "rand", "sha1", "simdutf8", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", "utf-8", ] @@ -3356,7 +3358,7 @@ dependencies = [ "deno_terminal 0.1.1", "parking_lot", "regex", - "thiserror 1.0.64", + "thiserror 1.0.69", ] [[package]] @@ -3705,9 +3707,9 @@ dependencies = [ [[package]] name = "glow" -version = "0.13.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" dependencies = [ "js-sys", "slotmap", @@ -3717,9 +3719,9 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" dependencies = [ "gl_generator", ] @@ -3743,6 +3745,18 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows 0.58.0", +] + [[package]] name = "gpu-descriptor" version = "0.3.0" @@ -3843,7 +3857,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror 1.0.64", + "thiserror 1.0.69", ] [[package]] @@ -4614,10 +4628,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -4649,7 +4664,7 @@ dependencies = [ "anyhow", "serde", "serde_json", - "thiserror 1.0.64", + "thiserror 1.0.69", "uuid", ] @@ -5023,9 +5038,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" dependencies = [ "bitflags 2.6.0", "block", @@ -5091,7 +5106,7 @@ dependencies = [ "rustc_version 0.4.0", "smallvec", "tagptr", - "thiserror 1.0.64", + "thiserror 1.0.69", "uuid", ] @@ -5109,23 +5124,23 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "naga" -version = "0.20.0" +version = "23.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f" dependencies = [ "arrayvec", - "bit-set", + "bit-set 0.8.0", "bitflags 2.6.0", + "cfg_aliases 0.1.1", "codespan-reporting", "hexf-parse", "indexmap 2.3.0", "log", - "num-traits", "rustc-hash 1.1.0", "serde", "spirv", "termcolor", - "thiserror 1.0.64", + "thiserror 1.0.69", "unicode-xid", ] @@ -5424,7 +5439,7 @@ dependencies = [ "js-sys", "once_cell", "pin-project-lite", - "thiserror 1.0.64", + "thiserror 1.0.69", ] [[package]] @@ -5454,7 +5469,7 @@ dependencies = [ "opentelemetry_sdk", "prost", "serde_json", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", "tonic", "tracing", @@ -5496,7 +5511,7 @@ dependencies = [ "percent-encoding", "rand", "serde_json", - "thiserror 1.0.64", + "thiserror 1.0.69", "tracing", ] @@ -5686,7 +5701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", - "thiserror 1.0.64", + "thiserror 1.0.69", "ucd-trie", ] @@ -5905,6 +5920,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -6116,7 +6137,7 @@ dependencies = [ "indexmap 2.3.0", "quick-xml", "strip-ansi-escapes", - "thiserror 1.0.64", + "thiserror 1.0.69", "uuid", ] @@ -6312,7 +6333,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.64", + "thiserror 1.0.69", ] [[package]] @@ -6861,9 +6882,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.205" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] @@ -6900,9 +6921,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -6948,8 +6969,6 @@ dependencies = [ [[package]] name = "serde_v8" version = "0.240.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0494d74c40ab94f53a19485de359ea6a55f05341b817b93440b673c1ce8ec6" dependencies = [ "deno_error", "num-bigint", @@ -7988,11 +8007,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.64", + "thiserror-impl 1.0.69", ] [[package]] @@ -8006,9 +8025,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -8178,7 +8197,7 @@ checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" dependencies = [ "either", "futures-util", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", ] @@ -8515,9 +8534,9 @@ checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -8634,7 +8653,7 @@ dependencies = [ "indexmap 2.3.0", "num-bigint", "serde", - "thiserror 1.0.64", + "thiserror 1.0.69", "wtf8", ] @@ -8729,23 +8748,24 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn 2.0.87", @@ -8766,9 +8786,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8776,9 +8796,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -8789,9 +8809,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-streams" @@ -8818,9 +8841,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -8856,15 +8879,14 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.21.1" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a" dependencies = [ "arrayvec", - "bit-vec", + "bit-vec 0.8.0", "bitflags 2.6.0", "cfg_aliases 0.1.1", - "codespan-reporting", "document-features", "indexmap 2.3.0", "log", @@ -8877,30 +8899,30 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "smallvec", - "thiserror 1.0.64", - "web-sys", + "thiserror 1.0.69", "wgpu-hal", "wgpu-types", ] [[package]] name = "wgpu-hal" -version = "0.21.1" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821" dependencies = [ "android_system_properties", "arrayvec", "ash", - "bit-set", + "bit-set 0.8.0", "bitflags 2.6.0", "block", + "bytemuck", "cfg_aliases 0.1.1", "core-graphics-types", - "d3d12", "glow", "glutin_wgl_sys", "gpu-alloc", + "gpu-allocator", "gpu-descriptor", "js-sys", "khronos-egl", @@ -8918,18 +8940,19 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror 1.0.64", + "thiserror 1.0.69", "wasm-bindgen", "web-sys", "wgpu-types", - "winapi", + "windows 0.58.0", + "windows-core 0.58.0", ] [[package]] name = "wgpu-types" -version = "0.20.0" +version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068" dependencies = [ "bitflags 2.6.0", "js-sys", @@ -8972,7 +8995,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b2b1bf557d947847a30eb73f79aa6cdb3eaf3ce02f5e9599438f77896a62b3c" dependencies = [ - "thiserror 1.0.64", + "thiserror 1.0.69", "windows 0.52.0", ] @@ -9334,7 +9357,7 @@ dependencies = [ "nom 7.1.3", "oid-registry", "rusticata-macros", - "thiserror 1.0.64", + "thiserror 1.0.69", "time", ] @@ -9478,7 +9501,7 @@ dependencies = [ "parking_lot", "rand", "regex", - "thiserror 1.0.64", + "thiserror 1.0.69", "tokio", "tokio-util", "uuid", @@ -9519,7 +9542,7 @@ dependencies = [ "flate2", "indexmap 2.3.0", "memchr", - "thiserror 1.0.64", + "thiserror 1.0.69", ] [[package]] diff --git a/ext/webgpu/01_webgpu.js b/ext/webgpu/01_webgpu.js index c28cffc40e..bb6531aa02 100644 --- a/ext/webgpu/01_webgpu.js +++ b/ext/webgpu/01_webgpu.js @@ -690,9 +690,7 @@ ObjectDefineProperty(GPUQuerySet, customInspect, { const GPUQuerySetPrototype = GPUQuerySet.prototype; // Converters -/* -// DICTIONARY: GPUPipelineErrorInit webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter( "GPUPipelineErrorInit", [ @@ -704,7 +702,6 @@ webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter( ], ); -// ENUM: GPUPipelineErrorReason webidl.converters["GPUPipelineErrorReason"] = webidl.createEnumConverter( "GPUPipelineErrorReason", [ @@ -713,16 +710,8 @@ webidl.converters["GPUPipelineErrorReason"] = webidl.createEnumConverter( ], ); -// TYPEDEF: GPUError -webidl.converters["GPUError"] = webidl.converters.any /!** put union here! **!/; +webidl.converters["GPUError"] = webidl.converters.any /* put union here! */; -// // INTERFACE: GPUUncapturedErrorEvent -// webidl.converters.GPUUncapturedErrorEvent = webidl.createInterfaceConverter( -// "GPUUncapturedErrorEvent", -// GPUUncapturedErrorEvent.prototype, -// ); - -// DICTIONARY: GPUUncapturedErrorEventInit const dictMembersGPUUncapturedErrorEventInit = [ { key: "error", converter: webidl.converters["GPUError"], required: true }, ]; @@ -733,71 +722,6 @@ webidl.converters["GPUUncapturedErrorEventInit"] = webidl dictMembersGPUUncapturedErrorEventInit, ); -// BYOW - -// ENUM: GPUCanvasAlphaMode -webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter( - "GPUCanvasAlphaMode", - [ - "opaque", - "premultiplied", - ], -); - -// NON-SPEC: ENUM: GPUPresentMode -webidl.converters["GPUPresentMode"] = webidl.createEnumConverter( - "GPUPresentMode", - [ - "autoVsync", - "autoNoVsync", - "fifo", - "fifoRelaxed", - "immediate", - "mailbox", - ], -); - -// DICT: GPUCanvasConfiguration -const dictMembersGPUCanvasConfiguration = [ - { key: "device", converter: webidl.converters.GPUDevice, required: true }, - { - key: "format", - converter: webidl.converters.GPUTextureFormat, - required: true, - }, - { - key: "usage", - converter: webidl.converters["GPUTextureUsageFlags"], - defaultValue: GPUTextureUsage.RENDER_ATTACHMENT, - }, - { - key: "alphaMode", - converter: webidl.converters["GPUCanvasAlphaMode"], - defaultValue: "opaque", - }, - - // Extended from spec - { - key: "presentMode", - converter: webidl.converters["GPUPresentMode"], - }, - { - key: "viewFormats", - converter: webidl.createSequenceConverter( - webidl.converters["GPUTextureFormat"], - ), - get defaultValue() { - return []; - }, - }, -]; -webidl.converters["GPUCanvasConfiguration"] = webidl - .createDictionaryConverter( - "GPUCanvasConfiguration", - dictMembersGPUCanvasConfiguration, - ); -*/ - let gpu; function initGPU() { if (!gpu) { diff --git a/ext/webgpu/02_surface.js b/ext/webgpu/02_surface.js index b0561469a9..763c4fc56c 100644 --- a/ext/webgpu/02_surface.js +++ b/ext/webgpu/02_surface.js @@ -7,146 +7,16 @@ /// import { primordials } from "ext:core/mod.js"; -import { - op_webgpu_surface_configure, - op_webgpu_surface_create, - op_webgpu_surface_get_current_texture, - op_webgpu_surface_present, -} from "ext:core/ops"; +import { GPUCanvasContext, UnsafeWindowSurface } from "ext:core/ops"; const { + ObjectDefineProperty, ObjectPrototypeIsPrototypeOf, - Symbol, SymbolFor, - TypeError, } = primordials; - -import * as webidl from "ext:deno_webidl/00_webidl.js"; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; -import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; -const _surfaceRid = Symbol("[[surfaceRid]]"); -const _configuration = Symbol("[[configuration]]"); -const _canvas = Symbol("[[canvas]]"); -const _currentTexture = Symbol("[[currentTexture]]"); -const _present = Symbol("[[present]]"); -const _dim = Symbol("[[dimensions]]"); - -class GPUCanvasContext { - /** @type {number} */ - [_surfaceRid]; - [_configuration]; - [_canvas]; - /** @type {GPUTexture | undefined} */ - [_currentTexture]; - [_dim]; - - get canvas() { - webidl.assertBranded(this, GPUCanvasContextPrototype); - return this[_canvas]; - } - - constructor() { - webidl.illegalConstructor(); - } - - configure(configuration) { - webidl.assertBranded(this, GPUCanvasContextPrototype); - const prefix = "Failed to execute 'configure' on 'GPUCanvasContext'"; - webidl.requiredArguments(arguments.length, 1, { prefix }); - configuration = webidl.converters.GPUCanvasConfiguration(configuration, { - prefix, - context: "Argument 1", - }); - - const { _device, assertDevice } = loadWebGPU(); - this[_device] = configuration.device[_device]; - this[_configuration] = configuration; - const device = assertDevice(this, { - prefix, - context: "configuration.device", - }); - - const { err } = op_webgpu_surface_configure({ - surfaceRid: this[_surfaceRid], - deviceRid: device.rid, - format: configuration.format, - viewFormats: configuration.viewFormats, - usage: configuration.usage, - width: this[_dim].width, - height: this[_dim].height, - alphaMode: configuration.alphaMode, - }); - - device.pushError(err); - } - - unconfigure() { - const { _device } = loadWebGPU(); - - webidl.assertBranded(this, GPUCanvasContextPrototype); - - this[_configuration] = null; - this[_device] = null; - } - - getCurrentTexture() { - webidl.assertBranded(this, GPUCanvasContextPrototype); - const prefix = - "Failed to execute 'getCurrentTexture' on 'GPUCanvasContext'"; - - if (this[_configuration] === null) { - throw new DOMException("Context is not configured", "InvalidStateError"); - } - const { createGPUTexture, assertDevice } = loadWebGPU(); - - const device = assertDevice(this, { prefix, context: "this" }); - - if (this[_currentTexture]) { - return this[_currentTexture]; - } - - const { rid } = op_webgpu_surface_get_current_texture( - device.rid, - this[_surfaceRid], - ); - - const texture = createGPUTexture( - { - size: { - width: this[_dim].width, - height: this[_dim].height, - depthOrArrayLayers: 1, - }, - mipLevelCount: 1, - sampleCount: 1, - dimension: "2d", - format: this[_configuration].format, - usage: this[_configuration].usage, - }, - device, - rid, - ); - device.trackResource(texture); - this[_currentTexture] = texture; - return texture; - } - - // Required to present the texture; browser don't need this. - [_present]() { - const { assertDevice } = loadWebGPU(); - - webidl.assertBranded(this, GPUCanvasContextPrototype); - const prefix = "Failed to execute 'present' on 'GPUCanvasContext'"; - const device = assertDevice(this[_currentTexture], { - prefix, - context: "this", - }); - op_webgpu_surface_present(device.rid, this[_surfaceRid]); - this[_currentTexture].destroy(); - this[_currentTexture] = undefined; - } - - [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { +ObjectDefineProperty(GPUCanvasContext, SymbolFor("Deno.privateCustomInspect"), { + value(inspect, inspectOptions) { return inspect( createFilteredInspectProxy({ object: this, @@ -157,60 +27,8 @@ class GPUCanvasContext { }), inspectOptions, ); - } -} + }, +}); const GPUCanvasContextPrototype = GPUCanvasContext.prototype; -function createCanvasContext(options) { - // lazy load webgpu if needed - const canvasContext = webidl.createBranded(GPUCanvasContext); - canvasContext[_surfaceRid] = options.surfaceRid; - canvasContext[_canvas] = options.canvas; - canvasContext[_dim] = { width: options.width, height: options.height }; - - return canvasContext; -} - -// External webgpu surfaces - -// TODO(@littledivy): This will extend `OffscreenCanvas` when we add it. -class UnsafeWindowSurface { - #ctx; - #surfaceRid; - #options; - - constructor(options) { - if (typeof options !== "object") { - throw new TypeError("options must be provided."); - } - if ( - typeof options.width !== "number" || typeof options.height !== "number" - ) { - throw new TypeError("width and height must be provided."); - } - - this.#surfaceRid = op_webgpu_surface_create( - options.system, - options.windowHandle, - options.displayHandle, - ); - this.#options = options; - } - - getContext(context) { - if (context !== "webgpu") { - throw new TypeError("Only 'webgpu' context is supported"); - } - this.#ctx = createCanvasContext({ - surfaceRid: this.#surfaceRid, - ...this.#options, - }); - return this.#ctx; - } - - present() { - this.#ctx[_present](); - } -} - export { GPUCanvasContext, UnsafeWindowSurface }; diff --git a/ext/webgpu/byow.rs b/ext/webgpu/byow.rs index e911e1402b..84e97a1460 100644 --- a/ext/webgpu/byow.rs +++ b/ext/webgpu/byow.rs @@ -1,5 +1,4 @@ -// Copyright 2018-2025 the Deno authors. MIT license. - +use std::cell::RefCell; use std::ffi::c_void; #[cfg(any( target_os = "linux", @@ -9,11 +8,17 @@ use std::ffi::c_void; ))] use std::ptr::NonNull; +use deno_core::cppgc::SameObject; use deno_core::op2; +use deno_core::v8; +use deno_core::v8::Local; +use deno_core::v8::Value; +use deno_core::FromV8; +use deno_core::GarbageCollected; use deno_core::OpState; -use deno_core::ResourceId; +use deno_error::JsErrorBox; -use crate::surface::WebGpuSurface; +use crate::surface::GPUCanvasContext; #[derive(Debug, thiserror::Error, deno_error::JsError)] pub enum ByowError { @@ -65,46 +70,156 @@ pub enum ByowError { NSViewDisplay, } -#[op2(fast)] -#[smi] -pub fn op_webgpu_surface_create( - state: &mut OpState, - #[string] system: &str, - p1: *const c_void, - p2: *const c_void, -) -> Result { - let instance = state - .try_borrow::() - .ok_or(ByowError::WebGPUNotInitiated)?; - // Security note: - // - // The `p1` and `p2` parameters are pointers to platform-specific window - // handles. - // - // The code below works under the assumption that: - // - // - handles can only be created by the FFI interface which - // enforces --allow-ffi. - // - // - `*const c_void` deserizalizes null and v8::External. - // - // - Only FFI can export v8::External to user code. - if p1.is_null() { - return Err(ByowError::InvalidParameters); +// TODO(@littledivy): This will extend `OffscreenCanvas` when we add it. +pub struct UnsafeWindowSurface { + pub id: wgpu_core::id::SurfaceId, + pub width: RefCell, + pub height: RefCell, + + pub context: SameObject, +} + +impl GarbageCollected for UnsafeWindowSurface {} + +#[op2] +impl UnsafeWindowSurface { + #[constructor] + #[cppgc] + fn new( + state: &mut OpState, + #[from_v8] options: UnsafeWindowSurfaceOptions, + ) -> Result { + let instance = state + .try_borrow::() + .ok_or(ByowError::WebGPUNotInitiated)?; + + // Security note: + // + // The `window_handle` and `display_handle` options are pointers to + // platform-specific window handles. + // + // The code below works under the assumption that: + // + // - handles can only be created by the FFI interface which + // enforces --allow-ffi. + // + // - `*const c_void` deserizalizes null and v8::External. + // + // - Only FFI can export v8::External to user code. + if options.window_handle.is_null() { + return Err(ByowError::InvalidParameters); + } + + let (win_handle, display_handle) = raw_window( + options.system, + options.window_handle, + options.display_handle, + )?; + + // SAFETY: see above comment + let id = unsafe { + instance + .instance_create_surface(display_handle, win_handle, None) + .map_err(ByowError::CreateSurface)? + }; + + Ok(UnsafeWindowSurface { + id, + width: RefCell::new(options.width), + height: RefCell::new(options.height), + context: SameObject::new(), + }) } - let (win_handle, display_handle) = raw_window(system, p1, p2)?; - // SAFETY: see above comment - let surface = unsafe { - instance - .instance_create_surface(display_handle, win_handle, None) - .map_err(ByowError::CreateSurface)? - }; + #[global] + fn get_context(&self, scope: &mut v8::HandleScope) -> v8::Global { + self.context.get(scope, |_| GPUCanvasContext { + surface_id: self.id, + width: self.width.clone(), + height: self.height.clone(), + config: RefCell::new(None), + texture: RefCell::new(None), + }) + } - let rid = state - .resource_table - .add(WebGpuSurface(instance.clone(), surface)); - Ok(rid) + #[nofast] + fn present(&self, scope: &mut v8::HandleScope) -> Result<(), JsErrorBox> { + let Some(context) = self.context.value(scope) else { + return Err(JsErrorBox::type_error("getContext was never called")); + }; + + context.present().map_err(JsErrorBox::from_err) + } +} + +struct UnsafeWindowSurfaceOptions { + system: UnsafeWindowSurfaceSystem, + window_handle: *const c_void, + display_handle: *const c_void, + width: u32, + height: u32, +} + +#[derive(Eq, PartialEq)] +enum UnsafeWindowSurfaceSystem { + Cocoa, + Win32, + X11, + Wayland, +} + +impl<'a> FromV8<'a> for UnsafeWindowSurfaceOptions { + type Error = JsErrorBox; + + fn from_v8( + scope: &mut v8::HandleScope<'a>, + value: Local<'a, Value>, + ) -> Result { + let obj = value.try_cast::().unwrap(); + + let key = v8::String::new(scope, "system").unwrap(); + let val = obj.get(scope, key.into()).unwrap(); + let s = String::from_v8(scope, val).unwrap(); + let system = match s.as_str() { + "cocoa" => UnsafeWindowSurfaceSystem::Cocoa, + "win32" => UnsafeWindowSurfaceSystem::Win32, + "x11" => UnsafeWindowSurfaceSystem::X11, + "wayland" => UnsafeWindowSurfaceSystem::Wayland, + _ => { + return Err(JsErrorBox::type_error(format!( + "Invalid system kind '{s}'" + ))) + } + }; + + let key = v8::String::new(scope, "windowHandle").unwrap(); + let val = obj.get(scope, key.into()).unwrap(); + let Some(window_handle) = deno_core::_ops::to_external_option(&val) else { + return Err(JsErrorBox::type_error("expected external")); + }; + + let key = v8::String::new(scope, "displayHandle").unwrap(); + let val = obj.get(scope, key.into()).unwrap(); + let Some(display_handle) = deno_core::_ops::to_external_option(&val) else { + return Err(JsErrorBox::type_error("expected external")); + }; + + let key = v8::String::new(scope, "width").unwrap(); + let val = obj.get(scope, key.into()).unwrap(); + let width = deno_core::convert::Number::::from_v8(scope, val)?.0; + + let key = v8::String::new(scope, "height").unwrap(); + let val = obj.get(scope, key.into()).unwrap(); + let height = deno_core::convert::Number::::from_v8(scope, val)?.0; + + Ok(Self { + system, + window_handle, + display_handle, + width, + height, + }) + } } type RawHandles = ( @@ -114,11 +229,11 @@ type RawHandles = ( #[cfg(target_os = "macos")] fn raw_window( - system: &str, + system: UnsafeWindowSurfaceSystem, _ns_window: *const c_void, ns_view: *const c_void, ) -> Result { - if system != "cocoa" { + if system != UnsafeWindowSurfaceSystem::Cocoa { return Err(ByowError::InvalidSystem); } @@ -136,12 +251,12 @@ fn raw_window( #[cfg(target_os = "windows")] fn raw_window( - system: &str, + system: UnsafeWindowSurfaceSystem, window: *const c_void, hinstance: *const c_void, ) -> Result { use raw_window_handle::WindowsDisplayHandle; - if system != "win32" { + if system != UnsafeWindowSurfaceSystem::Win32 { return Err(ByowError::InvalidSystem); } @@ -162,12 +277,12 @@ fn raw_window( #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] fn raw_window( - system: &str, + system: UnsafeWindowSurfaceSystem, window: *const c_void, display: *const c_void, ) -> Result { let (win_handle, display_handle); - if system == "x11" { + if system == UnsafeWindowSurfaceSystem::X11 { win_handle = raw_window_handle::RawWindowHandle::Xlib( raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _), ); @@ -178,7 +293,7 @@ fn raw_window( 0, ), ); - } else if system == "wayland" { + } else if system == UnsafeWindowSurfaceSystem::Wayland { win_handle = raw_window_handle::RawWindowHandle::Wayland( raw_window_handle::WaylandWindowHandle::new( NonNull::new(window as *mut c_void).ok_or(ByowError::NullWindow)?, @@ -205,7 +320,7 @@ fn raw_window( target_os = "openbsd", )))] fn raw_window( - _system: &str, + _system: UnsafeWindowSurfaceSystem, _window: *const c_void, _display: *const c_void, ) -> Result { diff --git a/ext/webgpu/device.rs b/ext/webgpu/device.rs index e2adcbbe8d..09a44235c3 100644 --- a/ext/webgpu/device.rs +++ b/ext/webgpu/device.rs @@ -6,6 +6,7 @@ use std::rc::Rc; use deno_core::cppgc::SameObject; use deno_core::op2; use deno_core::v8; +use deno_core::webidl::WebIdlInterfaceConverter; use deno_core::GarbageCollected; use deno_error::JsErrorBox; use wgpu_core::binding_model::BindingResource; @@ -57,6 +58,10 @@ impl Drop for GPUDevice { } } +impl WebIdlInterfaceConverter for GPUDevice { + const NAME: &'static str = "GPUDevice"; +} + impl GarbageCollected for GPUDevice {} // TODO: extend EventTarget diff --git a/ext/webgpu/lib.rs b/ext/webgpu/lib.rs index ff37eb765c..4535c0296b 100644 --- a/ext/webgpu/lib.rs +++ b/ext/webgpu/lib.rs @@ -18,6 +18,7 @@ mod adapter; mod bind_group; mod bind_group_layout; mod buffer; +mod byow; mod command_buffer; mod command_encoder; mod compute_pass; @@ -32,14 +33,12 @@ mod render_pass; mod render_pipeline; mod sampler; mod shader; +mod surface; mod texture; mod webidl; pub const UNSTABLE_FEATURE_NAME: &str = "webgpu"; -//pub mod byow; -//pub mod surface; - pub type Instance = Arc; deno_core::extension!( @@ -72,8 +71,10 @@ deno_core::extension!( adapter::GPUSupportedLimits, texture::GPUTexture, texture::GPUTextureView, + byow::UnsafeWindowSurface, + surface::GPUCanvasContext, ], - esm = ["00_init.js"], + esm = ["00_init.js", "02_surface.js"], lazy_loaded_esm = ["01_webgpu.js"], ); diff --git a/ext/webgpu/surface.rs b/ext/webgpu/surface.rs index 054d6766a9..934a914047 100644 --- a/ext/webgpu/surface.rs +++ b/ext/webgpu/surface.rs @@ -1,146 +1,229 @@ -// Copyright 2018-2025 the Deno authors. MIT license. +use std::cell::RefCell; -use std::borrow::Cow; -use std::rc::Rc; - -use deno_core::error::ResourceError; use deno_core::op2; -use deno_core::OpState; -use deno_core::Resource; -use deno_core::ResourceId; +use deno_core::v8; +use deno_core::GarbageCollected; +use deno_core::WebIDL; +use deno_core::_ops::make_cppgc_object; +use deno_core::cppgc::Ptr; use deno_error::JsErrorBox; -use serde::Deserialize; use wgpu_types::SurfaceStatus; -use crate::error::WebGpuResult; +use crate::device::GPUDevice; +use crate::texture::GPUTexture; +use crate::texture::GPUTextureFormat; #[derive(Debug, thiserror::Error, deno_error::JsError)] pub enum SurfaceError { - #[class(inherit)] - #[error(transparent)] - Resource( - #[from] - #[inherit] - ResourceError, - ), + #[class("DOMExceptionInvalidStateError")] + #[error("Context is not configured")] + UnconfiguredContext, #[class(generic)] #[error("Invalid Surface Status")] InvalidStatus, #[class(generic)] #[error(transparent)] - Surface(wgpu_core::present::SurfaceError), + Surface(#[from] wgpu_core::present::SurfaceError), } -pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId); -impl Resource for WebGpuSurface { - fn name(&self) -> Cow { - "webGPUSurface".into() - } - - fn close(self: Rc) { - self.0.surface_drop(self.1); - } +pub struct Configuration { + pub device: Ptr, + pub usage: u32, + pub format: GPUTextureFormat, } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SurfaceConfigureArgs { - surface_rid: ResourceId, - device_rid: ResourceId, - format: wgpu_types::TextureFormat, - usage: u32, - width: u32, - height: u32, - present_mode: Option, - alpha_mode: wgpu_types::CompositeAlphaMode, - view_formats: Vec, +pub struct GPUCanvasContext { + pub surface_id: wgpu_core::id::SurfaceId, + pub width: RefCell, + pub height: RefCell, + + pub config: RefCell>, + pub texture: RefCell>>, } +impl GarbageCollected for GPUCanvasContext {} + #[op2] -#[serde] -pub fn op_webgpu_surface_configure( - state: &mut OpState, - #[serde] args: SurfaceConfigureArgs, -) -> Result { - let instance = state.borrow::(); - let device_resource = state - .resource_table - .get::(args.device_rid)?; - let device = device_resource.1; - let surface_resource = state - .resource_table - .get::(args.surface_rid)?; - let surface = surface_resource.1; +impl GPUCanvasContext { + #[getter] + #[global] + fn canvas(&self) -> v8::Global { + todo!() + } - let conf = wgpu_types::SurfaceConfiguration::> { - usage: wgpu_types::TextureUsages::from_bits(args.usage) - .ok_or_else(|| JsErrorBox::type_error("usage is not valid"))?, - format: args.format, - width: args.width, - height: args.height, - present_mode: args.present_mode.unwrap_or_default(), - alpha_mode: args.alpha_mode, - view_formats: args.view_formats, - desired_maximum_frame_latency: 2, - }; + fn configure( + &self, + #[webidl] configuration: GPUCanvasConfiguration, + ) -> Result<(), JsErrorBox> { + let usage = wgpu_types::TextureUsages::from_bits(configuration.usage) + .ok_or_else(|| JsErrorBox::type_error("usage is not valid"))?; + let format = configuration.format.clone().into(); + let conf = wgpu_types::SurfaceConfiguration { + usage, + format, + width: *self.width.borrow(), + height: *self.height.borrow(), + present_mode: configuration + .present_mode + .map(Into::into) + .unwrap_or_default(), + alpha_mode: configuration.alpha_mode.into(), + view_formats: configuration + .view_formats + .into_iter() + .map(Into::into) + .collect(), + desired_maximum_frame_latency: 2, + }; - let err = - gfx_select!(device => instance.surface_configure(surface, device, &conf)); + let device = configuration.device; - Ok(WebGpuResult::maybe_err(err)) -} + let err = + device + .instance + .surface_configure(self.surface_id, device.id, &conf); -#[op2] -#[serde] -pub fn op_webgpu_surface_get_current_texture( - state: &mut OpState, - #[smi] device_rid: ResourceId, - #[smi] surface_rid: ResourceId, -) -> Result { - let instance = state.borrow::(); - let device_resource = state - .resource_table - .get::(device_rid)?; - let device = device_resource.1; - let surface_resource = - state.resource_table.get::(surface_rid)?; - let surface = surface_resource.1; + device.error_handler.push_error(err); - let output = - gfx_select!(device => instance.surface_get_current_texture(surface, None)) - .map_err(SurfaceError::Surface)?; + self.config.borrow_mut().replace(Configuration { + device, + usage: configuration.usage, + format: configuration.format, + }); - match output.status { - SurfaceStatus::Good | SurfaceStatus::Suboptimal => { - let id = output.texture_id.unwrap(); - let rid = state.resource_table.add(crate::texture::WebGpuTexture { - instance: instance.clone(), - id, - owned: false, - }); - Ok(WebGpuResult::rid(rid)) + Ok(()) + } + + #[fast] + fn unconfigure(&self) { + *self.config.borrow_mut() = None; + } + + #[global] + fn get_current_texture( + &self, + scope: &mut v8::HandleScope, + ) -> Result, SurfaceError> { + let config = self.config.borrow(); + let Some(config) = config.as_ref() else { + return Err(SurfaceError::UnconfiguredContext); + }; + + { + if let Some(obj) = self.texture.borrow().as_ref() { + return Ok(obj.clone()); + } + } + + let output = config + .device + .instance + .surface_get_current_texture(self.surface_id, None)?; + + match output.status { + SurfaceStatus::Good | SurfaceStatus::Suboptimal => { + let id = output.texture_id.unwrap(); + + let texture = GPUTexture { + instance: config.device.instance.clone(), + error_handler: config.device.error_handler.clone(), + id, + label: "".to_string(), + size: wgpu_types::Extent3d { + width: *self.width.borrow(), + height: *self.height.borrow(), + depth_or_array_layers: 1, + }, + mip_level_count: 0, + sample_count: 0, + dimension: crate::texture::GPUTextureDimension::D2, + format: config.format.clone(), + usage: config.usage, + }; + let obj = make_cppgc_object(scope, texture); + let obj = v8::Global::new(scope, obj); + *self.texture.borrow_mut() = Some(obj.clone()); + + Ok(obj) + } + _ => Err(SurfaceError::InvalidStatus), } - _ => Err(SurfaceError::InvalidStatus), } } -#[op2(fast)] -pub fn op_webgpu_surface_present( - state: &mut OpState, - #[smi] device_rid: ResourceId, - #[smi] surface_rid: ResourceId, -) -> Result<(), SurfaceError> { - let instance = state.borrow::(); - let device_resource = state - .resource_table - .get::(device_rid)?; - let device = device_resource.1; - let surface_resource = - state.resource_table.get::(surface_rid)?; - let surface = surface_resource.1; +impl GPUCanvasContext { + pub fn present(&self) -> Result<(), SurfaceError> { + let config = self.config.borrow(); + let Some(config) = config.as_ref() else { + return Err(SurfaceError::UnconfiguredContext); + }; - let _ = gfx_select!(device => instance.surface_present(surface)) - .map_err(SurfaceError::Surface)?; + config.device.instance.surface_present(self.surface_id)?; - Ok(()) + Ok(()) + } +} + +#[derive(WebIDL)] +#[webidl(dictionary)] +struct GPUCanvasConfiguration { + device: Ptr, + format: GPUTextureFormat, + #[webidl(default = wgpu_types::TextureUsages::RENDER_ATTACHMENT.bits())] + #[options(enforce_range = true)] + usage: u32, + #[webidl(default = GPUCanvasAlphaMode::Opaque)] + alpha_mode: GPUCanvasAlphaMode, + + // Extended from spec + present_mode: Option, + #[webidl(default = vec![])] + view_formats: Vec, +} + +#[derive(WebIDL)] +#[webidl(enum)] +enum GPUCanvasAlphaMode { + Opaque, + Premultiplied, +} + +impl From for wgpu_types::CompositeAlphaMode { + fn from(value: GPUCanvasAlphaMode) -> Self { + match value { + GPUCanvasAlphaMode::Opaque => Self::Opaque, + GPUCanvasAlphaMode::Premultiplied => Self::PreMultiplied, + } + } +} + +// Extended from spec +#[derive(WebIDL)] +#[webidl(enum)] +enum GPUPresentMode { + #[webidl(rename = "autoVsync")] + AutoVsync, + #[webidl(rename = "autoNoVsync")] + AutoNoVsync, + #[webidl(rename = "fifo")] + Fifo, + #[webidl(rename = "fifoRelaxed")] + FifoRelaxed, + #[webidl(rename = "immediate")] + Immediate, + #[webidl(rename = "mailbox")] + Mailbox, +} + +impl From for wgpu_types::PresentMode { + fn from(value: GPUPresentMode) -> Self { + match value { + GPUPresentMode::AutoVsync => Self::AutoVsync, + GPUPresentMode::AutoNoVsync => Self::AutoNoVsync, + GPUPresentMode::Fifo => Self::Fifo, + GPUPresentMode::FifoRelaxed => Self::FifoRelaxed, + GPUPresentMode::Immediate => Self::Immediate, + GPUPresentMode::Mailbox => Self::Mailbox, + } + } } diff --git a/runtime/js/90_deno_ns.js b/runtime/js/90_deno_ns.js index 1f90c13cf6..5aaf0614dc 100644 --- a/runtime/js/90_deno_ns.js +++ b/runtime/js/90_deno_ns.js @@ -28,7 +28,7 @@ import * as signals from "ext:deno_os/40_signals.js"; import * as tty from "ext:runtime/40_tty.js"; import * as kv from "ext:deno_kv/01_db.ts"; import * as cron from "ext:deno_cron/01_cron.ts"; -//import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; +import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; import * as telemetry from "ext:deno_telemetry/telemetry.ts"; const { ObjectDefineProperties } = primordials; @@ -203,7 +203,7 @@ ObjectDefineProperties(denoNsUnstableById[unstableIds.net], { // denoNsUnstableById[unstableIds.unsafeProto] = { __proto__: null } denoNsUnstableById[unstableIds.webgpu] = { - //UnsafeWindowSurface: webgpuSurface.UnsafeWindowSurface, + UnsafeWindowSurface: webgpuSurface.UnsafeWindowSurface, }; // denoNsUnstableById[unstableIds.workerOptions] = { __proto__: null } diff --git a/runtime/js/98_global_scope_shared.js b/runtime/js/98_global_scope_shared.js index ba485c6a20..99bace7647 100644 --- a/runtime/js/98_global_scope_shared.js +++ b/runtime/js/98_global_scope_shared.js @@ -35,7 +35,7 @@ import process from "node:process"; import { Buffer } from "node:buffer"; import { clearImmediate, setImmediate } from "node:timers"; import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; -//import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; +import * as webgpuSurface from "ext:deno_webgpu/02_surface.js"; import { unstableIds } from "ext:runtime/90_deno_ns.js"; const loadImage = core.createLazyLoader("ext:deno_canvas/01_image.js"); @@ -164,7 +164,7 @@ const windowOrWorkerGlobalScope = { (webgpu) => webgpu.GPUBufferUsage, loadWebGPU, ), - //GPUCanvasContext: core.propNonEnumerable(webgpuSurface.GPUCanvasContext), + GPUCanvasContext: core.propNonEnumerable(webgpuSurface.GPUCanvasContext), GPUColorWrite: core.propNonEnumerableLazyLoaded( (webgpu) => webgpu.GPUColorWrite, loadWebGPU,