diff options
Diffstat (limited to 'extensions/webgpu')
-rw-r--r-- | extensions/webgpu/01_webgpu.js | 128 | ||||
-rw-r--r-- | extensions/webgpu/02_idl_types.js | 37 | ||||
-rw-r--r-- | extensions/webgpu/Cargo.toml | 4 | ||||
-rw-r--r-- | extensions/webgpu/buffer.rs | 2 | ||||
-rw-r--r-- | extensions/webgpu/command_encoder.rs | 2 | ||||
-rw-r--r-- | extensions/webgpu/lib.deno_webgpu.d.ts | 18 | ||||
-rw-r--r-- | extensions/webgpu/lib.rs | 37 | ||||
-rw-r--r-- | extensions/webgpu/pipeline.rs | 2 | ||||
-rw-r--r-- | extensions/webgpu/render_pass.rs | 27 | ||||
-rw-r--r-- | extensions/webgpu/texture.rs | 32 | ||||
-rw-r--r-- | extensions/webgpu/webgpu.idl | 66 |
11 files changed, 230 insertions, 125 deletions
diff --git a/extensions/webgpu/01_webgpu.js b/extensions/webgpu/01_webgpu.js index 096dfa722..50d4d6eba 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 a177e435c..9102b8d7a 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<USVString, GPUPipelineConstantValue>"] = 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<USVString, GPUPipelineConstantValue>"], + }, ]; 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 15e23f725..3c9cae8b4 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 c9c93eeb6..6980b6348 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 d9f96842f..6821a2954 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 d884dd98c..9f7a31cb7 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<GPUDevice>; } declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { - nonGuaranteedFeatures?: GPUFeatureName[]; - nonGuaranteedLimits?: Record<string, number>; + requiredFeatures?: GPUFeatureName[]; + requiredLimits?: Record<string, number>; } 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 4cee61346..56337d030 100644 --- a/extensions/webgpu/lib.rs +++ b/extensions/webgpu/lib.rs @@ -223,6 +223,7 @@ pub struct GpuAdapterDevice { name: Option<String>, 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<u32>, max_uniform_buffer_binding_size: Option<u32>, max_storage_buffer_binding_size: Option<u32>, + // 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_workgroup_invocations: Option<u32>, + // max_compute_per_dimension_dispatch_size: Option<u32>, } impl From<GpuLimits> for wgpu_types::Limits { @@ -344,11 +353,29 @@ impl From<GpuLimits> 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<GpuLimits> for wgpu_types::Limits { pub struct RequestDeviceArgs { adapter_rid: ResourceId, label: Option<String>, - non_guaranteed_features: Option<Vec<String>>, - non_guaranteed_limits: Option<GpuLimits>, + required_features: Option<Vec<String>>, + required_limits: Option<GpuLimits>, } 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 f2c1abc74..6d11179a4 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<String, GPUPipelineConstantValue> } #[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 09849cbd9..81f2e6640 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<u64>, } pub fn op_webgpu_render_pass_set_index_buffer( @@ -497,11 +498,20 @@ pub fn op_webgpu_render_pass_set_index_buffer( .get::<WebGpuRenderPass>(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<u64>, } pub fn op_webgpu_render_pass_set_vertex_buffer( @@ -531,12 +541,21 @@ pub fn op_webgpu_render_pass_set_vertex_buffer( .get::<WebGpuRenderPass>(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 1c79248b0..587ac46a7 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 023dcda96..b2a536f2f 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<DOMString>; }; +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<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {}); }; dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { - sequence<GPUFeatureName> nonGuaranteedFeatures = []; - record<DOMString, GPUSize32> nonGuaranteedLimits = {}; + sequence<GPUFeatureName> requiredFeatures = []; + record<DOMString, GPUSize32> 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<USVString, GPUPipelineConstantValue> 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<GPUBufferDynamicOffset> 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", }; |