diff --git a/Cargo.lock b/Cargo.lock index 149c75c385..8d07a0dcd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,6 +972,15 @@ dependencies = [ "swc_ecmascript", ] +[[package]] +name = "drm-fourcc" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbf3a5ed4671aabffefce172ff43d69c1f27dd2c6aea28e5212a70f32ada0cf" +dependencies = [ + "serde", +] + [[package]] name = "either" version = "1.6.1" @@ -1072,6 +1081,16 @@ dependencies = [ "libc", ] +[[package]] +name = "external-memory" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4dfe8d292b014422776a8c516862d2bff8a81b223a4461dfdc45f3862dc9d39" +dependencies = [ + "bitflags", + "drm-fourcc", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1359,9 +1378,9 @@ dependencies = [ [[package]] name = "gfx-auxil" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccf8711c9994dfa34337466bee3ae1462e172874c432ce4eb120ab2e98d39cf" +checksum = "1694991b11d642680e82075a75c7c2bd75556b805efa7660b705689f05b1ab1c" dependencies = [ "fxhash", "gfx-hal", @@ -1370,14 +1389,15 @@ dependencies = [ [[package]] name = "gfx-backend-dx11" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f839f27f8c8a6dc553ccca7f5b35a42009432bc25db9688bba7061cd394161f" +checksum = "8f9e453baf3aaef2b0c354ce0b3d63d76402e406a59b64b7182d123cfa6635ae" dependencies = [ "arrayvec", "bitflags", "gfx-auxil", "gfx-hal", + "gfx-renderdoc", "libloading", "log", "parking_lot", @@ -1392,9 +1412,9 @@ dependencies = [ [[package]] name = "gfx-backend-dx12" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3937738b0da5839bba4e33980d29f9a06dbce184d04a3a08c9a949e7953700e3" +checksum = "21506399f64a3c4d389182a89a30073856ae33eb712315456b4fd8f39ee7682a" dependencies = [ "arrayvec", "bit-set", @@ -1402,6 +1422,7 @@ dependencies = [ "d3d12", "gfx-auxil", "gfx-hal", + "gfx-renderdoc", "log", "parking_lot", "range-alloc", @@ -1414,9 +1435,9 @@ dependencies = [ [[package]] name = "gfx-backend-empty" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac55ada4bfcd35479b3421eea324d36d7da5f724e2f66ecb36d4efdb7041a5e" +checksum = "29c8f813c47791918aa00dc9c9ddf961d23fa8c2a5d869e6cb8ea84f944820f4" dependencies = [ "gfx-hal", "log", @@ -1425,9 +1446,9 @@ dependencies = [ [[package]] name = "gfx-backend-gl" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0caa03d6e0b7b4f202aea1f20c3f3288cfa06d92d24cea9d69c9a7627967244a" +checksum = "6bae057fc3a0ab23ecf97ae51d4017d27d5ddf0aab16ee6dcb58981af88c3152" dependencies = [ "arrayvec", "bitflags", @@ -1447,15 +1468,16 @@ dependencies = [ [[package]] name = "gfx-backend-metal" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340895ad544ba46433acb3bdabece0ef16f2dbedc030adbd7c9eaf2839fbed41" +checksum = "0de85808e2a98994c6af925253f8a9593bc57180ef1ea137deab6d35cc949517" dependencies = [ "arrayvec", "bitflags", "block", "cocoa-foundation", "copyless", + "core-graphics-types", "foreign-types", "fxhash", "gfx-hal", @@ -1472,15 +1494,16 @@ dependencies = [ [[package]] name = "gfx-backend-vulkan" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a353fc6fdb42ec646de49bbb74e4870e37a7e680caf33f3ac0615c30b1146d94" +checksum = "a9861ec855acbbc65c0e4f966d761224886e811dc2c6d413a4776e9293d0e5c0" dependencies = [ "arrayvec", "ash", "byteorder", "core-graphics-types", "gfx-hal", + "gfx-renderdoc", "inplace_it", "log", "naga", @@ -1493,16 +1516,28 @@ dependencies = [ [[package]] name = "gfx-hal" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d285bfd566f6b9134af908446ca350c0a1047495dfb9bbd826e701e8ee1d259" +checksum = "7fbb575ea793dd0507b3082f4f2cde62dc9f3cebd98f5cd49ba2a4da97a976fd" dependencies = [ "bitflags", + "external-memory", "naga", "raw-window-handle", "thiserror", ] +[[package]] +name = "gfx-renderdoc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8027995e247e2426d3a00d13f5191dd56c314bff02dc4b54cbf727f1ba9c40a" +dependencies = [ + "libloading", + "log", + "renderdoc-sys", +] + [[package]] name = "glow" version = "0.9.0" @@ -2048,13 +2083,13 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "metal" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c12e48c737ee9a55e8bb2352bcde588f79ae308d3529ee888f7cc0f469b5777" +checksum = "79d7d769f1c104b8388294d6594d491d2e21240636f5f94d37f8a0f3d7904450" dependencies = [ "bitflags", "block", - "cocoa-foundation", + "core-graphics-types", "foreign-types", "log", "objc", @@ -2100,9 +2135,9 @@ dependencies = [ [[package]] name = "naga" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f470a97eafcdd0dbea43d5e1a8ef3557aa31f49ba643d9430dbbf911c162b24c" +checksum = "ef670817eef03d356d5a509ea275e7dd3a78ea9e24261ea3cb2dfed1abb08f64" dependencies = [ "bit-set", "bitflags", @@ -2111,6 +2146,7 @@ dependencies = [ "log", "num-traits", "petgraph", + "rose_tree", "spirv_headers", "thiserror", ] @@ -2736,6 +2772,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "renderdoc-sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" + [[package]] name = "reqwest" version = "0.11.3" @@ -2815,6 +2857,15 @@ dependencies = [ "serde", ] +[[package]] +name = "rose_tree" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284de9dae38774e2813aaabd7e947b4a6fe9b8c58c2309f754a487cdd50de1c2" +dependencies = [ + "petgraph", +] + [[package]] name = "rsa" version = "0.4.0" @@ -4344,9 +4395,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56c368fc0e6f3927c711d2b55a51ad4321218efc0239c4acf69e456ab70399" +checksum = "2af5c8acd3ae5781a277cdf65a17f3a7135de5ae782775620e74ea16c9d47770" dependencies = [ "arrayvec", "bitflags", @@ -4375,9 +4426,9 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" +checksum = "4f5c9678cd533558e28b416d66947b099742df1939307478db54f867137f1b60" dependencies = [ "bitflags", "serde", diff --git a/extensions/webgpu/01_webgpu.js b/extensions/webgpu/01_webgpu.js index 096dfa722e..50d4d6eba6 100644 --- a/extensions/webgpu/01_webgpu.js +++ b/extensions/webgpu/01_webgpu.js @@ -214,7 +214,8 @@ * @typedef InnerGPUAdapter * @property {number} rid * @property {GPUSupportedFeatures} features - * @property {GPUAdapterLimits} limits + * @property {GPUSupportedLimits} limits + * @property {boolean} isSoftware */ /** @@ -229,7 +230,7 @@ adapter[_adapter] = { ...inner, features: createGPUSupportedFeatures(inner.features), - limits: createGPUAdapterLimits(inner.limits), + limits: createGPUSupportedLimits(inner.limits), }; return adapter; } @@ -250,11 +251,15 @@ webidl.assertBranded(this, GPUAdapter); return this[_adapter].features; } - /** @returns {GPUAdapterLimits} */ + /** @returns {GPUSupportedLimits} */ get limits() { webidl.assertBranded(this, GPUAdapter); return this[_adapter].limits; } + /** @returns {boolean} */ + get isSoftware() { + return this[_adapter].isSoftware; + } constructor() { webidl.illegalConstructor(); @@ -271,24 +276,24 @@ prefix, context: "Argument 1", }); - const nonGuaranteedFeatures = descriptor.nonGuaranteedFeatures ?? []; - for (const feature of nonGuaranteedFeatures) { + const requiredFeatures = descriptor.requiredFeatures ?? []; + for (const feature of requiredFeatures) { if (!SetPrototypeHas(this[_adapter].features[_features], feature)) { throw new TypeError( `${prefix}: nonGuaranteedFeatures must be a subset of the adapter features.`, ); } } - const nonGuaranteedLimits = descriptor.nonGuaranteedLimits; - // TODO(lucacasonato): validate nonGuaranteedLimits + const requiredLimits = descriptor.requiredLimits; + // TODO(lucacasonato): validate requiredLimits const { rid, features, limits } = await core.opAsync( "op_webgpu_request_device", { adapterRid: this[_adapter].rid, labe: descriptor.label, - nonGuaranteedFeatures, - nonGuaranteedLimits, + requiredFeatures, + requiredLimits, }, ); @@ -318,9 +323,9 @@ const _limits = Symbol("[[limits]]"); - function createGPUAdapterLimits(features) { - /** @type {GPUAdapterLimits} */ - const adapterFeatures = webidl.createBranded(GPUAdapterLimits); + function createGPUSupportedLimits(features) { + /** @type {GPUSupportedLimits} */ + const adapterFeatures = webidl.createBranded(GPUSupportedLimits); adapterFeatures[_limits] = features; return adapterFeatures; } @@ -341,12 +346,18 @@ * @property {number} maxUniformBuffersPerShaderStage * @property {number} maxUniformBufferBindingSize * @property {number} maxStorageBufferBindingSize + * @property {number} minUniformBufferOffsetAlignment + * @property {number} minStorageBufferOffsetAlignment * @property {number} maxVertexBuffers * @property {number} maxVertexAttributes * @property {number} maxVertexBufferArrayStride + * @property {number} maxInterStageShaderComponents + * @property {number} maxComputeWorkgroupStorageSize + * @property {number} maxComputeWorkgroupInvocations + * @property {number} maxComputePerDimensionDispatchSize */ - class GPUAdapterLimits { + class GPUSupportedLimits { /** @type {InnerAdapterLimits} */ [_limits]; constructor() { @@ -354,73 +365,97 @@ } get maxTextureDimension1D() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxTextureDimension1D; } get maxTextureDimension2D() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxTextureDimension2D; } get maxTextureDimension3D() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxTextureDimension3D; } get maxTextureArrayLayers() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxTextureArrayLayers; } get maxBindGroups() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxBindGroups; } get maxDynamicUniformBuffersPerPipelineLayout() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxDynamicUniformBuffersPerPipelineLayout; } get maxDynamicStorageBuffersPerPipelineLayout() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxDynamicStorageBuffersPerPipelineLayout; } get maxSampledTexturesPerShaderStage() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxSampledTexturesPerShaderStage; } get maxSamplersPerShaderStage() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxSamplersPerShaderStage; } get maxStorageBuffersPerShaderStage() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxStorageBuffersPerShaderStage; } get maxStorageTexturesPerShaderStage() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxStorageTexturesPerShaderStage; } get maxUniformBuffersPerShaderStage() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxUniformBuffersPerShaderStage; } get maxUniformBufferBindingSize() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxUniformBufferBindingSize; } get maxStorageBufferBindingSize() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxStorageBufferBindingSize; } + get minUniformBufferOffsetAlignment() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].minUniformBufferOffsetAlignment; + } + get minStorageBufferOffsetAlignment() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].minStorageBufferOffsetAlignment; + } get maxVertexBuffers() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxVertexBuffers; } get maxVertexAttributes() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxVertexAttributes; } get maxVertexBufferArrayStride() { - webidl.assertBranded(this, GPUAdapterLimits); + webidl.assertBranded(this, GPUSupportedLimits); return this[_limits].maxVertexBufferArrayStride; } + get maxInterStageShaderComponents() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].maxInterStageShaderComponents; + } + get maxComputeWorkgroupStorageSize() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].maxComputeWorkgroupStorageSize; + } + get maxComputeWorkgroupInvocations() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].maxComputeWorkgroupInvocations; + } + get maxComputePerDimensionDispatchSize() { + webidl.assertBranded(this, GPUSupportedLimits); + return this[_limits].maxComputePerDimensionDispatchSize; + } [SymbolFor("Deno.privateCustomInspect")](inspect) { return `${this.constructor.name} ${inspect(this[_limits])}`; @@ -1117,6 +1152,7 @@ compute: { module, entryPoint: descriptor.compute.entryPoint, + constants: descriptor.compute.constants, }, }, ); @@ -1764,12 +1800,12 @@ prefix, context: "Argument 1", }); - size = size === undefined - ? undefined - : webidl.converters.GPUSize64(size, { + if (size !== undefined) { + size = webidl.converters.GPUSize64(size, { prefix, context: "Argument 2", }); + } assertDevice(this, { prefix, context: "this" }); const bufferRid = assertResource(this, { prefix, context: "this" }); /** @type {number} */ @@ -3762,7 +3798,7 @@ * @param {number} offset * @param {number} size */ - setIndexBuffer(buffer, indexFormat, offset = 0, size = 0) { + setIndexBuffer(buffer, indexFormat, offset = 0, size) { webidl.assertBranded(this, GPURenderPassEncoder); const prefix = "Failed to execute 'setIndexBuffer' on 'GPURenderPassEncoder'"; @@ -3779,10 +3815,12 @@ prefix, context: "Argument 3", }); - size = webidl.converters.GPUSize64(size, { - prefix, - context: "Argument 4", - }); + if (size !== undefined) { + size = webidl.converters.GPUSize64(size, { + prefix, + context: "Argument 4", + }); + } const device = assertDevice(this[_encoder], { prefix, context: "encoder referenced by this", @@ -3816,7 +3854,7 @@ * @param {number} offset * @param {number} size */ - setVertexBuffer(slot, buffer, offset = 0, size = 0) { + setVertexBuffer(slot, buffer, offset = 0, size) { webidl.assertBranded(this, GPURenderPassEncoder); const prefix = "Failed to execute 'setVertexBuffer' on 'GPURenderPassEncoder'"; @@ -3833,10 +3871,12 @@ prefix, context: "Argument 3", }); - size = webidl.converters.GPUSize64(size, { - prefix, - context: "Argument 4", - }); + if (size !== undefined) { + size = webidl.converters.GPUSize64(size, { + prefix, + context: "Argument 4", + }); + } const device = assertDevice(this[_encoder], { prefix, context: "encoder referenced by this", @@ -5068,7 +5108,7 @@ gpu: webidl.createBranded(GPU), GPU, GPUAdapter, - GPUAdapterLimits, + GPUSupportedLimits, GPUSupportedFeatures, GPUDevice, GPUQueue, diff --git a/extensions/webgpu/02_idl_types.js b/extensions/webgpu/02_idl_types.js index a177e435c4..9102b8d7a4 100644 --- a/extensions/webgpu/02_idl_types.js +++ b/extensions/webgpu/02_idl_types.js @@ -10,7 +10,7 @@ const { GPU, GPUAdapter, - GPUAdapterLimits, + GPUSupportedLimits, GPUSupportedFeatures, GPUDevice, GPUQueue, @@ -57,10 +57,10 @@ dictMembersGPUObjectDescriptorBase, ); - // INTERFACE: GPUAdapterLimits - webidl.converters.GPUAdapterLimits = webidl.createInterfaceConverter( - "GPUAdapterLimits", - GPUAdapterLimits, + // INTERFACE: GPUSupportedLimits + webidl.converters.GPUSupportedLimits = webidl.createInterfaceConverter( + "GPUSupportedLimits", + GPUSupportedLimits, ); // INTERFACE: GPUSupportedFeatures @@ -69,6 +69,12 @@ GPUSupportedFeatures, ); + // ENUM: GPUPredefinedColorSpace + webidl.converters.GPUPredefinedColorSpace = webidl.createEnumConverter( + "GPUPredefinedColorSpace", + ["srgb"], + ); + // INTERFACE: GPU webidl.converters.GPU = webidl.createInterfaceConverter("GPU", GPU); @@ -87,6 +93,11 @@ key: "powerPreference", converter: webidl.converters["GPUPowerPreference"], }, + { + key: "forceSoftware", + converter: webidl.converters.boolean, + defaultValue: false, + }, ]; webidl.converters["GPURequestAdapterOptions"] = webidl .createDictionaryConverter( @@ -907,6 +918,15 @@ dictMembersGPUPipelineDescriptorBase, ); + // TYPEDEF: GPUPipelineConstantValue + webidl.converters.GPUPipelineConstantValue = webidl.converters.double; + + webidl.converters["record"] = webidl + .createRecordConverter( + webidl.converters.USVString, + webidl.converters.GPUPipelineConstantValue, + ); + // DICTIONARY: GPUProgrammableStage const dictMembersGPUProgrammableStage = [ { @@ -919,6 +939,11 @@ converter: webidl.converters["USVString"], required: true, }, + { + key: "constants", + converter: + webidl.converters["record"], + }, ]; webidl.converters["GPUProgrammableStage"] = webidl.createDictionaryConverter( "GPUProgrammableStage", @@ -1663,7 +1688,7 @@ // ENUM: GPUStoreOp webidl.converters["GPUStoreOp"] = webidl.createEnumConverter("GPUStoreOp", [ "store", - "clear", + "discard", ]); // DICTIONARY: GPURenderPassColorAttachment diff --git a/extensions/webgpu/Cargo.toml b/extensions/webgpu/Cargo.toml index 15e23f7257..3c9cae8b4d 100644 --- a/extensions/webgpu/Cargo.toml +++ b/extensions/webgpu/Cargo.toml @@ -17,5 +17,5 @@ path = "lib.rs" deno_core = { version = "0.92.0", path = "../../core" } tokio = { version = "1.8.0", features = ["full"] } serde = { version = "1.0.125", features = ["derive"] } -wgpu-core = { version = "0.8.1", features = ["trace"] } -wgpu-types = "0.8.0" +wgpu-core = { version = "0.9.0", features = ["trace"] } +wgpu-types = "0.9.0" diff --git a/extensions/webgpu/buffer.rs b/extensions/webgpu/buffer.rs index c9c93eeb6e..6980b63480 100644 --- a/extensions/webgpu/buffer.rs +++ b/extensions/webgpu/buffer.rs @@ -190,7 +190,7 @@ pub fn op_webgpu_buffer_get_mapped_range( gfx_select!(buffer => instance.buffer_get_mapped_range( buffer, args.offset, - std::num::NonZeroU64::new(args.size.unwrap_or(0)) + args.size )) .map_err(|e| DomExceptionOperationError::new(&e.to_string()))?; diff --git a/extensions/webgpu/command_encoder.rs b/extensions/webgpu/command_encoder.rs index d9f96842f7..6821a2954e 100644 --- a/extensions/webgpu/command_encoder.rs +++ b/extensions/webgpu/command_encoder.rs @@ -32,7 +32,7 @@ impl Resource for WebGpuCommandBuffer { fn serialize_store_op(store_op: String) -> wgpu_core::command::StoreOp { match store_op.as_str() { "store" => wgpu_core::command::StoreOp::Store, - "clear" => wgpu_core::command::StoreOp::Clear, + "discard" => wgpu_core::command::StoreOp::Clear, _ => unreachable!(), } } diff --git a/extensions/webgpu/lib.deno_webgpu.d.ts b/extensions/webgpu/lib.deno_webgpu.d.ts index d884dd98c6..9f7a31cb79 100644 --- a/extensions/webgpu/lib.deno_webgpu.d.ts +++ b/extensions/webgpu/lib.deno_webgpu.d.ts @@ -15,7 +15,7 @@ declare interface GPUObjectDescriptorBase { label?: string; } -declare class GPUAdapterLimits { +declare class GPUSupportedLimits { maxTextureDimension1D?: number; maxTextureDimension2D?: number; maxTextureDimension3D?: number; @@ -30,9 +30,15 @@ declare class GPUAdapterLimits { maxUniformBuffersPerShaderStage?: number; maxUniformBufferBindingSize?: number; maxStorageBufferBindingSize?: number; + minUniformBufferOffsetAlignment?: number; + minStorageBufferOffsetAlignment?: number; maxVertexBuffers?: number; maxVertexAttributes?: number; maxVertexBufferArrayStride?: number; + maxInterStageShaderComponents?: number; + maxComputeWorkgroupStorageSize?: number; + maxComputeWorkgroupInvocations?: number; + maxComputePerDimensionDispatchSize?: number; } declare class GPUSupportedFeatures { @@ -63,6 +69,7 @@ declare class GPU { declare interface GPURequestAdapterOptions { powerPreference?: GPUPowerPreference; + forceSoftware?: boolean; } declare type GPUPowerPreference = "low-power" | "high-performance"; @@ -70,14 +77,15 @@ declare type GPUPowerPreference = "low-power" | "high-performance"; declare class GPUAdapter { readonly name: string; readonly features: GPUSupportedFeatures; - readonly limits: GPUAdapterLimits; + readonly limits: GPUSupportedLimits; + readonly isSoftware: boolean; requestDevice(descriptor?: GPUDeviceDescriptor): Promise; } declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { - nonGuaranteedFeatures?: GPUFeatureName[]; - nonGuaranteedLimits?: Record; + requiredFeatures?: GPUFeatureName[]; + requiredLimits?: Record; } declare type GPUFeatureName = @@ -953,7 +961,7 @@ declare interface GPURenderPassDepthStencilAttachment { declare type GPULoadOp = "load"; -declare type GPUStoreOp = "store" | "clear"; +declare type GPUStoreOp = "store" | "discard"; declare class GPURenderBundle implements GPUObjectBase { label: string | null; diff --git a/extensions/webgpu/lib.rs b/extensions/webgpu/lib.rs index 4cee613465..56337d030e 100644 --- a/extensions/webgpu/lib.rs +++ b/extensions/webgpu/lib.rs @@ -223,6 +223,7 @@ pub struct GpuAdapterDevice { name: Option, limits: wgpu_types::Limits, features: Vec<&'static str>, + is_software: bool, } pub async fn op_webgpu_request_adapter( @@ -252,6 +253,7 @@ pub async fn op_webgpu_request_adapter( }, None => Default::default(), }, + // TODO(lucacasonato): respect forceSoftware compatible_surface: None, // windowless }; let res = instance.request_adapter( @@ -284,6 +286,7 @@ pub async fn op_webgpu_request_adapter( name: Some(name), features, limits: adapter_limits, + is_software: false, })) } @@ -304,9 +307,15 @@ struct GpuLimits { max_uniform_buffers_per_shader_stage: Option, max_uniform_buffer_binding_size: Option, max_storage_buffer_binding_size: Option, + // min_uniform_buffer_offset_alignment: Option, + // min_storage_buffer_offset_alignment: Option, max_vertex_buffers: Option, max_vertex_attributes: Option, max_vertex_buffer_array_stride: Option, + // max_inter_stage_shader_components: Option, + // max_compute_workgroup_storage_size: Option, + // max_compute_workgroup_invocations: Option, + // max_compute_per_dimension_dispatch_size: Option, } impl From for wgpu_types::Limits { @@ -344,11 +353,29 @@ impl From for wgpu_types::Limits { 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_workgroup_invocations: limits + // .max_compute_workgroup_invocations + // .unwrap_or(default), + // max_compute_per_dimension_dispatch_size: limits + // .max_compute_per_dimension_dispatch_size + // .unwrap_or(default), max_push_constant_size: 0, } } @@ -359,8 +386,8 @@ impl From for wgpu_types::Limits { pub struct RequestDeviceArgs { adapter_rid: ResourceId, label: Option, - non_guaranteed_features: Option>, - non_guaranteed_limits: Option, + required_features: Option>, + required_limits: Option, } pub async fn op_webgpu_request_device( @@ -378,7 +405,7 @@ pub async fn op_webgpu_request_device( let mut features: wgpu_types::Features = wgpu_types::Features::empty(); - if let Some(passed_features) = args.non_guaranteed_features { + if let Some(passed_features) = args.required_features { if passed_features.contains(&"depth-clamping".to_string()) { features.set(wgpu_types::Features::DEPTH_CLAMPING, true); } @@ -459,7 +486,7 @@ pub async fn op_webgpu_request_device( label: args.label.map(Cow::from), features, limits: args - .non_guaranteed_limits + .required_limits .map_or(wgpu_types::Limits::default(), Into::into), }; @@ -485,6 +512,8 @@ pub async fn op_webgpu_request_device( name: None, features, limits, + // TODO(lucacasonato): report correctly from wgpu + is_software: false, }) } diff --git a/extensions/webgpu/pipeline.rs b/extensions/webgpu/pipeline.rs index f2c1abc74a..6d11179a4f 100644 --- a/extensions/webgpu/pipeline.rs +++ b/extensions/webgpu/pipeline.rs @@ -153,6 +153,7 @@ fn serialize_blend_component( struct GpuProgrammableStage { module: u32, entry_point: String, + // constants: HashMap } #[derive(Deserialize)] @@ -197,6 +198,7 @@ pub fn op_webgpu_create_compute_pipeline( 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 { diff --git a/extensions/webgpu/render_pass.rs b/extensions/webgpu/render_pass.rs index 09849cbd91..81f2e6640e 100644 --- a/extensions/webgpu/render_pass.rs +++ b/extensions/webgpu/render_pass.rs @@ -2,6 +2,7 @@ use deno_core::error::bad_resource_id; use deno_core::error::null_opbuf; +use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; @@ -480,7 +481,7 @@ pub struct RenderPassSetIndexBufferArgs { buffer: u32, index_format: String, offset: u64, - size: u64, + size: Option, } pub fn op_webgpu_render_pass_set_index_buffer( @@ -497,11 +498,20 @@ pub fn op_webgpu_render_pass_set_index_buffer( .get::(args.render_pass_rid) .ok_or_else(bad_resource_id)?; + let size = if let Some(size) = args.size { + Some( + std::num::NonZeroU64::new(size) + .ok_or_else(|| type_error("size must be larger than 0"))?, + ) + } else { + None + }; + render_pass_resource.0.borrow_mut().set_index_buffer( buffer_resource.0, super::pipeline::serialize_index_format(args.index_format), args.offset, - std::num::NonZeroU64::new(args.size), + size, ); Ok(WebGpuResult::empty()) @@ -514,7 +524,7 @@ pub struct RenderPassSetVertexBufferArgs { slot: u32, buffer: u32, offset: u64, - size: u64, + size: Option, } pub fn op_webgpu_render_pass_set_vertex_buffer( @@ -531,12 +541,21 @@ pub fn op_webgpu_render_pass_set_vertex_buffer( .get::(args.render_pass_rid) .ok_or_else(bad_resource_id)?; + let size = if let Some(size) = args.size { + Some( + std::num::NonZeroU64::new(size) + .ok_or_else(|| type_error("size must be larger than 0"))?, + ) + } else { + None + }; + wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer( &mut render_pass_resource.0.borrow_mut(), args.slot, buffer_resource.0, args.offset, - std::num::NonZeroU64::new(args.size), + size, ); Ok(WebGpuResult::empty()) diff --git a/extensions/webgpu/texture.rs b/extensions/webgpu/texture.rs index 1c79248b0c..587ac46a7a 100644 --- a/extensions/webgpu/texture.rs +++ b/extensions/webgpu/texture.rs @@ -215,23 +215,25 @@ pub fn op_webgpu_create_texture_view( .map(|s| serialize_texture_format(&s)) .transpose()?, dimension: args.dimension.map(|s| serialize_dimension(&s)), - aspect: match args.aspect { - Some(aspect) => match aspect.as_str() { - "all" => wgpu_types::TextureAspect::All, - "stencil-only" => wgpu_types::TextureAspect::StencilOnly, - "depth-only" => wgpu_types::TextureAspect::DepthOnly, - _ => unreachable!(), + range: wgpu_types::ImageSubresourceRange { + aspect: match args.aspect { + Some(aspect) => match aspect.as_str() { + "all" => wgpu_types::TextureAspect::All, + "stencil-only" => wgpu_types::TextureAspect::StencilOnly, + "depth-only" => wgpu_types::TextureAspect::DepthOnly, + _ => unreachable!(), + }, + None => wgpu_types::TextureAspect::All, }, - None => wgpu_types::TextureAspect::All, + base_mip_level: args.base_mip_level.unwrap_or(0), + mip_level_count: std::num::NonZeroU32::new( + args.mip_level_count.unwrap_or(0), + ), + base_array_layer: args.base_array_layer.unwrap_or(0), + array_layer_count: std::num::NonZeroU32::new( + args.array_layer_count.unwrap_or(0), + ), }, - base_mip_level: args.base_mip_level.unwrap_or(0), - mip_level_count: std::num::NonZeroU32::new( - args.mip_level_count.unwrap_or(0), - ), - base_array_layer: args.base_array_layer.unwrap_or(0), - array_layer_count: std::num::NonZeroU32::new( - args.array_layer_count.unwrap_or(0), - ), }; gfx_put!(texture => instance.texture_create_view( diff --git a/extensions/webgpu/webgpu.idl b/extensions/webgpu/webgpu.idl index 023dcda96b..b2a536f2ff 100644 --- a/extensions/webgpu/webgpu.idl +++ b/extensions/webgpu/webgpu.idl @@ -7,7 +7,7 @@ dictionary GPUObjectDescriptorBase { }; [Exposed=Window] -interface GPUAdapterLimits { +interface GPUSupportedLimits { readonly attribute unsigned long maxTextureDimension1D; readonly attribute unsigned long maxTextureDimension2D; readonly attribute unsigned long maxTextureDimension3D; @@ -22,9 +22,15 @@ interface GPUAdapterLimits { readonly attribute unsigned long maxUniformBuffersPerShaderStage; readonly attribute unsigned long maxUniformBufferBindingSize; readonly attribute unsigned long maxStorageBufferBindingSize; + readonly attribute unsigned long minUniformBufferOffsetAlignment; + readonly attribute unsigned long minStorageBufferOffsetAlignment; readonly attribute unsigned long maxVertexBuffers; readonly attribute unsigned long maxVertexAttributes; readonly attribute unsigned long maxVertexBufferArrayStride; + readonly attribute unsigned long maxInterStageShaderComponents; + readonly attribute unsigned long maxComputeWorkgroupStorageSize; + readonly attribute unsigned long maxComputeWorkgroupInvocations; + readonly attribute unsigned long maxComputePerDimensionDispatchSize; }; [Exposed=Window] @@ -32,6 +38,10 @@ interface GPUSupportedFeatures { readonly setlike; }; +enum GPUPredefinedColorSpace { + "srgb", +}; + interface mixin NavigatorGPU { [SameObject] readonly attribute GPU gpu; }; @@ -45,6 +55,7 @@ interface GPU { dictionary GPURequestAdapterOptions { GPUPowerPreference powerPreference; + boolean forceSoftware = false; }; enum GPUPowerPreference { @@ -56,14 +67,15 @@ enum GPUPowerPreference { interface GPUAdapter { readonly attribute DOMString name; [SameObject] readonly attribute GPUSupportedFeatures features; - [SameObject] readonly attribute GPUAdapterLimits limits; + [SameObject] readonly attribute GPUSupportedLimits limits; + readonly attribute boolean isSoftware; Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); }; dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { - sequence nonGuaranteedFeatures = []; - record nonGuaranteedLimits = {}; + sequence requiredFeatures = []; + record requiredLimits = {}; }; enum GPUFeatureName { @@ -78,7 +90,7 @@ enum GPUFeatureName { [Exposed=(Window, DedicatedWorker), Serializable] interface GPUDevice : EventTarget { [SameObject] readonly attribute GPUSupportedFeatures features; - readonly attribute object limits; + [SameObject] readonly attribute GPUSupportedLimits limits; [SameObject] readonly attribute GPUQueue queue; @@ -474,8 +486,11 @@ interface mixin GPUPipelineBase { dictionary GPUProgrammableStage { required GPUShaderModule module; required USVString entryPoint; + record constants; }; +typedef double GPUPipelineConstantValue; // May represent WGSL’s bool, f32, i32, u32. + [Exposed=Window, Serializable] interface GPUComputePipeline { }; @@ -762,11 +777,6 @@ dictionary GPUImageCopyTexture { GPUTextureAspect aspect = "all"; }; -dictionary GPUImageCopyExternalImage { - required (ImageBitmap or HTMLCanvasElement or OffscreenCanvas) source; - GPUOrigin2D origin = {}; -}; - interface mixin GPUProgrammablePassEncoder { undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup, optional sequence dynamicOffsets = []); @@ -803,8 +813,8 @@ dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase { interface mixin GPURenderEncoderBase { undefined setPipeline(GPURenderPipeline pipeline); - undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); - undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size = 0); + undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size); + undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size); undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1, optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0); @@ -876,7 +886,7 @@ enum GPULoadOp { enum GPUStoreOp { "store", - "clear" + "discard" }; [Exposed=Window] @@ -919,11 +929,6 @@ interface GPUQueue { [AllowShared] BufferSource data, GPUImageDataLayout dataLayout, GPUExtent3D size); - - undefined copyExternalImageToTexture( - GPUImageCopyExternalImage source, - GPUImageCopyTexture destination, - GPUExtent3D copySize); }; GPUQueue includes GPUObjectBase; @@ -953,31 +958,6 @@ enum GPUPipelineStatisticName { "compute-shader-invocations" }; -[Exposed=Window] -interface GPUCanvasContext { - GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor); - - GPUTextureFormat getSwapChainPreferredFormat(GPUAdapter adapter); -}; - -enum GPUCanvasCompositingAlphaMode { - "opaque", - "premultiplied", -}; - -dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase { - required GPUDevice device; - required GPUTextureFormat format; - GPUTextureUsageFlags usage = 0x10; // GPUTextureUsage.RENDER_ATTACHMENT - GPUCanvasCompositingAlphaMode compositingAlphaMode = "opaque"; -}; - -[Exposed=Window] -interface GPUSwapChain { - GPUTexture getCurrentTexture(); -}; -GPUSwapChain includes GPUObjectBase; - enum GPUDeviceLostReason { "destroyed", }; diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 5d2767969c..b473acdef8 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -383,7 +383,7 @@ delete Object.prototype.__proto__; GPU: util.nonEnumerable(webgpu.GPU), GPUAdapter: util.nonEnumerable(webgpu.GPUAdapter), - GPUAdapterLimits: util.nonEnumerable(webgpu.GPUAdapterLimits), + GPUSupportedLimits: util.nonEnumerable(webgpu.GPUSupportedLimits), GPUSupportedFeatures: util.nonEnumerable(webgpu.GPUSupportedFeatures), GPUDevice: util.nonEnumerable(webgpu.GPUDevice), GPUQueue: util.nonEnumerable(webgpu.GPUQueue),