webgpu: Sync various parts of spec (#33009)

* Sync `GPUObjectDescriptorBase` (label is not option anymore)

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Sync `GPUFeatureName`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* shader_f16 feature is not usable in wgpu so disable it

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* sync `GPUTextureFormat`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* `validate_texture_format_required_features`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Sync `GPUTexture` attributes

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Make `entryPoint` in `GPUProgrammableStage` optional

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Set good expectations

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Bad expectations because naga does not support cons declarations

Also fail on firefox, where skipped before due to missing device features

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Bad expectation, also fails on firefox

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Bad expectations, because naga does not support `let pos = positions[vertex_index];`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Set expectation

external texture does not work in firefox too (again naga)

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* set bad expectations, because naga does not support `enable`

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Set bad expectations for, `Texture with '' label has been destroyed`

also fails in firefox with same reason

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* one bad expectation

also on firefox

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* expect that also matches firefox

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* more expect

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Use only 1 proc for _webgpu

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* better doc comment

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
Samson 2024-08-19 16:06:30 +02:00 committed by GitHub
parent f45c98496e
commit 94ff89a5e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 910 additions and 4947 deletions

View file

@ -110,10 +110,10 @@ impl GPUAdapterMethods for GPUAdapter {
// Step 2 // Step 2
let promise = Promise::new_in_current_realm(comp); let promise = Promise::new_in_current_realm(comp);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let mut features = wgt::Features::empty(); let mut required_features = wgt::Features::empty();
for &ext in descriptor.requiredFeatures.iter() { for &ext in descriptor.requiredFeatures.iter() {
if let Some(feature) = gpu_to_wgt_feature(ext) { if let Some(feature) = gpu_to_wgt_feature(ext) {
features.insert(feature); required_features.insert(feature);
} else { } else {
promise.reject_error(Error::Type(format!( promise.reject_error(Error::Type(format!(
"{} is not supported feature", "{} is not supported feature",
@ -123,21 +123,23 @@ impl GPUAdapterMethods for GPUAdapter {
} }
} }
let mut desc = wgt::DeviceDescriptor { let mut required_limits = wgt::Limits::default();
required_features: features,
required_limits: wgt::Limits::default(),
label: None,
memory_hints: MemoryHints::MemoryUsage,
};
if let Some(limits) = &descriptor.requiredLimits { if let Some(limits) = &descriptor.requiredLimits {
for (limit, value) in (*limits).iter() { for (limit, value) in (*limits).iter() {
if !set_limit(&mut desc.required_limits, limit.as_ref(), *value) { if !set_limit(&mut required_limits, limit.as_ref(), *value) {
warn!("Unknown GPUDevice limit: {limit}"); warn!("Unknown GPUDevice limit: {limit}");
promise.reject_error(Error::Operation); promise.reject_error(Error::Operation);
return promise; return promise;
} }
} }
} }
let desc = wgt::DeviceDescriptor {
required_features,
required_limits,
label: Some(descriptor.parent.label.to_string()),
memory_hints: MemoryHints::MemoryUsage,
};
let device_id = self let device_id = self
.global() .global()
.wgpu_id_hub() .wgpu_id_hub()

View file

@ -20,6 +20,7 @@ use super::bindings::codegen::Bindings::WebGPUBinding::GPUTextureUsageConstants;
use super::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas; use super::bindings::codegen::UnionTypes::HTMLCanvasElementOrOffscreenCanvas;
use super::bindings::error::{Error, Fallible}; use super::bindings::error::{Error, Fallible};
use super::bindings::root::MutNullableDom; use super::bindings::root::MutNullableDom;
use super::bindings::str::USVString;
use super::gputexture::GPUTexture; use super::gputexture::GPUTexture;
use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElement_Binding::HTMLCanvasElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElement_Binding::HTMLCanvasElementMethods;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
@ -207,7 +208,9 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
fn Configure(&self, descriptor: &GPUCanvasConfiguration) -> Fallible<()> { fn Configure(&self, descriptor: &GPUCanvasConfiguration) -> Fallible<()> {
// Step 1 is let // Step 1 is let
// Step 2 // Step 2
// TODO: device features descriptor
.device
.validate_texture_format_required_features(&descriptor.format)?;
let format = match descriptor.format { let format = match descriptor.format {
GPUTextureFormat::Rgba8unorm | GPUTextureFormat::Rgba8unorm_srgb => ImageFormat::RGBA8, GPUTextureFormat::Rgba8unorm | GPUTextureFormat::Rgba8unorm_srgb => ImageFormat::RGBA8,
GPUTextureFormat::Bgra8unorm | GPUTextureFormat::Bgra8unorm_srgb => ImageFormat::BGRA8, GPUTextureFormat::Bgra8unorm | GPUTextureFormat::Bgra8unorm_srgb => ImageFormat::BGRA8,
@ -220,7 +223,11 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
}; };
// Step 3 // Step 3
// TODO: device features for view_format in &descriptor.viewFormats {
descriptor
.device
.validate_texture_format_required_features(view_format)?;
}
// Step 4 // Step 4
let size = self.size(); let size = self.size();
@ -236,7 +243,9 @@ impl GPUCanvasContextMethods for GPUCanvasContext {
}), }),
viewFormats: descriptor.viewFormats.clone(), viewFormats: descriptor.viewFormats.clone(),
// other members to default // other members to default
parent: GPUObjectDescriptorBase { label: None }, parent: GPUObjectDescriptorBase {
label: USVString::default(),
},
dimension: GPUTextureDimension::_2d, dimension: GPUTextureDimension::_2d,
}; };

View file

@ -124,7 +124,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(), self.channel.clone(),
self, self,
WebGPUComputePass(compute_pass_id), WebGPUComputePass(compute_pass_id),
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
@ -213,7 +213,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(), self.channel.clone(),
WebGPURenderPass(render_pass_id), WebGPURenderPass(render_pass_id),
self, self,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
@ -324,7 +324,7 @@ impl GPUCommandEncoderMethods for GPUCommandEncoder {
self.channel.clone(), self.channel.clone(),
buffer, buffer,
self.buffers.borrow_mut().drain().collect(), self.buffers.borrow_mut().drain().collect(),
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
} }

View file

@ -5,7 +5,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use webgpu::wgc::command as wgpu_com; use webgpu::wgc::command as wgpu_com;
use webgpu::wgt; use webgpu::wgt::{self, AstcBlock, AstcChannel};
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
GPUAddressMode, GPUBlendComponent, GPUBlendFactor, GPUBlendOperation, GPUCompareFunction, GPUAddressMode, GPUBlendComponent, GPUBlendFactor, GPUBlendOperation, GPUCompareFunction,
@ -67,8 +67,135 @@ pub fn convert_texture_format(format: GPUTextureFormat) -> wgt::TextureFormat {
GPUTextureFormat::Bc6h_rgb_ufloat => wgt::TextureFormat::Bc6hRgbUfloat, GPUTextureFormat::Bc6h_rgb_ufloat => wgt::TextureFormat::Bc6hRgbUfloat,
GPUTextureFormat::Bc7_rgba_unorm => wgt::TextureFormat::Bc7RgbaUnorm, GPUTextureFormat::Bc7_rgba_unorm => wgt::TextureFormat::Bc7RgbaUnorm,
GPUTextureFormat::Bc7_rgba_unorm_srgb => wgt::TextureFormat::Bc7RgbaUnormSrgb, GPUTextureFormat::Bc7_rgba_unorm_srgb => wgt::TextureFormat::Bc7RgbaUnormSrgb,
GPUTextureFormat::Rg11b10float => wgt::TextureFormat::Rg11b10Float,
GPUTextureFormat::Bc6h_rgb_float => wgt::TextureFormat::Bc6hRgbFloat, GPUTextureFormat::Bc6h_rgb_float => wgt::TextureFormat::Bc6hRgbFloat,
GPUTextureFormat::Rgb9e5ufloat => wgt::TextureFormat::Rgb9e5Ufloat,
GPUTextureFormat::Rgb10a2uint => wgt::TextureFormat::Rgb10a2Uint,
GPUTextureFormat::Rg11b10ufloat => wgt::TextureFormat::Rg11b10Float,
GPUTextureFormat::Stencil8 => wgt::TextureFormat::Stencil8,
GPUTextureFormat::Depth16unorm => wgt::TextureFormat::Depth16Unorm,
GPUTextureFormat::Depth32float_stencil8 => wgt::TextureFormat::Depth32FloatStencil8,
GPUTextureFormat::Etc2_rgb8unorm => wgt::TextureFormat::Etc2Rgb8Unorm,
GPUTextureFormat::Etc2_rgb8unorm_srgb => wgt::TextureFormat::Etc2Rgb8UnormSrgb,
GPUTextureFormat::Etc2_rgb8a1unorm => wgt::TextureFormat::Etc2Rgb8A1Unorm,
GPUTextureFormat::Etc2_rgb8a1unorm_srgb => wgt::TextureFormat::Etc2Rgb8A1UnormSrgb,
GPUTextureFormat::Etc2_rgba8unorm => wgt::TextureFormat::Etc2Rgba8Unorm,
GPUTextureFormat::Etc2_rgba8unorm_srgb => wgt::TextureFormat::Etc2Rgba8UnormSrgb,
GPUTextureFormat::Eac_r11unorm => wgt::TextureFormat::EacR11Unorm,
GPUTextureFormat::Eac_r11snorm => wgt::TextureFormat::EacR11Snorm,
GPUTextureFormat::Eac_rg11unorm => wgt::TextureFormat::EacRg11Unorm,
GPUTextureFormat::Eac_rg11snorm => wgt::TextureFormat::EacRg11Snorm,
GPUTextureFormat::Astc_4x4_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_4x4_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B4x4,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_5x4_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_5x4_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B5x4,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_5x5_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_5x5_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B5x5,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_6x5_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_6x5_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B6x5,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_6x6_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_6x6_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B6x6,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_8x5_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_8x5_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B8x5,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_8x6_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_8x6_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B8x6,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_8x8_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_8x8_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B8x8,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_10x5_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_10x5_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B10x5,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_10x6_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_10x6_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B10x6,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_10x8_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_10x8_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B10x8,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_10x10_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_10x10_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B10x10,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_12x10_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_12x10_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B12x10,
channel: AstcChannel::UnormSrgb,
},
GPUTextureFormat::Astc_12x12_unorm => wgt::TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: AstcChannel::Unorm,
},
GPUTextureFormat::Astc_12x12_unorm_srgb => wgt::TextureFormat::Astc {
block: AstcBlock::B12x12,
channel: AstcChannel::UnormSrgb,
},
} }
} }
@ -329,5 +456,9 @@ pub fn convert_ic_texture(ic_texture: &GPUImageCopyTexture) -> wgpu_com::ImageCo
} }
pub fn convert_label(parent: &GPUObjectDescriptorBase) -> Option<Cow<'static, str>> { pub fn convert_label(parent: &GPUObjectDescriptorBase) -> Option<Cow<'static, str>> {
parent.label.as_ref().map(|s| Cow::Owned(s.to_string())) if parent.label.is_empty() {
None
} else {
Some(Cow::Owned(parent.label.to_string()))
}
} }

View file

@ -18,12 +18,13 @@ use webgpu::wgc::pipeline::RenderPipelineDescriptor;
use webgpu::wgc::{ use webgpu::wgc::{
binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res, binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res,
}; };
use webgpu::wgt::TextureFormat;
use webgpu::{ use webgpu::{
self, wgt, PopError, WebGPU, WebGPUComputePipeline, WebGPURenderPipeline, WebGPURequest, self, wgt, PopError, WebGPU, WebGPUComputePipeline, WebGPURenderPipeline, WebGPURequest,
WebGPUResponse, WebGPUResponse,
}; };
use super::bindings::codegen::Bindings::WebGPUBinding::GPUPipelineErrorReason; use super::bindings::codegen::Bindings::WebGPUBinding::{GPUPipelineErrorReason, GPUTextureFormat};
use super::bindings::codegen::UnionTypes::GPUPipelineLayoutOrGPUAutoLayoutMode; use super::bindings::codegen::UnionTypes::GPUPipelineLayoutOrGPUAutoLayoutMode;
use super::bindings::error::Fallible; use super::bindings::error::Fallible;
use super::gpu::AsyncWGPUListener; use super::gpu::AsyncWGPUListener;
@ -190,6 +191,28 @@ impl GPUDevice {
let _ = self.eventtarget.DispatchEvent(ev.event()); let _ = self.eventtarget.DispatchEvent(ev.event());
} }
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-texture-format-required-features>
///
/// Validates that the device suppports required features,
/// and if so returns an ok containing wgpu's `TextureFormat`
pub fn validate_texture_format_required_features(
&self,
format: &GPUTextureFormat,
) -> Fallible<TextureFormat> {
let texture_format = convert_texture_format(*format);
if self
.features
.wgpu_features()
.contains(texture_format.required_features())
{
Ok(texture_format)
} else {
Err(Error::Type(format!(
"{texture_format:?} is not supported by this GPUDevice"
)))
}
}
fn get_pipeline_layout_data( fn get_pipeline_layout_data(
&self, &self,
layout: &GPUPipelineLayoutOrGPUAutoLayoutMode, layout: &GPUPipelineLayoutOrGPUAutoLayoutMode,
@ -223,10 +246,10 @@ impl GPUDevice {
fn parse_render_pipeline( fn parse_render_pipeline(
&self, &self,
descriptor: &GPURenderPipelineDescriptor, descriptor: &GPURenderPipelineDescriptor,
) -> ( ) -> Fallible<(
Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>, Option<(PipelineLayoutId, Vec<BindGroupLayoutId>)>,
RenderPipelineDescriptor<'static>, RenderPipelineDescriptor<'static>,
) { )> {
let (layout, implicit_ids, _) = self.get_pipeline_layout_data(&descriptor.parent.layout); let (layout, implicit_ids, _) = self.get_pipeline_layout_data(&descriptor.parent.layout);
let desc = wgpu_pipe::RenderPipelineDescriptor { let desc = wgpu_pipe::RenderPipelineDescriptor {
@ -236,7 +259,12 @@ impl GPUDevice {
vertex: wgpu_pipe::VertexState { vertex: wgpu_pipe::VertexState {
stage: wgpu_pipe::ProgrammableStageDescriptor { stage: wgpu_pipe::ProgrammableStageDescriptor {
module: descriptor.vertex.parent.module.id().0, module: descriptor.vertex.parent.module.id().0,
entry_point: Some(Cow::Owned(descriptor.vertex.parent.entryPoint.to_string())), entry_point: descriptor
.vertex
.parent
.entryPoint
.as_ref()
.map(|ep| Cow::Owned(ep.to_string())),
constants: Cow::Owned(HashMap::new()), constants: Cow::Owned(HashMap::new()),
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
@ -269,10 +297,15 @@ impl GPUDevice {
fragment: descriptor fragment: descriptor
.fragment .fragment
.as_ref() .as_ref()
.map(|stage| wgpu_pipe::FragmentState { .map(|stage| -> Fallible<wgpu_pipe::FragmentState> {
Ok(wgpu_pipe::FragmentState {
stage: wgpu_pipe::ProgrammableStageDescriptor { stage: wgpu_pipe::ProgrammableStageDescriptor {
module: stage.parent.module.id().0, module: stage.parent.module.id().0,
entry_point: Some(Cow::Owned(stage.parent.entryPoint.to_string())), entry_point: stage
.parent
.entryPoint
.as_ref()
.map(|ep| Cow::Owned(ep.to_string())),
constants: Cow::Owned(HashMap::new()), constants: Cow::Owned(HashMap::new()),
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
@ -281,35 +314,58 @@ impl GPUDevice {
.targets .targets
.iter() .iter()
.map(|state| { .map(|state| {
self.validate_texture_format_required_features(&state.format)
.map(|format| {
Some(wgt::ColorTargetState { Some(wgt::ColorTargetState {
format: convert_texture_format(state.format), format,
write_mask: wgt::ColorWrites::from_bits_retain(state.writeMask), write_mask: wgt::ColorWrites::from_bits_retain(
blend: state.blend.as_ref().map(|blend| wgt::BlendState { state.writeMask,
color: convert_blend_component(&blend.color),
alpha: convert_blend_component(&blend.alpha),
}),
})
})
.collect::<Vec<_>>(),
), ),
blend: state.blend.as_ref().map(|blend| {
wgt::BlendState {
color: convert_blend_component(
&blend.color,
),
alpha: convert_blend_component(
&blend.alpha,
),
}
}), }),
})
})
})
.collect::<Result<Vec<_>, _>>()?,
),
})
})
.transpose()?,
primitive: convert_primitive_state(&descriptor.primitive), primitive: convert_primitive_state(&descriptor.primitive),
depth_stencil: descriptor.depthStencil.as_ref().map(|dss_desc| { depth_stencil: descriptor
wgt::DepthStencilState { .depthStencil
format: convert_texture_format(dss_desc.format), .as_ref()
.map(|dss_desc| {
self.validate_texture_format_required_features(&dss_desc.format)
.map(|format| wgt::DepthStencilState {
format,
depth_write_enabled: dss_desc.depthWriteEnabled, depth_write_enabled: dss_desc.depthWriteEnabled,
depth_compare: convert_compare_function(dss_desc.depthCompare), depth_compare: convert_compare_function(dss_desc.depthCompare),
stencil: wgt::StencilState { stencil: wgt::StencilState {
front: wgt::StencilFaceState { front: wgt::StencilFaceState {
compare: convert_compare_function(dss_desc.stencilFront.compare), compare: convert_compare_function(
dss_desc.stencilFront.compare,
),
fail_op: convert_stencil_op(dss_desc.stencilFront.failOp), fail_op: convert_stencil_op(dss_desc.stencilFront.failOp),
depth_fail_op: convert_stencil_op(dss_desc.stencilFront.depthFailOp), depth_fail_op: convert_stencil_op(
dss_desc.stencilFront.depthFailOp,
),
pass_op: convert_stencil_op(dss_desc.stencilFront.passOp), pass_op: convert_stencil_op(dss_desc.stencilFront.passOp),
}, },
back: wgt::StencilFaceState { back: wgt::StencilFaceState {
compare: convert_compare_function(dss_desc.stencilBack.compare), compare: convert_compare_function(dss_desc.stencilBack.compare),
fail_op: convert_stencil_op(dss_desc.stencilBack.failOp), fail_op: convert_stencil_op(dss_desc.stencilBack.failOp),
depth_fail_op: convert_stencil_op(dss_desc.stencilBack.depthFailOp), depth_fail_op: convert_stencil_op(
dss_desc.stencilBack.depthFailOp,
),
pass_op: convert_stencil_op(dss_desc.stencilBack.passOp), pass_op: convert_stencil_op(dss_desc.stencilBack.passOp),
}, },
read_mask: dss_desc.stencilReadMask, read_mask: dss_desc.stencilReadMask,
@ -320,8 +376,9 @@ impl GPUDevice {
slope_scale: *dss_desc.depthBiasSlopeScale, slope_scale: *dss_desc.depthBiasSlopeScale,
clamp: *dss_desc.depthBiasClamp, clamp: *dss_desc.depthBiasClamp,
}, },
} })
}), })
.transpose()?,
multisample: wgt::MultisampleState { multisample: wgt::MultisampleState {
count: descriptor.multisample.count, count: descriptor.multisample.count,
mask: descriptor.multisample.mask as u64, mask: descriptor.multisample.mask as u64,
@ -329,7 +386,7 @@ impl GPUDevice {
}, },
multiview: None, multiview: None,
}; };
(implicit_ids, desc) Ok((implicit_ids, desc))
} }
/// <https://gpuweb.github.io/gpuweb/#lose-the-device> /// <https://gpuweb.github.io/gpuweb/#lose-the-device>
@ -420,7 +477,7 @@ impl GPUDeviceMethods for GPUDevice {
state, state,
descriptor.size, descriptor.size,
map_info, map_info,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
)) ))
} }
@ -429,7 +486,8 @@ impl GPUDeviceMethods for GPUDevice {
fn CreateBindGroupLayout( fn CreateBindGroupLayout(
&self, &self,
descriptor: &GPUBindGroupLayoutDescriptor, descriptor: &GPUBindGroupLayoutDescriptor,
) -> DomRoot<GPUBindGroupLayout> { ) -> Fallible<DomRoot<GPUBindGroupLayout>> {
// TODO(sagudev): pass invalid bits to wgpu
let mut valid = true; let mut valid = true;
let entries = descriptor let entries = descriptor
.entries .entries
@ -471,7 +529,7 @@ impl GPUDeviceMethods for GPUDevice {
wgt::StorageTextureAccess::WriteOnly wgt::StorageTextureAccess::WriteOnly
}, },
}, },
format: convert_texture_format(storage.format), format: self.validate_texture_format_required_features(&storage.format)?,
view_dimension: convert_view_dimension(storage.viewDimension), view_dimension: convert_view_dimension(storage.viewDimension),
} }
} else if let Some(texture) = &bind.texture { } else if let Some(texture) = &bind.texture {
@ -495,14 +553,14 @@ impl GPUDeviceMethods for GPUDevice {
todo!("Handle error"); todo!("Handle error");
}; };
wgt::BindGroupLayoutEntry { Ok(wgt::BindGroupLayoutEntry {
binding: bind.binding, binding: bind.binding,
visibility, visibility,
ty, ty,
count: None, count: None,
}
}) })
.collect::<Vec<_>>(); })
.collect::<Fallible<Vec<_>>>()?;
let desc = if valid { let desc = if valid {
Some(wgpu_bind::BindGroupLayoutDescriptor { Some(wgpu_bind::BindGroupLayoutDescriptor {
@ -531,12 +589,12 @@ impl GPUDeviceMethods for GPUDevice {
let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id); let bgl = webgpu::WebGPUBindGroupLayout(bind_group_layout_id);
GPUBindGroupLayout::new( Ok(GPUBindGroupLayout::new(
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
bgl, bgl,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) ))
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createpipelinelayout>
@ -579,7 +637,7 @@ impl GPUDeviceMethods for GPUDevice {
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
pipeline_layout, pipeline_layout,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
bgls, bgls,
) )
} }
@ -636,7 +694,7 @@ impl GPUDeviceMethods for GPUDevice {
bind_group, bind_group,
self.device, self.device,
&descriptor.layout, &descriptor.layout,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
@ -655,7 +713,7 @@ impl GPUDeviceMethods for GPUDevice {
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
webgpu::WebGPUShaderModule(program_id), webgpu::WebGPUShaderModule(program_id),
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
promise.clone(), promise.clone(),
); );
let sender = response_async(&promise, &*shader_module); let sender = response_async(&promise, &*shader_module);
@ -689,7 +747,11 @@ impl GPUDeviceMethods for GPUDevice {
layout, layout,
stage: wgpu_pipe::ProgrammableStageDescriptor { stage: wgpu_pipe::ProgrammableStageDescriptor {
module: descriptor.compute.module.id().0, module: descriptor.compute.module.id().0,
entry_point: Some(Cow::Owned(descriptor.compute.entryPoint.to_string())), entry_point: descriptor
.compute
.entryPoint
.as_ref()
.map(|ep| Cow::Owned(ep.to_string())),
constants: Cow::Owned(HashMap::new()), constants: Cow::Owned(HashMap::new()),
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
@ -711,7 +773,7 @@ impl GPUDeviceMethods for GPUDevice {
GPUComputePipeline::new( GPUComputePipeline::new(
&self.global(), &self.global(),
compute_pipeline, compute_pipeline,
descriptor.parent.parent.label.clone().unwrap_or_default(), descriptor.parent.parent.label.clone(),
self, self,
) )
} }
@ -736,7 +798,11 @@ impl GPUDeviceMethods for GPUDevice {
layout, layout,
stage: wgpu_pipe::ProgrammableStageDescriptor { stage: wgpu_pipe::ProgrammableStageDescriptor {
module: descriptor.compute.module.id().0, module: descriptor.compute.module.id().0,
entry_point: Some(Cow::Owned(descriptor.compute.entryPoint.to_string())), entry_point: descriptor
.compute
.entryPoint
.as_ref()
.map(|ep| Cow::Owned(ep.to_string())),
constants: Cow::Owned(HashMap::new()), constants: Cow::Owned(HashMap::new()),
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
@ -781,15 +847,18 @@ impl GPUDeviceMethods for GPUDevice {
self.channel.clone(), self.channel.clone(),
self, self,
encoder, encoder,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createtexture>
fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> Fallible<DomRoot<GPUTexture>> { fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> Fallible<DomRoot<GPUTexture>> {
// TODO(sagudev): This should be https://gpuweb.github.io/gpuweb/#abstract-opdef-validate-gpuextent3d-shape
let size = convert_texture_size_to_dict(&descriptor.size); let size = convert_texture_size_to_dict(&descriptor.size);
let desc = wgt::TextureUsages::from_bits(descriptor.usage).map(|usg| { // TODO(sagudev): We should pass invalid bits to wgpu
wgpu_res::TextureDescriptor { let desc = wgt::TextureUsages::from_bits(descriptor.usage)
.map(|usg| -> Fallible<_> {
Ok(wgpu_res::TextureDescriptor {
label: convert_label(&descriptor.parent), label: convert_label(&descriptor.parent),
size: convert_texture_size_to_wgt(&size), size: convert_texture_size_to_wgt(&size),
mip_level_count: descriptor.mipLevelCount, mip_level_count: descriptor.mipLevelCount,
@ -799,15 +868,16 @@ impl GPUDeviceMethods for GPUDevice {
GPUTextureDimension::_2d => wgt::TextureDimension::D2, GPUTextureDimension::_2d => wgt::TextureDimension::D2,
GPUTextureDimension::_3d => wgt::TextureDimension::D3, GPUTextureDimension::_3d => wgt::TextureDimension::D3,
}, },
format: convert_texture_format(descriptor.format), format: self.validate_texture_format_required_features(&descriptor.format)?,
usage: usg, usage: usg,
view_formats: descriptor view_formats: descriptor
.viewFormats .viewFormats
.iter() .iter()
.map(|tf| convert_texture_format(*tf)) .map(|tf| self.validate_texture_format_required_features(tf))
.collect(), .collect::<Fallible<_>>()?,
} })
}); })
.transpose()?;
let texture_id = self let texture_id = self
.global() .global()
@ -839,7 +909,7 @@ impl GPUDeviceMethods for GPUDevice {
descriptor.dimension, descriptor.dimension,
descriptor.format, descriptor.format,
descriptor.usage, descriptor.usage,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
)) ))
} }
@ -884,7 +954,7 @@ impl GPUDeviceMethods for GPUDevice {
self.device, self.device,
compare_enable, compare_enable,
sampler, sampler,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
@ -892,8 +962,8 @@ impl GPUDeviceMethods for GPUDevice {
fn CreateRenderPipeline( fn CreateRenderPipeline(
&self, &self,
descriptor: &GPURenderPipelineDescriptor, descriptor: &GPURenderPipelineDescriptor,
) -> DomRoot<GPURenderPipeline> { ) -> Fallible<DomRoot<GPURenderPipeline>> {
let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor); let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor)?;
let render_pipeline_id = self let render_pipeline_id = self
.global() .global()
@ -913,12 +983,12 @@ impl GPUDeviceMethods for GPUDevice {
let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id); let render_pipeline = webgpu::WebGPURenderPipeline(render_pipeline_id);
GPURenderPipeline::new( Ok(GPURenderPipeline::new(
&self.global(), &self.global(),
render_pipeline, render_pipeline,
descriptor.parent.parent.label.clone().unwrap_or_default(), descriptor.parent.parent.label.clone(),
self, self,
) ))
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipelineasync> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderpipelineasync>
@ -926,10 +996,10 @@ impl GPUDeviceMethods for GPUDevice {
&self, &self,
descriptor: &GPURenderPipelineDescriptor, descriptor: &GPURenderPipelineDescriptor,
comp: InRealm, comp: InRealm,
) -> Rc<Promise> { ) -> Fallible<Rc<Promise>> {
let promise = Promise::new_in_current_realm(comp); let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor)?;
let (implicit_ids, desc) = self.parse_render_pipeline(&descriptor);
let promise = Promise::new_in_current_realm(comp);
let sender = response_async(&promise, self); let sender = response_async(&promise, self);
let render_pipeline_id = self let render_pipeline_id = self
@ -948,14 +1018,14 @@ impl GPUDeviceMethods for GPUDevice {
}) })
.expect("Failed to create WebGPU render pipeline"); .expect("Failed to create WebGPU render pipeline");
promise Ok(promise)
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderbundleencoder> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-createrenderbundleencoder>
fn CreateRenderBundleEncoder( fn CreateRenderBundleEncoder(
&self, &self,
descriptor: &GPURenderBundleEncoderDescriptor, descriptor: &GPURenderBundleEncoderDescriptor,
) -> DomRoot<GPURenderBundleEncoder> { ) -> Fallible<DomRoot<GPURenderBundleEncoder>> {
let desc = wgpu_com::RenderBundleEncoderDescriptor { let desc = wgpu_com::RenderBundleEncoderDescriptor {
label: convert_label(&descriptor.parent.parent), label: convert_label(&descriptor.parent.parent),
color_formats: Cow::Owned( color_formats: Cow::Owned(
@ -963,16 +1033,24 @@ impl GPUDeviceMethods for GPUDevice {
.parent .parent
.colorFormats .colorFormats
.iter() .iter()
.map(|f| Some(convert_texture_format(*f))) .map(|format| {
.collect::<Vec<_>>(), self.validate_texture_format_required_features(format)
.map(|f| Some(f))
})
.collect::<Fallible<Vec<_>>>()?,
), ),
depth_stencil: descriptor.parent.depthStencilFormat.map(|dsf| { depth_stencil: descriptor
wgt::RenderBundleDepthStencil { .parent
format: convert_texture_format(dsf), .depthStencilFormat
.map(|dsf| {
self.validate_texture_format_required_features(&dsf)
.map(|format| wgt::RenderBundleDepthStencil {
format,
depth_read_only: descriptor.depthReadOnly, depth_read_only: descriptor.depthReadOnly,
stencil_read_only: descriptor.stencilReadOnly, stencil_read_only: descriptor.stencilReadOnly,
} })
}), })
.transpose()?,
sample_count: descriptor.parent.sampleCount, sample_count: descriptor.parent.sampleCount,
multiview: None, multiview: None,
}; };
@ -981,13 +1059,13 @@ impl GPUDeviceMethods for GPUDevice {
let render_bundle_encoder = let render_bundle_encoder =
wgpu_com::RenderBundleEncoder::new(&desc, self.device.0, None).unwrap(); wgpu_com::RenderBundleEncoder::new(&desc, self.device.0, None).unwrap();
GPURenderBundleEncoder::new( Ok(GPURenderBundleEncoder::new(
&self.global(), &self.global(),
render_bundle_encoder, render_bundle_encoder,
self, self,
self.channel.clone(), self.channel.clone(),
descriptor.parent.parent.label.clone().unwrap_or_default(), descriptor.parent.parent.label.clone(),
) ))
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope> /// <https://gpuweb.github.io/gpuweb/#dom-gpudevice-pusherrorscope>

View file

@ -222,7 +222,7 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder {
render_bundle, render_bundle,
self.device.id(), self.device.id(),
self.channel.clone(), self.channel.clone(),
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) )
} }
} }

View file

@ -9,7 +9,7 @@ use std::str::FromStr;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use indexmap::IndexSet; use indexmap::IndexSet;
use js::rust::HandleObject; use js::rust::HandleObject;
use webgpu::wgt; use webgpu::wgt::Features;
use super::bindings::like::Setlike; use super::bindings::like::Setlike;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
@ -39,43 +39,66 @@ pub struct GPUSupportedFeatures {
// internal storage for features // internal storage for features
#[custom_trace] #[custom_trace]
internal: DomRefCell<IndexSet<GPUFeatureName>>, internal: DomRefCell<IndexSet<GPUFeatureName>>,
#[ignore_malloc_size_of = "defined in wgpu-types"]
#[no_trace]
features: Features,
} }
impl GPUSupportedFeatures { impl GPUSupportedFeatures {
fn new( fn new(
global: &GlobalScope, global: &GlobalScope,
proto: Option<HandleObject>, proto: Option<HandleObject>,
features: wgt::Features, features: Features,
) -> DomRoot<GPUSupportedFeatures> { ) -> DomRoot<GPUSupportedFeatures> {
let mut set = IndexSet::new(); let mut set = IndexSet::new();
if features.contains(wgt::Features::DEPTH_CLIP_CONTROL) { if features.contains(Features::DEPTH_CLIP_CONTROL) {
set.insert(GPUFeatureName::Depth_clip_control); set.insert(GPUFeatureName::Depth_clip_control);
} }
if features.contains(wgt::Features::DEPTH32FLOAT_STENCIL8) { if features.contains(Features::DEPTH32FLOAT_STENCIL8) {
set.insert(GPUFeatureName::Depth32float_stencil8); set.insert(GPUFeatureName::Depth32float_stencil8);
} }
if features.contains(wgt::Features::PIPELINE_STATISTICS_QUERY) { if features.contains(Features::TEXTURE_COMPRESSION_BC) {
set.insert(GPUFeatureName::Pipeline_statistics_query);
}
if features.contains(wgt::Features::TEXTURE_COMPRESSION_BC) {
set.insert(GPUFeatureName::Texture_compression_bc); set.insert(GPUFeatureName::Texture_compression_bc);
} }
if features.contains(wgt::Features::TEXTURE_COMPRESSION_ETC2) { // TODO: texture-compression-bc-sliced-3d when wgpu supports it
if features.contains(Features::TEXTURE_COMPRESSION_ETC2) {
set.insert(GPUFeatureName::Texture_compression_etc2); set.insert(GPUFeatureName::Texture_compression_etc2);
} }
if features.contains(wgt::Features::TEXTURE_COMPRESSION_ASTC) { if features.contains(Features::TEXTURE_COMPRESSION_ASTC) {
set.insert(GPUFeatureName::Texture_compression_astc); set.insert(GPUFeatureName::Texture_compression_astc);
} }
if features.contains(wgt::Features::TIMESTAMP_QUERY) { if features.contains(Features::TIMESTAMP_QUERY) {
set.insert(GPUFeatureName::Timestamp_query); set.insert(GPUFeatureName::Timestamp_query);
} }
if features.contains(wgt::Features::INDIRECT_FIRST_INSTANCE) { if features.contains(Features::INDIRECT_FIRST_INSTANCE) {
set.insert(GPUFeatureName::Indirect_first_instance); set.insert(GPUFeatureName::Indirect_first_instance);
} }
// While this feature exists in wgpu, it's not supported by naga yet
// https://github.com/gfx-rs/wgpu/issues/4384
/*
if features.contains(Features::SHADER_F16) {
set.insert(GPUFeatureName::Shader_f16);
}
*/
if features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
set.insert(GPUFeatureName::Rg11b10ufloat_renderable);
}
if features.contains(Features::BGRA8UNORM_STORAGE) {
set.insert(GPUFeatureName::Bgra8unorm_storage);
}
if features.contains(Features::FLOAT32_FILTERABLE) {
set.insert(GPUFeatureName::Float32_filterable);
}
// TODO: clip-distances when wgpu supports it
if features.contains(Features::DUAL_SOURCE_BLENDING) {
set.insert(GPUFeatureName::Dual_source_blending);
}
reflect_dom_object_with_proto( reflect_dom_object_with_proto(
Box::new(GPUSupportedFeatures { Box::new(GPUSupportedFeatures {
reflector: Reflector::new(), reflector: Reflector::new(),
internal: DomRefCell::new(set), internal: DomRefCell::new(set),
features,
}), }),
global, global,
proto, proto,
@ -86,29 +109,42 @@ impl GPUSupportedFeatures {
pub fn Constructor( pub fn Constructor(
global: &GlobalScope, global: &GlobalScope,
proto: Option<HandleObject>, proto: Option<HandleObject>,
features: wgt::Features, features: Features,
) -> Fallible<DomRoot<GPUSupportedFeatures>> { ) -> Fallible<DomRoot<GPUSupportedFeatures>> {
Ok(GPUSupportedFeatures::new(global, proto, features)) Ok(GPUSupportedFeatures::new(global, proto, features))
} }
} }
impl GPUSupportedFeatures {
pub fn wgpu_features(&self) -> Features {
self.features
}
}
impl GPUSupportedFeaturesMethods for GPUSupportedFeatures { impl GPUSupportedFeaturesMethods for GPUSupportedFeatures {
fn Size(&self) -> u32 { fn Size(&self) -> u32 {
self.internal.size() self.internal.size()
} }
} }
pub fn gpu_to_wgt_feature(feature: GPUFeatureName) -> Option<wgt::Features> { pub fn gpu_to_wgt_feature(feature: GPUFeatureName) -> Option<Features> {
match feature { match feature {
GPUFeatureName::Depth_clip_control => Some(wgt::Features::DEPTH_CLIP_CONTROL), GPUFeatureName::Depth_clip_control => Some(Features::DEPTH_CLIP_CONTROL),
GPUFeatureName::Depth24unorm_stencil8 => None, GPUFeatureName::Depth32float_stencil8 => Some(Features::DEPTH32FLOAT_STENCIL8),
GPUFeatureName::Depth32float_stencil8 => Some(wgt::Features::DEPTH32FLOAT_STENCIL8), GPUFeatureName::Texture_compression_bc => Some(Features::TEXTURE_COMPRESSION_BC),
GPUFeatureName::Pipeline_statistics_query => Some(wgt::Features::PIPELINE_STATISTICS_QUERY), GPUFeatureName::Texture_compression_etc2 => Some(Features::TEXTURE_COMPRESSION_ETC2),
GPUFeatureName::Texture_compression_bc => Some(wgt::Features::TEXTURE_COMPRESSION_BC), GPUFeatureName::Texture_compression_astc => Some(Features::TEXTURE_COMPRESSION_ASTC),
GPUFeatureName::Texture_compression_etc2 => Some(wgt::Features::TEXTURE_COMPRESSION_ETC2), GPUFeatureName::Timestamp_query => Some(Features::TIMESTAMP_QUERY),
GPUFeatureName::Texture_compression_astc => Some(wgt::Features::TEXTURE_COMPRESSION_ASTC), GPUFeatureName::Indirect_first_instance => Some(Features::INDIRECT_FIRST_INSTANCE),
GPUFeatureName::Timestamp_query => Some(wgt::Features::TIMESTAMP_QUERY), // While this feature exists in wgpu, it's not supported by naga yet
GPUFeatureName::Indirect_first_instance => Some(wgt::Features::INDIRECT_FIRST_INSTANCE), // https://github.com/gfx-rs/wgpu/issues/4384
GPUFeatureName::Shader_f16 => None,
GPUFeatureName::Rg11b10ufloat_renderable => Some(Features::RG11B10UFLOAT_RENDERABLE),
GPUFeatureName::Bgra8unorm_storage => Some(Features::BGRA8UNORM_STORAGE),
GPUFeatureName::Float32_filterable => Some(Features::FLOAT32_FILTERABLE),
GPUFeatureName::Dual_source_blending => Some(Features::DUAL_SOURCE_BLENDING),
GPUFeatureName::Texture_compression_bc_sliced_3d => None,
GPUFeatureName::Clip_distances => None,
} }
} }

View file

@ -9,6 +9,7 @@ use dom_struct::dom_struct;
use webgpu::wgc::resource; use webgpu::wgc::resource;
use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView}; use webgpu::{wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView};
use super::bindings::error::Fallible;
use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
GPUExtent3DDict, GPUTextureAspect, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods, GPUExtent3DDict, GPUTextureAspect, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods,
@ -18,9 +19,7 @@ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::USVString; use crate::dom::bindings::str::USVString;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuconvert::{ use crate::dom::gpuconvert::{convert_label, convert_texture_view_dimension};
convert_label, convert_texture_format, convert_texture_view_dimension,
};
use crate::dom::gpudevice::GPUDevice; use crate::dom::gpudevice::GPUDevice;
use crate::dom::gputextureview::GPUTextureView; use crate::dom::gputextureview::GPUTextureView;
@ -142,13 +141,19 @@ impl GPUTextureMethods for GPUTexture {
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-createview> /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-createview>
fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot<GPUTextureView> { fn CreateView(
&self,
descriptor: &GPUTextureViewDescriptor,
) -> Fallible<DomRoot<GPUTextureView>> {
let desc = if !matches!(descriptor.mipLevelCount, Some(0)) && let desc = if !matches!(descriptor.mipLevelCount, Some(0)) &&
!matches!(descriptor.arrayLayerCount, Some(0)) !matches!(descriptor.arrayLayerCount, Some(0))
{ {
Some(resource::TextureViewDescriptor { Some(resource::TextureViewDescriptor {
label: convert_label(&descriptor.parent), label: convert_label(&descriptor.parent),
format: descriptor.format.map(convert_texture_format), format: descriptor
.format
.map(|f| self.device.validate_texture_format_required_features(&f))
.transpose()?,
dimension: descriptor.dimension.map(convert_texture_view_dimension), dimension: descriptor.dimension.map(convert_texture_view_dimension),
range: wgt::ImageSubresourceRange { range: wgt::ImageSubresourceRange {
aspect: match descriptor.aspect { aspect: match descriptor.aspect {
@ -187,13 +192,13 @@ impl GPUTextureMethods for GPUTexture {
let texture_view = WebGPUTextureView(texture_view_id); let texture_view = WebGPUTextureView(texture_view_id);
GPUTextureView::new( Ok(GPUTextureView::new(
&self.global(), &self.global(),
self.channel.clone(), self.channel.clone(),
texture_view, texture_view,
self, self,
descriptor.parent.label.clone().unwrap_or_default(), descriptor.parent.label.clone(),
) ))
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy> /// <https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy>
@ -212,4 +217,44 @@ impl GPUTextureMethods for GPUTexture {
}; };
self.destroyed.set(true); self.destroyed.set(true);
} }
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-width>
fn Width(&self) -> u32 {
self.texture_size.width
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-height>
fn Height(&self) -> u32 {
self.texture_size.height
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-depthorarraylayers>
fn DepthOrArrayLayers(&self) -> u32 {
self.texture_size.depthOrArrayLayers
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-miplevelcount>
fn MipLevelCount(&self) -> u32 {
self.mip_level_count
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-samplecount>
fn SampleCount(&self) -> u32 {
self.sample_count
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-dimension>
fn Dimension(&self) -> GPUTextureDimension {
self.dimension
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-format>
fn Format(&self) -> GPUTextureFormat {
self.format
}
/// <https://gpuweb.github.io/gpuweb/#dom-gputexture-usage>
fn Usage(&self) -> u32 {
self.texture_usage
}
} }

View file

@ -11,7 +11,7 @@ interface mixin GPUObjectBase {
}; };
dictionary GPUObjectDescriptorBase { dictionary GPUObjectDescriptorBase {
USVString label; USVString label = "";
}; };
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
@ -100,21 +100,26 @@ interface GPUAdapter {
Promise<GPUAdapterInfo> requestAdapterInfo(optional sequence<DOMString> unmaskHints = []); Promise<GPUAdapterInfo> requestAdapterInfo(optional sequence<DOMString> unmaskHints = []);
}; };
dictionary GPUDeviceDescriptor { dictionary GPUDeviceDescriptor: GPUObjectDescriptorBase {
sequence<GPUFeatureName> requiredFeatures = []; sequence<GPUFeatureName> requiredFeatures = [];
record<DOMString, GPUSize64> requiredLimits; record<DOMString, GPUSize64> requiredLimits;// = {};
}; };
enum GPUFeatureName { enum GPUFeatureName {
"depth-clip-control", "depth-clip-control",
"depth24unorm-stencil8",
"depth32float-stencil8", "depth32float-stencil8",
"pipeline-statistics-query",
"texture-compression-bc", "texture-compression-bc",
"texture-compression-bc-sliced-3d",
"texture-compression-etc2", "texture-compression-etc2",
"texture-compression-astc", "texture-compression-astc",
"timestamp-query", "timestamp-query",
"indirect-first-instance", "indirect-first-instance",
"shader-f16",
"rg11b10ufloat-renderable",
"bgra8unorm-storage",
"float32-filterable",
"clip-distances",
"dual-source-blending",
}; };
[Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), /*Serializable,*/ Pref="dom.webgpu.enabled"]
@ -134,22 +139,24 @@ interface GPUDevice: EventTarget {
[NewObject] [NewObject]
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {}); GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
[Throws]
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor); GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor); GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
[Throws]
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor); GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
[NewObject] [NewObject]
Promise<GPUComputePipeline> createComputePipelineAsync(GPUComputePipelineDescriptor descriptor); Promise<GPUComputePipeline> createComputePipelineAsync(GPUComputePipelineDescriptor descriptor);
[NewObject] [Throws, NewObject]
Promise<GPURenderPipeline> createRenderPipelineAsync(GPURenderPipelineDescriptor descriptor); Promise<GPURenderPipeline> createRenderPipelineAsync(GPURenderPipelineDescriptor descriptor);
[NewObject] [NewObject]
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {}); GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
[NewObject] [Throws, NewObject]
GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor); GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
//[NewObject] //[NewObject]
//GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor); //GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor);
@ -199,10 +206,19 @@ interface GPUMapMode {
[Exposed=(Window, DedicatedWorker), Serializable , Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Serializable , Pref="dom.webgpu.enabled"]
interface GPUTexture { interface GPUTexture {
[NewObject] [Throws, NewObject]
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {}); GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
undefined destroy(); undefined destroy();
readonly attribute GPUIntegerCoordinateOut width;
readonly attribute GPUIntegerCoordinateOut height;
readonly attribute GPUIntegerCoordinateOut depthOrArrayLayers;
readonly attribute GPUIntegerCoordinateOut mipLevelCount;
readonly attribute GPUSize32Out sampleCount;
readonly attribute GPUTextureDimension dimension;
readonly attribute GPUTextureFormat format;
readonly attribute GPUFlagsConstant usage;
}; };
GPUTexture includes GPUObjectBase; GPUTexture includes GPUObjectBase;
@ -293,8 +309,10 @@ enum GPUTextureFormat {
"bgra8unorm", "bgra8unorm",
"bgra8unorm-srgb", "bgra8unorm-srgb",
// Packed 32-bit formats // Packed 32-bit formats
"rgb9e5ufloat",
"rgb10a2uint",
"rgb10a2unorm", "rgb10a2unorm",
"rg11b10float", "rg11b10ufloat",
// 64-bit formats // 64-bit formats
"rg32uint", "rg32uint",
@ -309,13 +327,16 @@ enum GPUTextureFormat {
"rgba32sint", "rgba32sint",
"rgba32float", "rgba32float",
// Depth and stencil formats // Depth/stencil formats
//"stencil8", //TODO "stencil8",
//"depth16unorm", "depth16unorm",
"depth24plus", "depth24plus",
"depth24plus-stencil8", "depth24plus-stencil8",
"depth32float", "depth32float",
// "depth32float-stencil8" feature
"depth32float-stencil8",
// BC compressed formats usable if "texture-compression-bc" is both // BC compressed formats usable if "texture-compression-bc" is both
// supported by the device/user agent and enabled in requestDevice. // supported by the device/user agent and enabled in requestDevice.
"bc1-rgba-unorm", "bc1-rgba-unorm",
@ -333,11 +354,49 @@ enum GPUTextureFormat {
"bc7-rgba-unorm", "bc7-rgba-unorm",
"bc7-rgba-unorm-srgb", "bc7-rgba-unorm-srgb",
// "depth24unorm-stencil8" feature // ETC2 compressed formats usable if "texture-compression-etc2" is both
//"depth24unorm-stencil8", // supported by the device/user agent and enabled in requestDevice.
"etc2-rgb8unorm",
"etc2-rgb8unorm-srgb",
"etc2-rgb8a1unorm",
"etc2-rgb8a1unorm-srgb",
"etc2-rgba8unorm",
"etc2-rgba8unorm-srgb",
"eac-r11unorm",
"eac-r11snorm",
"eac-rg11unorm",
"eac-rg11snorm",
// "depth32float-stencil8" feature // ASTC compressed formats usable if "texture-compression-astc" is both
//"depth32float-stencil8", // supported by the device/user agent and enabled in requestDevice.
"astc-4x4-unorm",
"astc-4x4-unorm-srgb",
"astc-5x4-unorm",
"astc-5x4-unorm-srgb",
"astc-5x5-unorm",
"astc-5x5-unorm-srgb",
"astc-6x5-unorm",
"astc-6x5-unorm-srgb",
"astc-6x6-unorm",
"astc-6x6-unorm-srgb",
"astc-8x5-unorm",
"astc-8x5-unorm-srgb",
"astc-8x6-unorm",
"astc-8x6-unorm-srgb",
"astc-8x8-unorm",
"astc-8x8-unorm-srgb",
"astc-10x5-unorm",
"astc-10x5-unorm-srgb",
"astc-10x6-unorm",
"astc-10x6-unorm-srgb",
"astc-10x8-unorm",
"astc-10x8-unorm-srgb",
"astc-10x10-unorm",
"astc-10x10-unorm-srgb",
"astc-12x10-unorm",
"astc-12x10-unorm-srgb",
"astc-12x12-unorm",
"astc-12x12-unorm-srgb",
}; };
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
@ -547,7 +606,7 @@ interface mixin GPUPipelineBase {
dictionary GPUProgrammableStage { dictionary GPUProgrammableStage {
required GPUShaderModule module; required GPUShaderModule module;
required USVString entryPoint; USVString entryPoint;
}; };
[Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"] [Exposed=(Window, DedicatedWorker), Serializable, Pref="dom.webgpu.enabled"]
@ -1160,6 +1219,12 @@ typedef [EnforceRange] unsigned long GPUIndex32;
typedef [EnforceRange] unsigned long GPUSize32; typedef [EnforceRange] unsigned long GPUSize32;
typedef [EnforceRange] long GPUSignedOffset32; typedef [EnforceRange] long GPUSignedOffset32;
typedef unsigned long long GPUSize64Out;
typedef unsigned long GPUIntegerCoordinateOut;
typedef unsigned long GPUSize32Out;
typedef unsigned long GPUFlagsConstant;
dictionary GPUColorDict { dictionary GPUColorDict {
required double r; required double r;
required double g; required double g;

View file

@ -101,7 +101,7 @@ def handle_preset(s: str) -> Optional[JobConfig]:
elif s == "webgpu": elif s == "webgpu":
return JobConfig("WebGPU CTS", Workflow.LINUX, return JobConfig("WebGPU CTS", Workflow.LINUX,
wpt_layout=Layout.layout2020, # reftests are mode for new layout wpt_layout=Layout.layout2020, # reftests are mode for new layout
wpt_args="_webgpu", # run only webgpu cts wpt_args="--processes 1 _webgpu", # run only webgpu cts
profile="production", # WebGPU works to slow with debug assert profile="production", # WebGPU works to slow with debug assert
unit_tests=False) # production profile does not work with unit-tests unit_tests=False) # production profile does not work with unit-tests
else: else:

File diff suppressed because it is too large Load diff