diff --git a/Cargo.lock b/Cargo.lock index c6454a23b8b..6c2fe1c0f0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6955,7 +6955,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#430b29d781200009ef02839e41136718ff62456a" +source = "git+https://github.com/gfx-rs/wgpu#7e8b51b4286bd9452567eb1a56edb8e9b7c7f684" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -6982,7 +6982,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.5.0" -source = "git+https://github.com/gfx-rs/wgpu#430b29d781200009ef02839e41136718ff62456a" +source = "git+https://github.com/gfx-rs/wgpu#7e8b51b4286bd9452567eb1a56edb8e9b7c7f684" dependencies = [ "bitflags", "serde", diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs index 19f6f8258d4..af5f54d919e 100644 --- a/components/script/dom/gpudevice.rs +++ b/components/script/dom/gpudevice.rs @@ -73,7 +73,7 @@ use std::collections::HashMap; use std::ptr::NonNull; use std::rc::Rc; use webgpu::wgpu::{ - binding_model as wgpu_bind, command::RenderBundleEncoder, pipeline as wgpu_pipe, + binding_model as wgpu_bind, command as wgpu_com, pipeline as wgpu_pipe, resource as wgpu_res, }; use webgpu::{self, identity::WebGPUOpResult, wgt, ErrorScopeId, WebGPU, WebGPURequest}; @@ -320,12 +320,17 @@ impl GPUDeviceMethods for GPUDevice { /// https://gpuweb.github.io/gpuweb/#dom-gpudevice-createbuffer fn CreateBuffer(&self, descriptor: &GPUBufferDescriptor) -> DomRoot { - let desc = wgt::BufferUsage::from_bits(descriptor.usage).map(|usg| wgt::BufferDescriptor { - label: descriptor.parent.label.as_ref().map(|s| s.to_string()), - size: descriptor.size, - usage: usg, - mapped_at_creation: descriptor.mappedAtCreation, - }); + let desc = + wgt::BufferUsage::from_bits(descriptor.usage).map(|usg| wgpu_res::BufferDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + size: descriptor.size as wgt::BufferAddress, + usage: usg, + mapped_at_creation: descriptor.mappedAtCreation, + }); let id = self .global() .wgpu_id_hub() @@ -464,14 +469,19 @@ impl GPUDeviceMethods for GPUDevice { }, }; - wgt::BindGroupLayoutEntry::new(bind.binding, visibility, ty) + wgt::BindGroupLayoutEntry { + binding: bind.binding, + visibility: visibility, + ty, + count: None, + } }) .collect::>(); let scope_id = self.use_current_scope(); let desc = if valid { - Some(wgt::BindGroupLayoutDescriptor { + Some(wgpu_bind::BindGroupLayoutDescriptor { label: descriptor .parent .label @@ -518,7 +528,12 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPUPipelineLayoutDescriptor, ) -> DomRoot { - let desc = wgt::PipelineLayoutDescriptor { + let desc = wgpu_bind::PipelineLayoutDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), bind_group_layouts: Cow::Owned( descriptor .bindGroupLayouts @@ -673,7 +688,13 @@ impl GPUDeviceMethods for GPUDevice { let scope_id = self.use_current_scope(); let desc = wgpu_pipe::ComputePipelineDescriptor { - layout: descriptor.parent.layout.id().0, + label: descriptor + .parent + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + layout: Some(descriptor.parent.layout.id().0), compute_stage: wgpu_pipe::ProgrammableStageDescriptor { module: descriptor.computeStage.module.id().0, entry_point: Cow::Owned(descriptor.computeStage.entryPoint.to_string()), @@ -718,7 +739,11 @@ impl GPUDeviceMethods for GPUDevice { WebGPURequest::CreateCommandEncoder { device_id: self.device.0, command_encoder_id, - label: descriptor.parent.label.as_ref().map(|s| s.to_string()), + label: descriptor + .parent + .label + .as_ref() + .map(|l| Cow::Owned(l.to_string())), }, )) .expect("Failed to create WebGPU command encoder"); @@ -739,8 +764,12 @@ impl GPUDeviceMethods for GPUDevice { fn CreateTexture(&self, descriptor: &GPUTextureDescriptor) -> DomRoot { let size = convert_texture_size_to_dict(&descriptor.size); let desc = - wgt::TextureUsage::from_bits(descriptor.usage).map(|usg| wgt::TextureDescriptor { - label: descriptor.parent.label.as_ref().map(|s| s.to_string()), + wgt::TextureUsage::from_bits(descriptor.usage).map(|usg| wgpu_res::TextureDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|l| Cow::Owned(l.to_string())), size: convert_texture_size_to_wgt(&size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, @@ -803,11 +832,17 @@ impl GPUDeviceMethods for GPUDevice { .lock() .create_sampler_id(self.device.0.backend()); let compare_enable = descriptor.compare.is_some(); - let desc = wgt::SamplerDescriptor { - label: descriptor.parent.label.as_ref().map(|s| s.to_string()), - address_mode_u: convert_address_mode(descriptor.addressModeU), - address_mode_v: convert_address_mode(descriptor.addressModeV), - address_mode_w: convert_address_mode(descriptor.addressModeW), + let desc = wgpu_res::SamplerDescriptor { + label: descriptor + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + address_modes: [ + convert_address_mode(descriptor.addressModeU), + convert_address_mode(descriptor.addressModeV), + convert_address_mode(descriptor.addressModeW), + ], mag_filter: convert_filter_mode(descriptor.magFilter), min_filter: convert_filter_mode(descriptor.minFilter), mipmap_filter: convert_filter_mode(descriptor.mipmapFilter), @@ -872,7 +907,13 @@ impl GPUDeviceMethods for GPUDevice { let desc = if valid { Some(wgpu_pipe::RenderPipelineDescriptor { - layout: descriptor.parent.layout.id().0, + label: descriptor + .parent + .parent + .label + .as_ref() + .map(|s| Cow::Owned(s.to_string())), + layout: Some(descriptor.parent.layout.id().0), vertex_stage: wgpu_pipe::ProgrammableStageDescriptor { module: descriptor.vertexStage.module.id().0, entry_point: Cow::Owned(descriptor.vertexStage.entryPoint.to_string()), @@ -911,23 +952,27 @@ impl GPUDeviceMethods for GPUDevice { format: convert_texture_format(dss_desc.format), depth_write_enabled: dss_desc.depthWriteEnabled, depth_compare: convert_compare_function(dss_desc.depthCompare), - stencil_front: wgt::StencilStateFaceDescriptor { - compare: convert_compare_function(dss_desc.stencilFront.compare), - fail_op: convert_stencil_op(dss_desc.stencilFront.failOp), - depth_fail_op: convert_stencil_op(dss_desc.stencilFront.depthFailOp), - pass_op: convert_stencil_op(dss_desc.stencilFront.passOp), + stencil: wgt::StencilStateDescriptor { + front: wgt::StencilStateFaceDescriptor { + compare: convert_compare_function(dss_desc.stencilFront.compare), + fail_op: convert_stencil_op(dss_desc.stencilFront.failOp), + depth_fail_op: convert_stencil_op( + dss_desc.stencilFront.depthFailOp, + ), + pass_op: convert_stencil_op(dss_desc.stencilFront.passOp), + }, + back: wgt::StencilStateFaceDescriptor { + compare: convert_compare_function(dss_desc.stencilBack.compare), + fail_op: convert_stencil_op(dss_desc.stencilBack.failOp), + depth_fail_op: convert_stencil_op(dss_desc.stencilBack.depthFailOp), + pass_op: convert_stencil_op(dss_desc.stencilBack.passOp), + }, + read_mask: dss_desc.stencilReadMask, + write_mask: dss_desc.stencilWriteMask, }, - stencil_back: wgt::StencilStateFaceDescriptor { - compare: convert_compare_function(dss_desc.stencilBack.compare), - fail_op: convert_stencil_op(dss_desc.stencilBack.failOp), - depth_fail_op: convert_stencil_op(dss_desc.stencilBack.depthFailOp), - pass_op: convert_stencil_op(dss_desc.stencilBack.passOp), - }, - stencil_read_mask: dss_desc.stencilReadMask, - stencil_write_mask: dss_desc.stencilWriteMask, } }), - vertex_state: wgt::VertexStateDescriptor { + vertex_state: wgpu_pipe::VertexStateDescriptor { index_format: match vs_desc.indexFormat { GPUIndexFormat::Uint16 => wgt::IndexFormat::Uint16, GPUIndexFormat::Uint32 => wgt::IndexFormat::Uint32, @@ -936,7 +981,7 @@ impl GPUDeviceMethods for GPUDevice { vs_desc .vertexBuffers .iter() - .map(|buffer| wgt::VertexBufferDescriptor { + .map(|buffer| wgpu_pipe::VertexBufferDescriptor { stride: buffer.arrayStride, step_mode: match buffer.stepMode { GPUInputStepMode::Vertex => wgt::InputStepMode::Vertex, @@ -1002,7 +1047,7 @@ impl GPUDeviceMethods for GPUDevice { &self, descriptor: &GPURenderBundleEncoderDescriptor, ) -> DomRoot { - let desc = wgt::RenderBundleEncoderDescriptor { + let desc = wgpu_com::RenderBundleEncoderDescriptor { label: descriptor .parent .label @@ -1022,7 +1067,8 @@ impl GPUDeviceMethods for GPUDevice { }; // Handle error gracefully - let render_bundle_encoder = RenderBundleEncoder::new(&desc, self.device.0, None).unwrap(); + let render_bundle_encoder = + wgpu_com::RenderBundleEncoder::new(&desc, self.device.0, None).unwrap(); GPURenderBundleEncoder::new( &self.global(), diff --git a/components/script/dom/gpurenderbundleencoder.rs b/components/script/dom/gpurenderbundleencoder.rs index 7557171a9f5..13109d0b9b9 100644 --- a/components/script/dom/gpurenderbundleencoder.rs +++ b/components/script/dom/gpurenderbundleencoder.rs @@ -15,6 +15,7 @@ use crate::dom::gpudevice::GPUDevice; use crate::dom::gpurenderbundle::GPURenderBundle; use crate::dom::gpurenderpipeline::GPURenderPipeline; use dom_struct::dom_struct; +use std::borrow::Cow; use webgpu::{ wgpu::command::{bundle_ffi as wgpu_bundle, RenderBundleEncoder}, wgt, WebGPU, WebGPURenderBundle, WebGPURequest, @@ -184,7 +185,11 @@ impl GPURenderBundleEncoderMethods for GPURenderBundleEncoder { /// https://gpuweb.github.io/gpuweb/#dom-gpurenderbundleencoder-finish fn Finish(&self, descriptor: &GPURenderBundleDescriptor) -> DomRoot { let desc = wgt::RenderBundleDescriptor { - label: descriptor.parent.label.as_ref().map(|s| s.to_string()), + label: descriptor + .parent + .label + .as_ref() + .map(|l| Cow::Owned(l.to_string())), }; let encoder = self.render_bundle_encoder.borrow_mut().take().unwrap(); let render_bundle_id = self diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs index a7137d1bd61..fc93e300a9e 100644 --- a/components/script/dom/gputexture.rs +++ b/components/script/dom/gputexture.rs @@ -7,7 +7,7 @@ use crate::dom::bindings::codegen::Bindings::GPUTextureBinding::{ GPUExtent3DDict, GPUTextureDimension, GPUTextureFormat, GPUTextureMethods, }; use crate::dom::bindings::codegen::Bindings::GPUTextureViewBinding::{ - GPUTextureAspect, GPUTextureViewDescriptor, GPUTextureViewDimension, + GPUTextureAspect, GPUTextureViewDescriptor, }; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; @@ -16,10 +16,12 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::gpudevice::{convert_texture_format, convert_texture_view_dimension, GPUDevice}; use crate::dom::gputextureview::GPUTextureView; use dom_struct::dom_struct; +use std::borrow::Cow; use std::num::NonZeroU32; use std::string::String; use webgpu::{ - identity::WebGPUOpResult, wgt, WebGPU, WebGPURequest, WebGPUTexture, WebGPUTextureView, + identity::WebGPUOpResult, wgpu::resource, wgt, WebGPU, WebGPURequest, WebGPUTexture, + WebGPUTextureView, }; #[dom_struct] @@ -123,23 +125,6 @@ impl GPUTextureMethods for GPUTexture { /// https://gpuweb.github.io/gpuweb/#dom-gputexture-createview fn CreateView(&self, descriptor: &GPUTextureViewDescriptor) -> DomRoot { - let dimension = if let Some(d) = descriptor.dimension { - d - } else { - match self.dimension { - GPUTextureDimension::_1d => GPUTextureViewDimension::_1d, - GPUTextureDimension::_2d => { - if self.texture_size.depth > 1 && descriptor.arrayLayerCount.is_none() { - GPUTextureViewDimension::_2d_array - } else { - GPUTextureViewDimension::_2d - } - }, - GPUTextureDimension::_3d => GPUTextureViewDimension::_3d, - } - }; - - let format = descriptor.format.unwrap_or(self.format); let scope_id = self.device.use_current_scope(); let mut valid = true; let level_count = descriptor.mipLevelCount.and_then(|count| { @@ -156,14 +141,16 @@ impl GPUTextureMethods for GPUTexture { }); let desc = if valid { - Some(wgt::TextureViewDescriptor { + Some(resource::TextureViewDescriptor { label: descriptor .parent .label .as_ref() - .map(|s| String::from(s.as_ref())), - format: convert_texture_format(format), - dimension: convert_texture_view_dimension(dimension), + .map(|l| Cow::Owned(l.to_string())), + format: descriptor.format.map(|fr| convert_texture_format(fr)), + dimension: descriptor + .dimension + .map(|dm| convert_texture_view_dimension(dm)), aspect: match descriptor.aspect { GPUTextureAspect::All => wgt::TextureAspect::All, GPUTextureAspect::Stencil_only => wgt::TextureAspect::StencilOnly, diff --git a/components/webgpu/lib.rs b/components/webgpu/lib.rs index cbfe4cd161e..3c970a87760 100644 --- a/components/webgpu/lib.rs +++ b/components/webgpu/lib.rs @@ -21,9 +21,7 @@ use servo_config::pref; use smallvec::SmallVec; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::ffi::CString; use std::num::NonZeroU64; -use std::ptr; use std::rc::Rc; use std::slice; use std::sync::{Arc, Mutex}; @@ -33,13 +31,19 @@ use webrender_traits::{ WebrenderImageSource, }; use wgpu::{ - binding_model::BindGroupDescriptor, - command::{BufferCopyView, ComputePass, RenderBundleEncoder, RenderPass, TextureCopyView}, + binding_model::{BindGroupDescriptor, BindGroupLayoutDescriptor, PipelineLayoutDescriptor}, + command::{ + BufferCopyView, ComputePass, RenderBundleDescriptor, RenderBundleEncoder, RenderPass, + TextureCopyView, + }, device::HostMap, id, instance::RequestAdapterOptions, pipeline::{ComputePipelineDescriptor, RenderPipelineDescriptor}, - resource::{BufferMapAsyncStatus, BufferMapOperation}, + resource::{ + BufferDescriptor, BufferMapAsyncStatus, BufferMapOperation, SamplerDescriptor, + TextureDescriptor, TextureViewDescriptor, + }, }; pub type ErrorScopeId = NonZeroU64; @@ -119,19 +123,19 @@ pub enum WebGPURequest { CreateBindGroupLayout { device_id: id::DeviceId, bind_group_layout_id: id::BindGroupLayoutId, - descriptor: Option>, + descriptor: Option>, }, CreateBuffer { device_id: id::DeviceId, buffer_id: id::BufferId, - descriptor: Option>>, + descriptor: Option>, }, CreateCommandEncoder { device_id: id::DeviceId, // TODO(zakorgy): Serialize CommandEncoderDescriptor in wgpu-core // wgpu::command::CommandEncoderDescriptor, command_encoder_id: id::CommandEncoderId, - label: Option, + label: Option>, }, CreateComputePipeline { device_id: id::DeviceId, @@ -142,7 +146,7 @@ pub enum WebGPURequest { CreatePipelineLayout { device_id: id::DeviceId, pipeline_layout_id: id::PipelineLayoutId, - descriptor: wgt::PipelineLayoutDescriptor<'static, id::BindGroupLayoutId>, + descriptor: PipelineLayoutDescriptor<'static>, }, CreateRenderPipeline { device_id: id::DeviceId, @@ -152,7 +156,7 @@ pub enum WebGPURequest { CreateSampler { device_id: id::DeviceId, sampler_id: id::SamplerId, - descriptor: wgt::SamplerDescriptor>, + descriptor: SamplerDescriptor<'static>, }, CreateShaderModule { device_id: id::DeviceId, @@ -170,13 +174,13 @@ pub enum WebGPURequest { CreateTexture { device_id: id::DeviceId, texture_id: id::TextureId, - descriptor: Option>>, + descriptor: Option>, }, CreateTextureView { texture_id: id::TextureId, texture_view_id: id::TextureViewId, device_id: id::DeviceId, - descriptor: Option>>, + descriptor: Option>, }, DestroyBuffer(id::BufferId), DestroySwapChain { @@ -189,7 +193,7 @@ pub enum WebGPURequest { FreeDevice(id::DeviceId), RenderBundleEncoderFinish { render_bundle_encoder: RenderBundleEncoder, - descriptor: wgt::RenderBundleDescriptor>, + descriptor: RenderBundleDescriptor<'static>, render_bundle_id: id::RenderBundleId, device_id: id::DeviceId, }, @@ -579,16 +583,8 @@ impl<'a> WGPU<'a> { } => { let global = &self.global; if let Some(desc) = descriptor { - let st; - let label = match desc.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let result = gfx_select!(buffer_id => - global.device_create_buffer(device_id, &desc.map_label(|_| label), buffer_id)); + global.device_create_buffer(device_id, &desc, buffer_id)); if result.is_err() { let _ = gfx_select!(buffer_id => global.buffer_error(buffer_id)); } @@ -603,14 +599,6 @@ impl<'a> WGPU<'a> { label, } => { let global = &self.global; - let st; - let label = match label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let desc = wgt::CommandEncoderDescriptor { label }; let result = gfx_select!(command_encoder_id => global.device_create_command_encoder(device_id, &desc, command_encoder_id)); @@ -626,7 +614,7 @@ impl<'a> WGPU<'a> { } => { let global = &self.global; let result = gfx_select!(compute_pipeline_id => - global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id)); + global.device_create_compute_pipeline(device_id, &descriptor, compute_pipeline_id, None)); if result.is_err() { let _ = gfx_select!(compute_pipeline_id => global.compute_pipeline_error(compute_pipeline_id)); @@ -664,7 +652,7 @@ impl<'a> WGPU<'a> { let global = &self.global; if let Some(desc) = descriptor { let result = gfx_select!(render_pipeline_id => - global.device_create_render_pipeline(device_id, &desc, render_pipeline_id)); + global.device_create_render_pipeline(device_id, &desc, render_pipeline_id, None)); if result.is_err() { let _ = gfx_select!(render_pipeline_id => global.render_pipeline_error(render_pipeline_id)); @@ -680,17 +668,9 @@ impl<'a> WGPU<'a> { descriptor, } => { let global = &self.global; - let st; - let label = match descriptor.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let result = gfx_select!(sampler_id => global.device_create_sampler( device_id, - &descriptor.map_label(|_| label), + &descriptor, sampler_id )); if result.is_err() { @@ -763,17 +743,9 @@ impl<'a> WGPU<'a> { } => { let global = &self.global; if let Some(desc) = descriptor { - let st; - let label = match desc.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let result = gfx_select!(texture_id => global.device_create_texture( device_id, - &desc.map_label(|_| label), + &desc, texture_id )); if result.is_err() { @@ -792,17 +764,9 @@ impl<'a> WGPU<'a> { } => { let global = &self.global; if let Some(desc) = descriptor { - let st; - let label = match desc.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let result = gfx_select!(texture_view_id => global.texture_create_view( texture_id, - Some(&desc.map_label(|_| label)), + &desc, texture_view_id )); if result.is_err() { @@ -877,17 +841,9 @@ impl<'a> WGPU<'a> { device_id, } => { let global = &self.global; - let st; - let label = match descriptor.label { - Some(ref s) => { - st = CString::new(s.as_bytes()).unwrap(); - st.as_ptr() - }, - None => ptr::null(), - }; let result = gfx_select!(render_bundle_id => global.render_bundle_encoder_finish( render_bundle_encoder, - &descriptor.map_label(|_| label), + &descriptor, render_bundle_id )); if result.is_err() { @@ -1051,7 +1007,7 @@ impl<'a> WGPU<'a> { let buffer_size = (buffer_stride * size.height as u32) as wgt::BufferAddress; let buffer_desc = wgt::BufferDescriptor { - label: ptr::null(), + label: None, size: buffer_size, usage: wgt::BufferUsage::MAP_READ | wgt::BufferUsage::COPY_DST, @@ -1079,7 +1035,7 @@ impl<'a> WGPU<'a> { let buffer_size = (size.height as u32 * buffer_stride) as wgt::BufferAddress; - let comm_desc = wgt::CommandEncoderDescriptor { label: ptr::null() }; + let comm_desc = wgt::CommandEncoderDescriptor { label: None }; let _ = gfx_select!(encoder_id => global.device_create_command_encoder( device_id, &comm_desc, diff --git a/tests/wpt/webgpu/meta/MANIFEST.json b/tests/wpt/webgpu/meta/MANIFEST.json index 55c796b9fcd..28666d5d9c1 100644 --- a/tests/wpt/webgpu/meta/MANIFEST.json +++ b/tests/wpt/webgpu/meta/MANIFEST.json @@ -58,7 +58,7 @@ ], "gpu": { "device_pool.js": [ - "c6be73f9918be979816bf02978e8429ce8b4d63d", + "f72b6b734c671ff0316fadfec49e0a93bd16fd10", [] ], "implementation.js": [ @@ -102,7 +102,7 @@ [] ], "json_param_value.js": [ - "1bb32d06dfdf95be6953faac150b767585198cf7", + "921b3ddce6aacde8e3b05d4133dc07ffb90842f8", [] ], "parseQuery.js": [ @@ -161,7 +161,7 @@ ] }, "version.js": [ - "4d5e72c0442fdbdd4d5ceeefa14dcbaafae4ffaa", + "794e3cdef44214801f15234a61aaf5af338f97fc", [] ] }, @@ -229,7 +229,7 @@ ], "render_pass": { "storeOp.spec.js": [ - "c02e99db655933431cf8f310c21eac4febaf380d", + "83ae8657c1c822b6cfc8f511089de88dfd2d8fdc", [] ] }, @@ -239,18 +239,36 @@ [] ], "texture_zero_init_test.js": [ - "e3c21011bb288492bd137be9e2e43b5efd02aa36", + "381d7dcb0a8e9574834629223308c7ef0e375b4b", [] ] } }, "validation": { + "copyBufferToBuffer.spec.js": [ + "5fd4877383a47b1e3ca27af8e0843781dbf5a443", + [] + ], + "copy_between_linear_data_and_texture": { + "copyBetweenLinearDataAndTexture.js": [ + "0db6e68d4af6e395ba07157fd4b1ed0c567fd182", + [] + ], + "copyBetweenLinearDataAndTexture_dataRelated.spec.js": [ + "be1395b664276f13a728a60acee835d96753e6e1", + [] + ], + "copyBetweenLinearDataAndTexture_textureRelated.spec.js": [ + "bef71943fae2bc6f0dcaa4ae53b744190ccdc00c", + [] + ] + }, "createBindGroup.spec.js": [ "fa585038e39ff6208787ee89bc177bdb13cdc385", [] ], "createBindGroupLayout.spec.js": [ - "9c0df538b278aaa38d11f3922b749799f72f4c3f", + "43fd923687b68d9214305b04ea1573e044245928", [] ], "createPipelineLayout.spec.js": [ @@ -258,7 +276,7 @@ [] ], "createTexture.spec.js": [ - "a9c7a8be01e03bcda1aa2f96374c30c0ce0bbe45", + "ceff54e136ff321bf22a8647790c3263404f6afc", [] ], "createView.spec.js": [ @@ -266,11 +284,11 @@ [] ], "error_scope.spec.js": [ - "5523237daeba5d0c1c292dd3da8dead86a99f8e4", + "64575540e8bde1545565389108067bf4b078cae9", [] ], "fences.spec.js": [ - "cc04848410fed9f20b863aadbedf3482787b6de9", + "b50ebae572d9af8f4edd3f82c051877b6068374e", [] ], "queue_submit.spec.js": [ @@ -293,7 +311,7 @@ ], "resource_usages": { "textureUsageInRender.spec.js": [ - "6322ec25ee537584030c322ab99ec3d69e02b30e", + "12efa65ce2d9e9ed67cb2be398a0466424d38015", [] ] }, @@ -318,13 +336,13 @@ [] ], "validation_test.js": [ - "d816fd0594bd5097f4a7e3d2de91c3e0aa6e3f7b", + "c6cd14779bbb7b95e37bdb93d3f5be33902be6c2", [] ] } }, "capability_info.js": [ - "2e4264fe229c11bb387d300cebce6a4e69780cd1", + "10a8c5aa4b62c05830eabb33734d866939258ade", [] ], "examples.spec.js": [ @@ -332,23 +350,23 @@ [] ], "gpu_test.js": [ - "92f0e41840bd8e74eda57bbeda60757af798e2f9", + "f350131af3babe9729dec35261f7c445e2bf41d2", [] ], "idl": { "constants": { "flags.spec.js": [ - "1de75c84e5daeaafd3ac47b31b6011223b03e360", + "51b80aa8aa23cb987079f6dd228bb0bb68816624", [] ] }, "idl_test.js": [ - "231fc0945f87fe6aede03ec7a03c1ecaf7fe04db", + "3943563d2ac2c779e6cfb0ab033b92bca24e5749", [] ] }, "listing.js": [ - "8736de378a6a02235dfff5796f4fe4a963769001", + "3134cf0dd5693705ed82f0828f4dbd93fedf358e", [] ], "util": { @@ -357,12 +375,12 @@ [] ], "math.js": [ - "a76f1a00158ab50df82c74187de859dfbef41d60", + "4761467b586691662834dd0fbf3e86643a5eb823", [] ], "texture": { "layout.js": [ - "26d82a7be0aea4483b4b72d6faa2b9233a5f0039", + "c3c610bf0d93ebe66abf81d8f2017deba62641a3", [] ], "subresource.js": [ @@ -370,7 +388,7 @@ [] ], "texelData.js": [ - "8a827c47d21e1c1a89e081b2e70d1759c9208b0e", + "eadaa09633022e6c82355b07a4798c802c56a8e8", [] ] } @@ -383,7 +401,7 @@ ] }, "copyImageBitmapToTexture.spec.js": [ - "1432ff05e1daa192d5898bf1c7f42e84008b23b4", + "9df5ff94419baa92ff27f8b39cdc0ee99439dc06", [] ], "reftests": { @@ -396,7 +414,7 @@ [] ], "gpu_ref_test.js": [ - "dd58b543b01ec86c1a820d9d661a5c3f9b68b323", + "a45002835df48518eacb8d7887791ee200c3e3c1", [] ], "ref": { @@ -417,7 +435,7 @@ "testharness": { "webgpu": { "cts.html": [ - "e87ceb79a409fc3e3ddcccf38e48b865740e0809", + "28d69b38d20367b4c61e72e834f518a11e8de411", [ "webgpu/cts.html?q=webgpu:api,operation,buffers,map_detach:*", {} @@ -446,6 +464,18 @@ "webgpu/cts.html?q=webgpu:api,operation,render_pass,storeOp:*", {} ], + [ + "webgpu/cts.html?q=webgpu:api,validation,copyBufferToBuffer:*", + {} + ], + [ + "webgpu/cts.html?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_dataRelated:*", + {} + ], + [ + "webgpu/cts.html?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_textureRelated:*", + {} + ], [ "webgpu/cts.html?q=webgpu:api,validation,createBindGroup:*", {} diff --git a/tests/wpt/webgpu/meta/webgpu/cts.html.ini b/tests/wpt/webgpu/meta/webgpu/cts.html.ini index bb5f82cfa48..9a0e4bdddb0 100644 --- a/tests/wpt/webgpu/meta/webgpu/cts.html.ini +++ b/tests/wpt/webgpu/meta/webgpu/cts.html.ini @@ -261,7 +261,396 @@ [webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:readonly=true;depthStoreOp="clear"] expected: FAIL + [webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:readonly="_undef_";depthReadOnly=true] + expected: FAIL + + [webgpu:api,validation,render_pass,storeOp:store_op_and_read_only:readonly="_undef_";stencilReadOnly=true] + expected: FAIL + [cts.html?q=webgpu:api,validation,createPipelineLayout:*] [cts.html?q=webgpu:api,operation,command_buffer,render,basic:*] + +[cts.html?q=webgpu:api,validation,copyBufferToBuffer:*] + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_offset_alignment:srcOffset=2;dstOffset=0] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_with_invalid_buffer:] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=0;dstOffset=9007199254740984;copySize=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_within_same_buffer:srcOffset=4;dstOffset=0;copySize=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=0;dstOffset=16;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=0;dstOffset=36;copySize=0] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=0;dstOffset=36;copySize=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=0;dstOffset=9007199254740984;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=36;dstOffset=0;copySize=0] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=36;dstOffset=0;copySize=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=9007199254740984;dstOffset=0;copySize=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_size_alignment:copySize=5] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_size_alignment:copySize=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_within_same_buffer:srcOffset=0;dstOffset=4;copySize=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=9007199254740984;dstOffset=9007199254740984;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_offset_alignment:srcOffset=0;dstOffset=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_offset_alignment:srcOffset=0;dstOffset=5] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_within_same_buffer:srcOffset=0;dstOffset=8;copySize=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=0;dstOffset=20;copySize=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_within_same_buffer:srcOffset=8;dstOffset=0;copySize=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=0;dstOffset=0;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=2] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=16;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=9007199254740984;dstOffset=0;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=64] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=2;dstUsage=32] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_overflow:srcOffset=16;dstOffset=0;copySize=9007199254740984] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=256] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=256;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=20;dstOffset=0;copySize=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=0;dstOffset=0;copySize=36] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=16] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=1] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=4] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=32;dstUsage=8] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=128;dstUsage=512] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:copy_offset_alignment:srcOffset=5;dstOffset=0] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=4;dstUsage=128] + expected: FAIL + + [webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=64;dstUsage=256] + expected: FAIL + + +[cts.html?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_textureRelated:*] + expected: CRASH + +[cts.html?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_dataRelated:*] + expected: CRASH diff --git a/tests/wpt/webgpu/tests/webgpu/common/framework/gpu/device_pool.js b/tests/wpt/webgpu/tests/webgpu/common/framework/gpu/device_pool.js index c6be73f9918..f72b6b734c6 100644 --- a/tests/wpt/webgpu/tests/webgpu/common/framework/gpu/device_pool.js +++ b/tests/wpt/webgpu/tests/webgpu/common/framework/gpu/device_pool.js @@ -91,10 +91,13 @@ export class DevicePool { static async makeHolder() { const gpu = getGPU(); const adapter = await gpu.requestAdapter(); + assert(adapter !== null); + const device = await adapter.requestDevice(); + assert(device !== null); const holder = { acquired: false, - device: await adapter.requestDevice(), + device, lostReason: undefined, }; diff --git a/tests/wpt/webgpu/tests/webgpu/common/framework/query/json_param_value.js b/tests/wpt/webgpu/tests/webgpu/common/framework/query/json_param_value.js index 1bb32d06dfd..921b3ddce6a 100644 --- a/tests/wpt/webgpu/tests/webgpu/common/framework/query/json_param_value.js +++ b/tests/wpt/webgpu/tests/webgpu/common/framework/query/json_param_value.js @@ -3,10 +3,11 @@ **/ import { assert } from '../util/util.js'; // JSON can't represent `undefined` and by default stores it as `null`. // Instead, store `undefined` as this magic string value in JSON. -const jsUndefinedMagicValue = 'âś—undefined'; +const jsUndefinedMagicValue = '_undef_'; export function stringifyParamValue(value) { return JSON.stringify(value, (k, v) => { + // Make sure no one actually uses the magic value as a parameter. assert(v !== jsUndefinedMagicValue); return v === undefined ? jsUndefinedMagicValue : v; diff --git a/tests/wpt/webgpu/tests/webgpu/common/framework/version.js b/tests/wpt/webgpu/tests/webgpu/common/framework/version.js index 4d5e72c0442..794e3cdef44 100644 --- a/tests/wpt/webgpu/tests/webgpu/common/framework/version.js +++ b/tests/wpt/webgpu/tests/webgpu/common/framework/version.js @@ -1,3 +1,3 @@ // AUTO-GENERATED - DO NOT EDIT. See tools/gen_version. -export const version = 'a4499c8ced40640242a40448c4d4258e3fb830d3'; +export const version = 'fa4873f0a303566ca6f34744a253d96f5e462d3d'; diff --git a/tests/wpt/webgpu/tests/webgpu/cts.html b/tests/wpt/webgpu/tests/webgpu/cts.html index e87ceb79a40..28d69b38d20 100644 --- a/tests/wpt/webgpu/tests/webgpu/cts.html +++ b/tests/wpt/webgpu/tests/webgpu/cts.html @@ -36,6 +36,9 @@ + + + diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js index c02e99db655..83ae8657c1c 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/render_pass/storeOp.spec.js @@ -30,7 +30,11 @@ TODO: test with more interesting loadOp values`; import { params, poptions } from '../../../../common/framework/params_builder.js'; import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { kTextureFormatInfo, kTextureFormats } from '../../../capability_info.js'; +import { + kEncodableTextureFormatInfo, + kEncodableTextureFormats, + kSizedDepthStencilFormats, +} from '../../../capability_info.js'; import { GPUTest } from '../../../gpu_test.js'; // Test with a zero and non-zero mip. @@ -140,20 +144,16 @@ g.test('render_pass_store_op,color_attachment_with_depth_stencil_attachment') g.test('render_pass_store_op,color_attachment_only') .params( params() - .combine(poptions('colorFormat', kTextureFormats)) - // Filter out any depth/stencil or non-renderable formats - .filter( - ({ colorFormat }) => - kTextureFormatInfo[colorFormat].color && kTextureFormatInfo[colorFormat].renderable - ) + .combine(poptions('colorFormat', kEncodableTextureFormats)) + // Filter out any non-renderable formats + .filter(({ colorFormat }) => kEncodableTextureFormatInfo[colorFormat].renderable) .combine(poptions('storeOperation', kStoreOps)) .combine(poptions('mipLevel', kMipLevel)) .combine(poptions('arrayLayer', kArrayLayers)) ) .fn(t => { - const kColorFormat = 'rgba8unorm'; const colorAttachment = t.device.createTexture({ - format: kColorFormat, + format: t.params.colorFormat, size: { width: kWidth, height: kHeight, depth: t.params.arrayLayer + 1 }, mipLevelCount: kMipLevelCount, usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT, @@ -194,7 +194,7 @@ g.test('render_pass_store_op,color_attachment_only') expectedValue = { R: 1.0, G: 0.0, B: 0.0, A: 1.0 }; } - t.expectSingleColor(colorAttachment, kColorFormat, { + t.expectSingleColor(colorAttachment, t.params.colorFormat, { size: [kHeight, kWidth, 1], slice: t.params.arrayLayer, exp: expectedValue, @@ -266,15 +266,8 @@ g.test('render_pass_store_op,multiple_color_attachments') g.test('render_pass_store_op,depth_stencil_attachment_only') .params( params() - .combine(poptions('depthStencilFormat', kTextureFormats)) - // Filter out color and non-renderable formats. - .filter( - ({ depthStencilFormat }) => - (kTextureFormatInfo[depthStencilFormat].depth || - kTextureFormatInfo[depthStencilFormat].stencil) && - kTextureFormatInfo[depthStencilFormat].renderable && - kTextureFormatInfo[depthStencilFormat].copyable - ) + // TODO: Also test unsized depth/stencil formats + .combine(poptions('depthStencilFormat', kSizedDepthStencilFormats)) .combine(poptions('storeOperation', kStoreOps)) .combine(poptions('mipLevel', kMipLevel)) .combine(poptions('arrayLayer', kArrayLayers)) diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js index e3c21011bb2..381d7dcb0a8 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/operation/resource_init/texture_zero_init_test.js @@ -15,7 +15,11 @@ } import { params, poptions, pbool } from '../../../../common/framework/params_builder.js'; import { assert, unreachable } from '../../../../common/framework/util/util.js'; -import { kTextureAspects, kTextureFormatInfo, kTextureFormats } from '../../../capability_info.js'; +import { + kTextureAspects, + kUncompressedTextureFormatInfo, + kUncompressedTextureFormats, +} from '../../../capability_info.js'; import { GPUTest } from '../../../gpu_test.js'; import { createTextureUploadBuffer } from '../../../util/texture/layout.js'; import { SubresourceRange } from '../../../util/texture/subresource.js'; @@ -192,10 +196,10 @@ function getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMe usage |= GPUTextureUsage.OUTPUT_ATTACHMENT; } - if (!kTextureFormatInfo[format].copyable) { + if (!kUncompressedTextureFormatInfo[format].copyDst) { // Copies are not possible. We need OutputAttachment to initialize // canary data. - assert(kTextureFormatInfo[format].renderable); + assert(kUncompressedTextureFormatInfo[format].renderable); usage |= GPUTextureUsage.OUTPUT_ATTACHMENT; } @@ -306,7 +310,7 @@ export class TextureZeroInitTest extends GPUTest { this.params.aspect, subresourceRange )) { - if (kTextureFormatInfo[this.params.format].color) { + if (kUncompressedTextureFormatInfo[this.params.format].color) { commandEncoder .beginRenderPass({ colorAttachments: [ @@ -383,10 +387,13 @@ export class TextureZeroInitTest extends GPUTest { } initializeTexture(texture, state, subresourceRange) { - if (this.params.sampleCount > 1 || !kTextureFormatInfo[this.params.format].copyable) { + if ( + this.params.sampleCount > 1 || + !kUncompressedTextureFormatInfo[this.params.format].copyDst + ) { // Copies to multisampled textures not yet specified. // Use a storeOp for now. - assert(kTextureFormatInfo[this.params.format].renderable); + assert(kUncompressedTextureFormatInfo[this.params.format].renderable); this.initializeWithStoreOp(state, texture, subresourceRange); } else { this.initializeWithCopy(texture, state, subresourceRange); @@ -400,7 +407,7 @@ export class TextureZeroInitTest extends GPUTest { this.params.aspect, subresourceRange )) { - if (kTextureFormatInfo[this.params.format].color) { + if (kUncompressedTextureFormatInfo[this.params.format].color) { commandEncoder .beginRenderPass({ colorAttachments: [ @@ -434,12 +441,12 @@ export class TextureZeroInitTest extends GPUTest { return ( // TODO: Consider making a list of "valid" texture descriptors in capability_info. params() - .combine(poptions('format', kTextureFormats)) + .combine(poptions('format', kUncompressedTextureFormats)) .combine(poptions('aspect', kTextureAspects)) .unless( ({ format, aspect }) => - (aspect === 'depth-only' && !kTextureFormatInfo[format].depth) || - (aspect === 'stencil-only' && !kTextureFormatInfo[format].stencil) + (aspect === 'depth-only' && !kUncompressedTextureFormatInfo[format].depth) || + (aspect === 'stencil-only' && !kUncompressedTextureFormatInfo[format].stencil) ) .combine(poptions('mipLevelCount', kMipLevelCounts)) .combine(poptions('sampleCount', kSampleCounts)) @@ -456,14 +463,16 @@ export class TextureZeroInitTest extends GPUTest { (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) && (format === 'depth24plus' || format === 'depth24plus-stencil8') ) - .unless( - ({ readMethod, format }) => - (readMethod === ReadMethod.DepthTest && !kTextureFormatInfo[format].depth) || - (readMethod === ReadMethod.StencilTest && !kTextureFormatInfo[format].stencil) || - (readMethod === ReadMethod.ColorBlending && !kTextureFormatInfo[format].color) || + .unless(({ readMethod, format }) => { + const info = kUncompressedTextureFormatInfo[format]; + return ( + (readMethod === ReadMethod.DepthTest && !info.depth) || + (readMethod === ReadMethod.StencilTest && !info.stencil) || + (readMethod === ReadMethod.ColorBlending && !info.color) || // TODO: Test with depth sampling - (readMethod === ReadMethod.Sample && kTextureFormatInfo[format].depth) - ) + (readMethod === ReadMethod.Sample && info.depth) + ); + }) .unless( ({ readMethod, sampleCount }) => // We can only read from multisampled textures by sampling. @@ -481,11 +490,13 @@ export class TextureZeroInitTest extends GPUTest { readMethod ); - if (usage & GPUTextureUsage.OUTPUT_ATTACHMENT && !kTextureFormatInfo[format].renderable) { + const info = kUncompressedTextureFormatInfo[format]; + + if (usage & GPUTextureUsage.OUTPUT_ATTACHMENT && !info.renderable) { return false; } - if (usage & GPUTextureUsage.STORAGE && !kTextureFormatInfo[format].storage) { + if (usage & GPUTextureUsage.STORAGE && !info.storage) { return false; } diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copyBufferToBuffer.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copyBufferToBuffer.spec.js new file mode 100644 index 00000000000..5fd4877383a --- /dev/null +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copyBufferToBuffer.spec.js @@ -0,0 +1,271 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ export const description = ` +copyBufferToBuffer tests. + +Test Plan: +* Buffer is valid/invalid + - the source buffer is invalid + - the destination buffer is invalid +* Buffer usages + - the source buffer is created without GPUBufferUsage::COPY_SRC + - the destination buffer is created without GPUBufferUsage::COPY_DEST +* CopySize + - copySize is not a multiple of 4 + - copySize is 0 +* copy offsets + - sourceOffset is not a multiple of 4 + - destinationOffset is not a multiple of 4 +* Arthimetic overflow + - (sourceOffset + copySize) is overflow + - (destinationOffset + copySize) is overflow +* Out of bounds + - (sourceOffset + copySize) > size of source buffer + - (destinationOffset + copySize) > size of destination buffer +* Source buffer and destination buffer are the same buffer +`; +import { poptions, params } from '../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { kBufferUsages } from '../../capability_info.js'; +import { kMaxSafeMultipleOf8 } from '../../util/math.js'; + +import { ValidationTest } from './validation_test.js'; + +class F extends ValidationTest { + TestCopyBufferToBuffer(options) { + const { srcBuffer, srcOffset, dstBuffer, dstOffset, copySize, isSuccess } = options; + + const commandEncoder = this.device.createCommandEncoder(); + commandEncoder.copyBufferToBuffer(srcBuffer, srcOffset, dstBuffer, dstOffset, copySize); + + this.expectValidationError(() => { + commandEncoder.finish(); + }, !isSuccess); + } +} + +export const g = makeTestGroup(F); + +g.test('copy_with_invalid_buffer').fn(async t => { + const validBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, + }); + + const errorBuffer = t.getErrorBuffer(); + + t.TestCopyBufferToBuffer({ + srcBuffer: errorBuffer, + srcOffset: 0, + dstBuffer: validBuffer, + dstOffset: 0, + copySize: 8, + isSuccess: false, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer: validBuffer, + srcOffset: 0, + dstBuffer: errorBuffer, + dstOffset: 0, + copySize: 8, + isSuccess: false, + }); +}); + +g.test('buffer_usage') + .params( + params() + .combine(poptions('srcUsage', kBufferUsages)) + .combine(poptions('dstUsage', kBufferUsages)) + ) + .fn(async t => { + const { srcUsage, dstUsage } = t.params; + + const srcBuffer = t.device.createBuffer({ + size: 16, + usage: srcUsage, + }); + + const dstBuffer = t.device.createBuffer({ + size: 16, + usage: dstUsage, + }); + + const isSuccess = srcUsage === GPUBufferUsage.COPY_SRC && dstUsage === GPUBufferUsage.COPY_DST; + + t.TestCopyBufferToBuffer({ + srcBuffer, + srcOffset: 0, + dstBuffer, + dstOffset: 0, + copySize: 8, + isSuccess, + }); + }); + +g.test('copy_size_alignment') + .params([ + { copySize: 0, _isSuccess: true }, + { copySize: 2, _isSuccess: false }, + { copySize: 4, _isSuccess: true }, + { copySize: 5, _isSuccess: false }, + { copySize: 8, _isSuccess: true }, + ]) + .fn(async t => { + const { copySize, _isSuccess: isSuccess } = t.params; + + const srcBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_SRC, + }); + + const dstBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_DST, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer, + srcOffset: 0, + dstBuffer, + dstOffset: 0, + copySize, + isSuccess, + }); + }); + +g.test('copy_offset_alignment') + .params([ + { srcOffset: 0, dstOffset: 0, _isSuccess: true }, + { srcOffset: 2, dstOffset: 0, _isSuccess: false }, + { srcOffset: 4, dstOffset: 0, _isSuccess: true }, + { srcOffset: 5, dstOffset: 0, _isSuccess: false }, + { srcOffset: 8, dstOffset: 0, _isSuccess: true }, + { srcOffset: 0, dstOffset: 2, _isSuccess: false }, + { srcOffset: 0, dstOffset: 4, _isSuccess: true }, + { srcOffset: 0, dstOffset: 5, _isSuccess: false }, + { srcOffset: 0, dstOffset: 8, _isSuccess: true }, + { srcOffset: 4, dstOffset: 4, _isSuccess: true }, + ]) + .fn(async t => { + const { srcOffset, dstOffset, _isSuccess: isSuccess } = t.params; + + const srcBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_SRC, + }); + + const dstBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_DST, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer, + srcOffset, + dstBuffer, + dstOffset, + copySize: 8, + isSuccess, + }); + }); + +g.test('copy_overflow') + .params([ + { srcOffset: 0, dstOffset: 0, copySize: kMaxSafeMultipleOf8 }, + { srcOffset: 16, dstOffset: 0, copySize: kMaxSafeMultipleOf8 }, + { srcOffset: 0, dstOffset: 16, copySize: kMaxSafeMultipleOf8 }, + { srcOffset: kMaxSafeMultipleOf8, dstOffset: 0, copySize: 16 }, + { srcOffset: 0, dstOffset: kMaxSafeMultipleOf8, copySize: 16 }, + { srcOffset: kMaxSafeMultipleOf8, dstOffset: 0, copySize: kMaxSafeMultipleOf8 }, + { srcOffset: 0, dstOffset: kMaxSafeMultipleOf8, copySize: kMaxSafeMultipleOf8 }, + { + srcOffset: kMaxSafeMultipleOf8, + dstOffset: kMaxSafeMultipleOf8, + copySize: kMaxSafeMultipleOf8, + }, + ]) + .fn(async t => { + const { srcOffset, dstOffset, copySize } = t.params; + + const srcBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_SRC, + }); + + const dstBuffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_DST, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer, + srcOffset, + dstBuffer, + dstOffset, + copySize, + isSuccess: false, + }); + }); + +g.test('copy_out_of_bounds') + .params([ + { srcOffset: 0, dstOffset: 0, copySize: 32, _isSuccess: true }, + { srcOffset: 0, dstOffset: 0, copySize: 36 }, + { srcOffset: 36, dstOffset: 0, copySize: 4 }, + { srcOffset: 0, dstOffset: 36, copySize: 4 }, + { srcOffset: 36, dstOffset: 0, copySize: 0 }, + { srcOffset: 0, dstOffset: 36, copySize: 0 }, + { srcOffset: 20, dstOffset: 0, copySize: 16 }, + { srcOffset: 20, dstOffset: 0, copySize: 12, _isSuccess: true }, + { srcOffset: 0, dstOffset: 20, copySize: 16 }, + { srcOffset: 0, dstOffset: 20, copySize: 12, _isSuccess: true }, + ]) + .fn(async t => { + const { srcOffset, dstOffset, copySize, _isSuccess = false } = t.params; + + const srcBuffer = t.device.createBuffer({ + size: 32, + usage: GPUBufferUsage.COPY_SRC, + }); + + const dstBuffer = t.device.createBuffer({ + size: 32, + usage: GPUBufferUsage.COPY_DST, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer, + srcOffset, + dstBuffer, + dstOffset, + copySize, + isSuccess: _isSuccess, + }); + }); + +g.test('copy_within_same_buffer') + .params([ + { srcOffset: 0, dstOffset: 8, copySize: 4 }, + { srcOffset: 8, dstOffset: 0, copySize: 4 }, + { srcOffset: 0, dstOffset: 4, copySize: 8 }, + { srcOffset: 4, dstOffset: 0, copySize: 8 }, + ]) + .fn(async t => { + const { srcOffset, dstOffset, copySize } = t.params; + + const buffer = t.device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST, + }); + + t.TestCopyBufferToBuffer({ + srcBuffer: buffer, + srcOffset, + dstBuffer: buffer, + dstOffset, + copySize, + isSuccess: false, + }); + }); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture.js new file mode 100644 index 00000000000..0db6e68d4af --- /dev/null +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture.js @@ -0,0 +1,179 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ import { poptions } from '../../../../common/framework/params_builder.js'; +import { assert } from '../../../../common/framework/util/util.js'; +import { kSizedTextureFormatInfo } from '../../../capability_info.js'; +import { ValidationTest } from '../validation_test.js'; + +export const kAllTestMethods = ['WriteTexture', 'CopyBufferToTexture', 'CopyTextureToBuffer']; + +export class CopyBetweenLinearDataAndTextureTest extends ValidationTest { + bytesInACompleteRow(copyWidth, format) { + const info = kSizedTextureFormatInfo[format]; + assert(copyWidth % info.blockWidth === 0); + return (info.bytesPerBlock * copyWidth) / info.blockWidth; + } + + requiredBytesInCopy(layout, format, copyExtent) { + const info = kSizedTextureFormatInfo[format]; + assert(layout.rowsPerImage % info.blockHeight === 0); + assert(copyExtent.height % info.blockHeight === 0); + assert(copyExtent.width % info.blockWidth === 0); + if (copyExtent.width === 0 || copyExtent.height === 0 || copyExtent.depth === 0) { + return 0; + } else { + const texelBlockRowsPerImage = layout.rowsPerImage / info.blockHeight; + const bytesPerImage = layout.bytesPerRow * texelBlockRowsPerImage; + const bytesInLastSlice = + layout.bytesPerRow * (copyExtent.height / info.blockHeight - 1) + + (copyExtent.width / info.blockWidth) * info.bytesPerBlock; + return bytesPerImage * (copyExtent.depth - 1) + bytesInLastSlice; + } + } + + testRun( + textureCopyView, + textureDataLayout, + size, + { + dataSize, + method, + success, + submit = false, // If submit is true, the validaton error is expected to come from the submit and encoding should succeed. + } + ) { + switch (method) { + case 'WriteTexture': { + const data = new Uint8Array(dataSize); + + this.expectValidationError(() => { + this.device.defaultQueue.writeTexture(textureCopyView, data, textureDataLayout, size); + }, !success); + + break; + } + case 'CopyBufferToTexture': { + const buffer = this.device.createBuffer({ + size: dataSize, + usage: GPUBufferUsage.COPY_SRC, + }); + + const encoder = this.device.createCommandEncoder(); + encoder.copyBufferToTexture({ buffer, ...textureDataLayout }, textureCopyView, size); + + if (submit) { + const cmd = encoder.finish(); + this.expectValidationError(() => { + this.device.defaultQueue.submit([cmd]); + }, !success); + } else { + this.expectValidationError(() => { + encoder.finish(); + }, !success); + } + + break; + } + case 'CopyTextureToBuffer': { + const buffer = this.device.createBuffer({ + size: dataSize, + usage: GPUBufferUsage.COPY_DST, + }); + + const encoder = this.device.createCommandEncoder(); + encoder.copyTextureToBuffer(textureCopyView, { buffer, ...textureDataLayout }, size); + + if (submit) { + const cmd = encoder.finish(); + this.expectValidationError(() => { + this.device.defaultQueue.submit([cmd]); + }, !success); + } else { + this.expectValidationError(() => { + encoder.finish(); + }, !success); + } + + break; + } + } + } + + // This is a helper function used for creating a texture when we don't have to be very + // precise about its size as long as it's big enough and properly aligned. + createAlignedTexture( + format, + copySize = { width: 1, height: 1, depth: 1 }, + origin = { x: 0, y: 0, z: 0 } + ) { + const info = kSizedTextureFormatInfo[format]; + return this.device.createTexture({ + size: { + width: Math.max(1, copySize.width + origin.x) * info.blockWidth, + height: Math.max(1, copySize.height + origin.y) * info.blockHeight, + depth: Math.max(1, copySize.depth + origin.z), + }, + + format, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + } +} + +// For testing divisibility by a number we test all the values returned by this function: +function valuesToTestDivisibilityBy(number) { + const values = []; + for (let i = 0; i <= 2 * number; ++i) { + values.push(i); + } + values.push(3 * number); + return values; +} + +// This is a helper function used for expanding test parameters for texel block alignment tests on offset +export function texelBlockAlignmentTestExpanderForOffset({ format }) { + return poptions( + 'offset', + valuesToTestDivisibilityBy(kSizedTextureFormatInfo[format].bytesPerBlock) + ); +} + +// This is a helper function used for expanding test parameters for texel block alignment tests on rowsPerImage +export function texelBlockAlignmentTestExpanderForRowsPerImage({ format }) { + return poptions( + 'rowsPerImage', + valuesToTestDivisibilityBy(kSizedTextureFormatInfo[format].blockHeight) + ); +} + +// This is a helper function used for expanding test parameters for texel block alignment tests on origin and size +export function texelBlockAlignmentTestExpanderForValueToCoordinate({ format, coordinateToTest }) { + switch (coordinateToTest) { + case 'x': + case 'width': + return poptions( + 'valueToCoordinate', + valuesToTestDivisibilityBy(kSizedTextureFormatInfo[format].blockWidth) + ); + + case 'y': + case 'height': + return poptions( + 'valueToCoordinate', + valuesToTestDivisibilityBy(kSizedTextureFormatInfo[format].blockHeight) + ); + + case 'z': + case 'depth': + return poptions('valueToCoordinate', valuesToTestDivisibilityBy(1)); + } +} + +// This is a helper function used for filtering test parameters +export function formatCopyableWithMethod({ format, method }) { + if (method === 'CopyTextureToBuffer') { + return kSizedTextureFormatInfo[format].copySrc; + } else { + return kSizedTextureFormatInfo[format].copyDst; + } +} diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_dataRelated.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_dataRelated.spec.js new file mode 100644 index 00000000000..be1395b6642 --- /dev/null +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_dataRelated.spec.js @@ -0,0 +1,299 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ export const description = ''; +import { params, poptions } from '../../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { + kUncompressedTextureFormatInfo, + kSizedTextureFormats, + kSizedTextureFormatInfo, +} from '../../../capability_info.js'; +import { align } from '../../../util/math.js'; + +import { + CopyBetweenLinearDataAndTextureTest, + kAllTestMethods, + texelBlockAlignmentTestExpanderForOffset, + texelBlockAlignmentTestExpanderForRowsPerImage, + formatCopyableWithMethod, +} from './copyBetweenLinearDataAndTexture.js'; + +export const g = makeTestGroup(CopyBetweenLinearDataAndTextureTest); + +g.test('bound_on_rows_per_image') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('rowsPerImageInBlocks', [0, 1, 2])) + .combine(poptions('copyHeightInBlocks', [0, 1, 2])) + .combine(poptions('copyDepth', [1, 3])) + ) + .fn(async t => { + const { rowsPerImageInBlocks, copyHeightInBlocks, copyDepth, method } = t.params; + + const format = 'rgba8unorm'; + const rowsPerImage = rowsPerImageInBlocks * kUncompressedTextureFormatInfo[format].blockHeight; + const copyHeight = copyHeightInBlocks * kUncompressedTextureFormatInfo[format].blockHeight; + + const texture = t.device.createTexture({ + size: { width: 4, height: 4, depth: 3 }, + format, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + // The WebGPU spec: + // If layout.rowsPerImage is not 0, it must be greater than or equal to copyExtent.height. + // If copyExtent.depth is greater than 1: layout.rowsPerImage must be greater than or equal to copyExtent.height. + // TODO: Update this if https://github.com/gpuweb/gpuweb/issues/984 changes the spec. + + let success = true; + if (rowsPerImage !== 0 && rowsPerImage < copyHeight) { + success = false; + } + if (copyDepth > 1 && rowsPerImage < copyHeight) { + success = false; + } + + t.testRun( + { texture }, + { bytesPerRow: 1024, rowsPerImage }, + { width: 0, height: copyHeight, depth: copyDepth }, + { dataSize: 1, method, success } + ); + }); + +// Test with offset + requiredBytesIsCopy overflowing GPUSize64. +g.test('offset_plus_required_bytes_in_copy_overflow') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine([ + { bytesPerRow: 2 ** 31, rowsPerImage: 2 ** 31, depth: 1, _success: true }, // success case + { bytesPerRow: 2 ** 31, rowsPerImage: 2 ** 31, depth: 16, _success: false }, // bytesPerRow * rowsPerImage * (depth - 1) overflows. + ]) + ) + .fn(async t => { + const { method, bytesPerRow, rowsPerImage, depth, _success } = t.params; + + const texture = t.device.createTexture({ + size: [1, 1, depth], + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + t.testRun( + { texture }, + { bytesPerRow, rowsPerImage }, + { width: 1, height: 1, depth }, + { + dataSize: 10000, + method, + success: _success, + } + ); + }); + +// Testing that the minimal data size condition is checked correctly. +// In the success case, we test the exact value. +// In the failing case, we test the exact value minus 1. +g.test('required_bytes_in_copy') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine([ + { bytesPerRowPadding: 0, rowsPerImagePaddingInBlocks: 0 }, // no padding + { bytesPerRowPadding: 0, rowsPerImagePaddingInBlocks: 6 }, // rowsPerImage padding + { bytesPerRowPadding: 6, rowsPerImagePaddingInBlocks: 0 }, // bytesPerRow padding + { bytesPerRowPadding: 15, rowsPerImagePaddingInBlocks: 17 }, // both paddings + ]) + .combine([ + { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 5, offsetInBlocks: 0 }, // standard copy + { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 3, offsetInBlocks: 11 }, // standard copy, offset > 0 + { copyWidthInBlocks: 256, copyHeightInBlocks: 3, copyDepth: 2, offsetInBlocks: 0 }, // copyWidth is 256-aligned + { copyWidthInBlocks: 0, copyHeightInBlocks: 4, copyDepth: 5, offsetInBlocks: 0 }, // empty copy because of width + { copyWidthInBlocks: 3, copyHeightInBlocks: 0, copyDepth: 5, offsetInBlocks: 0 }, // empty copy because of height + { copyWidthInBlocks: 3, copyHeightInBlocks: 4, copyDepth: 0, offsetInBlocks: 13 }, // empty copy because of depth, offset > 0 + { copyWidthInBlocks: 1, copyHeightInBlocks: 4, copyDepth: 5, offsetInBlocks: 0 }, // copyWidth = 1 + { copyWidthInBlocks: 3, copyHeightInBlocks: 1, copyDepth: 5, offsetInBlocks: 15 }, // copyHeight = 1, offset > 0 + { copyWidthInBlocks: 5, copyHeightInBlocks: 4, copyDepth: 1, offsetInBlocks: 0 }, // copyDepth = 1 + { copyWidthInBlocks: 7, copyHeightInBlocks: 1, copyDepth: 1, offsetInBlocks: 0 }, // copyHeight = 1 and copyDepth = 1 + ]) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + ) + .fn(async t => { + const { + offsetInBlocks, + bytesPerRowPadding, + rowsPerImagePaddingInBlocks, + copyWidthInBlocks, + copyHeightInBlocks, + copyDepth, + format, + method, + } = t.params; + + // In the CopyB2T and CopyT2B cases we need to have bytesPerRow 256-aligned, + // to make this happen we align the bytesInACompleteRow value and multiply + // bytesPerRowPadding by 256. + const bytesPerRowAlignment = method === 'WriteTexture' ? 1 : 256; + + const info = kSizedTextureFormatInfo[format]; + const copyWidth = copyWidthInBlocks * info.blockWidth; + const copyHeight = copyHeightInBlocks * info.blockHeight; + const offset = offsetInBlocks * info.bytesPerBlock; + const rowsPerImage = copyHeight + rowsPerImagePaddingInBlocks * info.blockHeight; + const bytesPerRow = + align(t.bytesInACompleteRow(copyWidth, format), bytesPerRowAlignment) + + bytesPerRowPadding * bytesPerRowAlignment; + const size = { width: copyWidth, height: copyHeight, depth: copyDepth }; + + const minDataSize = + offset + t.requiredBytesInCopy({ offset, bytesPerRow, rowsPerImage }, format, size); + + const texture = t.createAlignedTexture(format, size); + + t.testRun({ texture }, { offset, bytesPerRow, rowsPerImage }, size, { + dataSize: minDataSize, + method, + success: true, + }); + + if (minDataSize > 0) { + t.testRun({ texture }, { offset, bytesPerRow, rowsPerImage }, size, { + dataSize: minDataSize - 1, + method, + success: false, + }); + } + }); + +g.test('texel_block_alignment_on_rows_per_image') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + .expand(texelBlockAlignmentTestExpanderForRowsPerImage) + ) + .fn(async t => { + const { rowsPerImage, format, method } = t.params; + const size = { width: 0, height: 0, depth: 0 }; + + const texture = t.createAlignedTexture(format, size); + + const success = rowsPerImage % kSizedTextureFormatInfo[format].blockHeight === 0; + + t.testRun({ texture }, { bytesPerRow: 0, rowsPerImage }, size, { + dataSize: 1, + method, + success, + }); + }); + +// TODO: Update this if https://github.com/gpuweb/gpuweb/issues/985 changes the spec. +g.test('texel_block_alignment_on_offset') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + .expand(texelBlockAlignmentTestExpanderForOffset) + ) + .fn(async t => { + const { format, offset, method } = t.params; + const size = { width: 0, height: 0, depth: 0 }; + + const texture = t.createAlignedTexture(format, size); + + const success = offset % kSizedTextureFormatInfo[format].bytesPerBlock === 0; + + t.testRun({ texture }, { offset, bytesPerRow: 0 }, size, { dataSize: offset, method, success }); + }); + +g.test('bound_on_bytes_per_row') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine([ + { blocksPerRow: 2, additionalPaddingPerRow: 0, copyWidthInBlocks: 2 }, // success + { blocksPerRow: 2, additionalPaddingPerRow: 5, copyWidthInBlocks: 3 }, // success if bytesPerBlock <= 5 + { blocksPerRow: 1, additionalPaddingPerRow: 0, copyWidthInBlocks: 2 }, // failure, bytesPerRow > 0 + { blocksPerRow: 0, additionalPaddingPerRow: 0, copyWidthInBlocks: 1 }, // failure, bytesPerRow = 0 + ]) + .combine([ + { copyHeightInBlocks: 0, copyDepth: 1 }, // we don't have to check the bound + { copyHeightInBlocks: 1, copyDepth: 0 }, // we don't have to check the bound + { copyHeightInBlocks: 2, copyDepth: 1 }, // we have to check the bound + { copyHeightInBlocks: 0, copyDepth: 2 }, // we have to check the bound + ]) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + ) + .fn(async t => { + const { + blocksPerRow, + additionalPaddingPerRow, + copyWidthInBlocks, + copyHeightInBlocks, + copyDepth, + format, + method, + } = t.params; + + // In the CopyB2T and CopyT2B cases we need to have bytesPerRow 256-aligned, + // to make this happen we multiply copyWidth and bytesPerRow by 256, so that + // the appropriate inequalities still hold. + const bytesPerRowAlignment = method === 'WriteTexture' ? 1 : 256; + + const info = kSizedTextureFormatInfo[format]; + const copyWidth = copyWidthInBlocks * info.blockWidth * bytesPerRowAlignment; + const copyHeight = copyHeightInBlocks * info.blockHeight; + const bytesPerRow = + (blocksPerRow * info.bytesPerBlock + additionalPaddingPerRow) * bytesPerRowAlignment; + const size = { width: copyWidth, height: copyHeight, depth: copyDepth }; + + const texture = t.createAlignedTexture(format, size); + + let success = true; + if (copyHeight > 1 || copyDepth > 1) { + success = bytesPerRow >= t.bytesInACompleteRow(copyWidth, format); + } + + t.testRun({ texture }, { bytesPerRow, rowsPerImage: copyHeight }, size, { + dataSize: 1024, + method, + success, + }); + }); + +g.test('bound_on_offset') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('offsetInBlocks', [0, 1, 2])) + .combine(poptions('dataSizeInBlocks', [0, 1, 2])) + ) + .fn(async t => { + const { offsetInBlocks, dataSizeInBlocks, method } = t.params; + + const format = 'rgba8unorm'; + const info = kSizedTextureFormatInfo[format]; + const offset = offsetInBlocks * info.bytesPerBlock; + const dataSize = dataSizeInBlocks * info.bytesPerBlock; + + const texture = t.device.createTexture({ + size: { width: 4, height: 4, depth: 1 }, + format, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + const success = offset <= dataSize; + + t.testRun( + { texture }, + { offset, bytesPerRow: 0 }, + { width: 0, height: 0, depth: 0 }, + { dataSize, method, success } + ); + }); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_textureRelated.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_textureRelated.spec.js new file mode 100644 index 00000000000..bef71943fae --- /dev/null +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/copy_between_linear_data_and_texture/copyBetweenLinearDataAndTexture_textureRelated.spec.js @@ -0,0 +1,307 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ export const description = ''; +import { params, poptions } from '../../../../common/framework/params_builder.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { kSizedTextureFormats, kSizedTextureFormatInfo } from '../../../capability_info.js'; + +import { + CopyBetweenLinearDataAndTextureTest, + kAllTestMethods, + texelBlockAlignmentTestExpanderForValueToCoordinate, + formatCopyableWithMethod, +} from './copyBetweenLinearDataAndTexture.js'; + +export const g = makeTestGroup(CopyBetweenLinearDataAndTextureTest); + +g.test('texture_must_be_valid') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('textureState', ['valid', 'destroyed', 'error'])) + ) + .fn(async t => { + const { method, textureState } = t.params; + + // A valid texture. + let texture = t.device.createTexture({ + size: { width: 4, height: 4, depth: 1 }, + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + switch (textureState) { + case 'destroyed': { + texture.destroy(); + break; + } + case 'error': { + texture = t.getErrorTexture(); + break; + } + } + + const success = textureState === 'valid'; + const submit = textureState === 'destroyed'; + + t.testRun( + { texture }, + { bytesPerRow: 0 }, + { width: 0, height: 0, depth: 0 }, + { dataSize: 1, method, success, submit } + ); + }); + +g.test('texture_usage_must_be_valid') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine( + poptions('usage', [ + GPUTextureUsage.COPY_SRC | GPUTextureUsage.SAMPLED, + GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED, + GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + ]) + ) + ) + .fn(async t => { + const { usage, method } = t.params; + + const texture = t.device.createTexture({ + size: { width: 4, height: 4, depth: 1 }, + format: 'rgba8unorm', + usage, + }); + + const success = + method === 'CopyTextureToBuffer' + ? (usage & GPUTextureUsage.COPY_SRC) !== 0 + : (usage & GPUTextureUsage.COPY_DST) !== 0; + + t.testRun( + { texture }, + { bytesPerRow: 0 }, + { width: 0, height: 0, depth: 0 }, + { dataSize: 1, method, success } + ); + }); + +g.test('sample_count_must_be_1') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('sampleCount', [1, 4])) + ) + .fn(async t => { + const { sampleCount, method } = t.params; + + const texture = t.device.createTexture({ + size: { width: 4, height: 4, depth: 1 }, + sampleCount, + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED, + }); + + const success = sampleCount === 1; + + t.testRun( + { texture }, + { bytesPerRow: 0 }, + { width: 0, height: 0, depth: 0 }, + { dataSize: 1, method, success } + ); + }); + +g.test('mip_level_must_be_in_range') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('mipLevelCount', [3, 5])) + .combine(poptions('mipLevel', [3, 4])) + ) + .fn(async t => { + const { mipLevelCount, mipLevel, method } = t.params; + + const texture = t.device.createTexture({ + size: { width: 32, height: 32, depth: 1 }, + mipLevelCount, + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + const success = mipLevel < mipLevelCount; + + t.testRun( + { texture, mipLevel }, + { bytesPerRow: 0 }, + { width: 0, height: 0, depth: 0 }, + { dataSize: 1, method, success } + ); + }); + +g.test('texel_block_alignments_on_origin') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('coordinateToTest', ['x', 'y', 'z'])) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + .expand(texelBlockAlignmentTestExpanderForValueToCoordinate) + ) + .fn(async t => { + const { valueToCoordinate, coordinateToTest, format, method } = t.params; + const info = kSizedTextureFormatInfo[format]; + + const origin = { x: 0, y: 0, z: 0 }; + const size = { width: 0, height: 0, depth: 0 }; + let success = true; + + origin[coordinateToTest] = valueToCoordinate; + switch (coordinateToTest) { + case 'x': { + success = origin.x % info.blockWidth === 0; + break; + } + case 'y': { + success = origin.y % info.blockHeight === 0; + break; + } + } + + const texture = t.createAlignedTexture(format, size, origin); + + t.testRun({ texture, origin }, { bytesPerRow: 0 }, size, { + dataSize: 1, + method, + success, + }); + }); + +g.test('1d_texture') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('width', [0, 1])) + .combine([ + { height: 1, depth: 1 }, + { height: 1, depth: 0 }, + { height: 1, depth: 2 }, + { height: 0, depth: 1 }, + { height: 2, depth: 1 }, + ]) + ) + .fn(async t => { + const { method, width, height, depth } = t.params; + const size = { width, height, depth }; + + const texture = t.device.createTexture({ + size: { width: 2, height: 1, depth: 1 }, + dimension: '1d', + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + // For 1d textures we require copyHeight and copyDepth to be 1, + // copyHeight or copyDepth being 0 should cause a validation error. + const success = size.height === 1 && size.depth === 1; + + t.testRun({ texture }, { bytesPerRow: 256, rowsPerImage: 4 }, size, { + dataSize: 16, + method, + success, + }); + }); + +g.test('texel_block_alignments_on_size') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('coordinateToTest', ['width', 'height', 'depth'])) + .combine(poptions('format', kSizedTextureFormats)) + .filter(formatCopyableWithMethod) + .expand(texelBlockAlignmentTestExpanderForValueToCoordinate) + ) + .fn(async t => { + const { valueToCoordinate, coordinateToTest, format, method } = t.params; + const info = kSizedTextureFormatInfo[format]; + + const origin = { x: 0, y: 0, z: 0 }; + const size = { width: 0, height: 0, depth: 0 }; + let success = true; + + size[coordinateToTest] = valueToCoordinate; + switch (coordinateToTest) { + case 'width': { + success = size.width % info.blockWidth === 0; + break; + } + case 'height': { + success = size.height % info.blockHeight === 0; + break; + } + } + + const texture = t.createAlignedTexture(format, size, origin); + + t.testRun({ texture, origin }, { bytesPerRow: 0 }, size, { + dataSize: 1, + method, + success, + }); + }); + +g.test('texture_range_conditions') + .params( + params() + .combine(poptions('method', kAllTestMethods)) + .combine(poptions('originValue', [7, 8])) + .combine(poptions('copySizeValue', [7, 8])) + .combine(poptions('textureSizeValue', [14, 15])) + .combine(poptions('mipLevel', [0, 2])) + .combine(poptions('coordinateToTest', [0, 1, 2])) + ) + .fn(async t => { + const { + originValue, + copySizeValue, + textureSizeValue, + mipLevel, + coordinateToTest, + method, + } = t.params; + + const origin = [0, 0, 0]; + const copySize = [0, 0, 0]; + const textureSize = { width: 16 << mipLevel, height: 16 << mipLevel, depth: 16 }; + const success = originValue + copySizeValue <= textureSizeValue; + + origin[coordinateToTest] = originValue; + copySize[coordinateToTest] = copySizeValue; + switch (coordinateToTest) { + case 0: { + textureSize.width = textureSizeValue << mipLevel; + break; + } + case 1: { + textureSize.height = textureSizeValue << mipLevel; + break; + } + case 2: { + textureSize.depth = textureSizeValue; + break; + } + } + + const texture = t.device.createTexture({ + size: textureSize, + mipLevelCount: 3, + format: 'rgba8unorm', + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST, + }); + + t.testRun({ texture, origin, mipLevel }, { bytesPerRow: 0 }, copySize, { + dataSize: 1, + method, + success, + }); + }); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js index 9c0df538b27..43fd923687b 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createBindGroupLayout.spec.js @@ -14,10 +14,10 @@ import { kShaderStageCombinations, kTextureBindingTypeInfo, kTextureComponentTypes, - kTextureFormats, - kTextureFormatInfo, kTextureViewDimensions, kTextureViewDimensionInfo, + kAllTextureFormats, + kAllTextureFormatInfo, } from '../../capability_info.js'; import { ValidationTest } from './validation_test.js'; @@ -83,7 +83,7 @@ g.test('bindingTypeSpecific_optional_members') ...poptions('textureComponentType', kTextureComponentTypes), ...pbool('multisampled'), ...poptions('viewDimension', kTextureViewDimensions), - ...poptions('storageTextureFormat', kTextureFormats), + ...poptions('storageTextureFormat', kAllTextureFormats), ]) ) .fn(t => { @@ -115,7 +115,10 @@ g.test('bindingTypeSpecific_optional_members') if (viewDimension !== undefined && !kTextureViewDimensionInfo[viewDimension].storage) { success = false; } - if (storageTextureFormat !== undefined && !kTextureFormatInfo[storageTextureFormat].storage) { + if ( + storageTextureFormat !== undefined && + !kAllTextureFormatInfo[storageTextureFormat].storage + ) { success = false; } } diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createTexture.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createTexture.spec.js index a9c7a8be01e..ceff54e136f 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createTexture.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/createTexture.spec.js @@ -5,7 +5,7 @@ createTexture validation tests. `; import { poptions } from '../../../common/framework/params_builder.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; -import { kTextureFormatInfo, kTextureFormats } from '../../capability_info.js'; +import { kAllTextureFormats, kAllTextureFormatInfo } from '../../capability_info.js'; import { ValidationTest } from './validation_test.js'; @@ -130,10 +130,10 @@ g.test('it_is_invalid_to_submit_a_destroyed_texture_before_and_after_encode') }); g.test('it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format') - .params(poptions('format', kTextureFormats)) + .params(poptions('format', kAllTextureFormats)) .fn(async t => { const format = t.params.format; - const info = kTextureFormatInfo[format]; + const info = kAllTextureFormatInfo[format]; const descriptor = t.getDescriptor({ width: 1, height: 1, format }); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/error_scope.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/error_scope.spec.js index 5523237daeb..64575540e8b 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/error_scope.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/error_scope.spec.js @@ -36,7 +36,10 @@ class F extends Fixture { super.init(); const gpu = getGPU(); const adapter = await gpu.requestAdapter(); - this._device = await adapter.requestDevice(); + assert(adapter !== null); + const device = await adapter.requestDevice(); + assert(device !== null); + this._device = device; } createErrorBuffer() { diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/fences.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/fences.spec.js index cc04848410f..b50ebae572d 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/fences.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/fences.spec.js @@ -4,6 +4,7 @@ fences validation tests. `; import { makeTestGroup } from '../../../common/framework/test_group.js'; +import { assert } from '../../../common/framework/util/util.js'; import { ValidationTest } from './validation_test.js'; @@ -60,6 +61,7 @@ g.test('signal_a_fence_on_a_different_device_than_it_was_created_on_is_invalid') const fence = t.queue.createFence(); const anotherDevice = await t.device.adapter.requestDevice(); + assert(anotherDevice !== null); const anotherQueue = anotherDevice.defaultQueue; t.expectValidationError(() => { @@ -71,6 +73,7 @@ g.test('signal_a_fence_on_a_different_device_does_not_update_fence_signaled_valu const fence = t.queue.createFence({ initialValue: 1 }); const anotherDevice = await t.device.adapter.requestDevice(); + assert(anotherDevice !== null); const anotherQueue = anotherDevice.defaultQueue; t.expectValidationError(() => { diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/resource_usages/textureUsageInRender.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/resource_usages/textureUsageInRender.spec.js index 6322ec25ee5..12efa65ce2d 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/resource_usages/textureUsageInRender.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/resource_usages/textureUsageInRender.spec.js @@ -4,15 +4,31 @@ Texture Usages Validation Tests in Render Pass. Test Coverage: - - Tests that read and write usages upon the same texture subresource, or different subresources - of the same texture. Different subresources of the same texture includes different mip levels, - different array layers, and different aspects. - - When read and write usages are binding to the same texture subresource, an error should be - generated. Otherwise, no error should be generated. + + - For each combination of two texture usages: + - For various subresource ranges (different mip levels or array layers) that overlap a given + subresources or not for color formats: + - Check that an error is generated when read-write or write-write usages are binding to the + same texture subresource. Otherwise, no error should be generated. One exception is race + condition upon two writeonly-storage-texture usages, which is valid. + + - For each combination of two texture usages: + - For various aspects (all, depth-only, stencil-only) that overlap a given subresources or not + for depth/stencil formats: + - Check that an error is generated when read-write or write-write usages are binding to the + same aspect. Otherwise, no error should be generated. + + - Test combinations of two shader stages: + - Texture usages in bindings with invisible shader stages should be tracked. Invisible shader + stages include shader stage with visibility none and compute shader stage in render pass. `; import { poptions, params } from '../../../../common/framework/params_builder.js'; import { makeTestGroup } from '../../../../common/framework/test_group.js'; -import { kTextureFormatInfo, kShaderStages } from '../../../capability_info.js'; +import { + kShaderStages, + kDepthStencilFormats, + kDepthStencilFormatInfo, +} from '../../../capability_info.js'; import { ValidationTest } from '../validation_test.js'; class TextureUsageTracking extends ValidationTest { @@ -40,65 +56,183 @@ class TextureUsageTracking extends ValidationTest { export const g = makeTestGroup(TextureUsageTracking); -const READ_BASE_LEVEL = 3; -const READ_BASE_LAYER = 0; +const BASE_LEVEL = 3; +const BASE_LAYER = 0; +const TOTAL_LEVELS = 6; +const TOTAL_LAYERS = 2; -g.test('readwrite_upon_subresources') - .params([ - // read and write usages are binding to the same texture subresource. - { - writeBaseLevel: READ_BASE_LEVEL, - writeBaseLayer: READ_BASE_LAYER, - _success: false, - }, +g.test('subresources_and_binding_types_combination_for_color') + .params( + params() + .combine([ + // Two texture usages are binding to the same texture subresource. + { + baseLevel: BASE_LEVEL, + baseLayer: BASE_LAYER, + levelCount: 1, + layerCount: 1, + _resourceSuccess: false, + }, - // read and write usages are binding to different mip levels of the same texture. - { - writeBaseLevel: READ_BASE_LEVEL + 1, - writeBaseLayer: READ_BASE_LAYER, - _success: true, - }, + // Two texture usages are binding to different mip levels of the same texture. + { + baseLevel: BASE_LEVEL + 1, + baseLayer: BASE_LAYER, + levelCount: 1, + layerCount: 1, + _resourceSuccess: true, + }, - // read and write usages are binding to different array layers of the same texture. - { - writeBaseLevel: READ_BASE_LEVEL, - writeBaseLayer: READ_BASE_LAYER + 1, - _success: true, - }, - ]) + // Two texture usages are binding to different array layers of the same texture. + { + baseLevel: BASE_LEVEL, + baseLayer: BASE_LAYER + 1, + levelCount: 1, + layerCount: 1, + _resourceSuccess: true, + }, + + // The second texture usage contains the whole mip chain where the first texture usage is using. + { + baseLevel: 0, + baseLayer: BASE_LAYER, + levelCount: TOTAL_LEVELS, + layerCount: 1, + _resourceSuccess: false, + }, + + // The second texture usage contains the all layers where the first texture usage is using. + { + baseLevel: BASE_LEVEL, + baseLayer: 0, + levelCount: 1, + layerCount: TOTAL_LAYERS, + _resourceSuccess: false, + }, + ]) + .combine([ + { + type0: 'sampled-texture', + type1: 'sampled-texture', + _usageSuccess: true, + }, + + { + type0: 'sampled-texture', + type1: 'readonly-storage-texture', + _usageSuccess: true, + }, + + { + type0: 'sampled-texture', + type1: 'writeonly-storage-texture', + _usageSuccess: false, + }, + + { + type0: 'sampled-texture', + type1: 'render-target', + _usageSuccess: false, + }, + + { + type0: 'readonly-storage-texture', + type1: 'readonly-storage-texture', + _usageSuccess: true, + }, + + { + type0: 'readonly-storage-texture', + type1: 'writeonly-storage-texture', + _usageSuccess: false, + }, + + { + type0: 'readonly-storage-texture', + type1: 'render-target', + _usageSuccess: false, + }, + + // Race condition upon multiple writable storage texture is valid. + { + type0: 'writeonly-storage-texture', + type1: 'writeonly-storage-texture', + _usageSuccess: true, + }, + + { + type0: 'writeonly-storage-texture', + type1: 'render-target', + _usageSuccess: false, + }, + ]) + ) .fn(async t => { - const { writeBaseLevel, writeBaseLayer, _success } = t.params; + const { + baseLevel, + baseLayer, + levelCount, + layerCount, + type0, + type1, + _usageSuccess, + _resourceSuccess, + } = t.params; - const texture = t.createTexture({ arrayLayerCount: 2, mipLevelCount: 6 }); + const texture = t.createTexture({ + arrayLayerCount: TOTAL_LAYERS, + mipLevelCount: TOTAL_LEVELS, + usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.STORAGE | GPUTextureUsage.OUTPUT_ATTACHMENT, + }); - const sampleView = texture.createView({ - baseMipLevel: READ_BASE_LEVEL, + const view0 = texture.createView({ + baseMipLevel: BASE_LEVEL, mipLevelCount: 1, - baseArrayLayer: READ_BASE_LAYER, + baseArrayLayer: BASE_LAYER, arrayLayerCount: 1, }); - const renderView = texture.createView({ - baseMipLevel: writeBaseLevel, - mipLevelCount: 1, - baseArrayLayer: writeBaseLayer, - arrayLayerCount: 1, + const view1Dimension = layerCount !== 1 ? '2d-array' : '2d'; + const view1 = texture.createView({ + dimension: view1Dimension, + baseMipLevel: baseLevel, + mipLevelCount: levelCount, + baseArrayLayer: baseLayer, + arrayLayerCount: layerCount, }); - const bindGroupLayout = t.device.createBindGroupLayout({ - entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type: 'sampled-texture' }], - }); + // TODO: Add two 'render-target' usages for color attachments. + const bglEntries = [ + { + binding: 0, + visibility: GPUShaderStage.FRAGMENT, + type: type0, + storageTextureFormat: type0 === 'sampled-texture' ? undefined : 'rgba8unorm', + }, + ]; + const bgEntries = [{ binding: 0, resource: view0 }]; + if (type1 !== 'render-target') { + bglEntries.push({ + binding: 1, + visibility: GPUShaderStage.FRAGMENT, + type: type1, + viewDimension: view1Dimension, + storageTextureFormat: type1 === 'sampled-texture' ? undefined : 'rgba8unorm', + }); + + bgEntries.push({ binding: 1, resource: view1 }); + } const bindGroup = t.device.createBindGroup({ - entries: [{ binding: 0, resource: sampleView }], - layout: bindGroupLayout, + entries: bgEntries, + layout: t.device.createBindGroupLayout({ entries: bglEntries }), }); const encoder = t.device.createCommandEncoder(); const pass = encoder.beginRenderPass({ colorAttachments: [ { - attachment: renderView, + attachment: type1 === 'render-target' ? view1 : t.createTexture().createView(), loadValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 }, storeOp: 'store', }, @@ -108,42 +242,72 @@ g.test('readwrite_upon_subresources') pass.setBindGroup(0, bindGroup); pass.endPass(); + const success = _resourceSuccess || _usageSuccess; t.expectValidationError(() => { encoder.finish(); - }, !_success); + }, !success); }); -g.test('readwrite_upon_aspects') +g.test('subresources_and_binding_types_combination_for_aspect') .params( params() - .combine(poptions('format', ['depth32float', 'depth24plus', 'depth24plus-stencil8'])) - .combine(poptions('readAspect', ['all', 'depth-only', 'stencil-only'])) - .combine(poptions('writeAspect', ['all', 'depth-only', 'stencil-only'])) + .combine(poptions('format', kDepthStencilFormats)) + .combine(poptions('aspect0', ['all', 'depth-only', 'stencil-only'])) + .combine(poptions('aspect1', ['all', 'depth-only', 'stencil-only'])) .unless( - ({ format, readAspect, writeAspect }) => - // TODO: Exclude depth-only aspect once WebGPU supports stencil-only texture format(s). - (readAspect === 'stencil-only' && !kTextureFormatInfo[format].stencil) || - (writeAspect === 'stencil-only' && !kTextureFormatInfo[format].stencil) + ({ format, aspect0, aspect1 }) => + (aspect0 === 'stencil-only' && !kDepthStencilFormatInfo[format].stencil) || + (aspect1 === 'stencil-only' && !kDepthStencilFormatInfo[format].stencil) ) + .unless( + ({ format, aspect0, aspect1 }) => + (aspect0 === 'depth-only' && !kDepthStencilFormatInfo[format].depth) || + (aspect1 === 'depth-only' && !kDepthStencilFormatInfo[format].depth) + ) + .combine([ + { + type0: 'sampled-texture', + type1: 'sampled-texture', + _usageSuccess: true, + }, + + { + type0: 'sampled-texture', + type1: 'render-target', + _usageSuccess: false, + }, + ]) ) .fn(async t => { - const { format, readAspect, writeAspect } = t.params; + const { format, aspect0, aspect1, type0, type1, _usageSuccess } = t.params; - const view = t.createTexture({ format }).createView(); + const texture = t.createTexture({ format }); + const view0 = texture.createView({ aspect: aspect0 }); + const view1 = texture.createView({ aspect: aspect1 }); - const bindGroupLayout = t.device.createBindGroupLayout({ - entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type: 'sampled-texture' }], - }); + const bglEntries = [ + { + binding: 0, + visibility: GPUShaderStage.FRAGMENT, + type: type0, + }, + ]; + const bgEntries = [{ binding: 0, resource: view0 }]; + if (type1 !== 'render-target') { + bglEntries.push({ + binding: 1, + visibility: GPUShaderStage.FRAGMENT, + type: type1, + }); + + bgEntries.push({ binding: 1, resource: view1 }); + } const bindGroup = t.device.createBindGroup({ - entries: [{ binding: 0, resource: view }], - layout: bindGroupLayout, + entries: bgEntries, + layout: t.device.createBindGroupLayout({ entries: bglEntries }), }); - const success = - (readAspect === 'depth-only' && writeAspect === 'stencil-only') || - (readAspect === 'stencil-only' && writeAspect === 'depth-only'); - const encoder = t.device.createCommandEncoder(); const pass = encoder.beginRenderPass({ colorAttachments: [ @@ -154,18 +318,26 @@ g.test('readwrite_upon_aspects') }, ], - depthStencilAttachment: { - attachment: view, - depthStoreOp: 'clear', - depthLoadValue: 'load', - stencilStoreOp: 'clear', - stencilLoadValue: 'load', - }, + depthStencilAttachment: + type1 !== 'render-target' + ? undefined + : { + attachment: view1, + depthStoreOp: 'clear', + depthLoadValue: 'load', + stencilStoreOp: 'clear', + stencilLoadValue: 'load', + }, }); pass.setBindGroup(0, bindGroup); pass.endPass(); + const disjointAspects = + (aspect0 === 'depth-only' && aspect1 === 'stencil-only') || + (aspect0 === 'stencil-only' && aspect1 === 'depth-only'); + const success = disjointAspects || _usageSuccess; + t.expectValidationError(() => { encoder.finish(); }, !success); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/validation_test.js b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/validation_test.js index d816fd0594b..c6cd14779bb 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/validation_test.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/api/validation/validation_test.js @@ -53,15 +53,21 @@ export class ValidationTest extends GPUTest { }); } + getErrorTexture() { + this.device.pushErrorScope('validation'); + const texture = this.device.createTexture({ + size: { width: 0, height: 0, depth: 0 }, + format: 'rgba8unorm', + usage: GPUTextureUsage.SAMPLED, + }); + + this.device.popErrorScope(); + return texture; + } + getErrorTextureView() { this.device.pushErrorScope('validation'); - const view = this.device - .createTexture({ - size: { width: 0, height: 0, depth: 0 }, - format: 'rgba8unorm', - usage: GPUTextureUsage.SAMPLED, - }) - .createView(); + const view = this.getErrorTexture().createView(); this.device.popErrorScope(); return view; } diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/capability_info.js b/tests/wpt/webgpu/tests/webgpu/webgpu/capability_info.js index 2e4264fe229..10a8c5aa4b6 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/capability_info.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/capability_info.js @@ -29,10 +29,7 @@ export const kBufferUsages = numericKeysOf(kBufferUsageInfo); // Textures -export const kTextureFormatInfo = { - // Try to keep these manually-formatted in a readable grid. - // (Note: this list should always match the one in the spec.) - +export const kRegularTextureFormatInfo = { // 8-bit formats r8unorm: { renderable: true, @@ -40,7 +37,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1, @@ -51,7 +49,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1, @@ -62,7 +61,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1, @@ -73,7 +73,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1, @@ -85,7 +86,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -96,7 +98,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -107,7 +110,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -118,7 +122,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -129,7 +134,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -140,7 +146,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -151,7 +158,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1, @@ -163,7 +171,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -174,7 +183,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -185,7 +195,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -196,7 +207,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -207,7 +219,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -218,7 +231,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -229,7 +243,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -240,7 +255,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -251,7 +267,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -262,7 +279,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -273,7 +291,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -284,7 +303,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -295,7 +315,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -307,7 +328,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -318,7 +340,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, @@ -330,7 +353,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -341,7 +365,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -352,7 +377,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -363,7 +389,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -374,7 +401,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -385,7 +413,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1, @@ -397,7 +426,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1, @@ -408,7 +438,8 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1, @@ -419,30 +450,44 @@ export const kTextureFormatInfo = { depth: false, stencil: false, storage: true, - copyable: true, + copySrc: true, + copyDst: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1, }, - // Depth/stencil formats +}; + +export const kRegularTextureFormats = keysOf(kRegularTextureFormatInfo); + +export const kSizedDepthStencilFormatInfo = { depth32float: { renderable: true, color: false, depth: true, stencil: false, storage: false, - copyable: true, + copySrc: true, + copyDst: false, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1, }, +}; + +export const kSizedDepthStencilFormats = keysOf(kSizedDepthStencilFormatInfo); + +export const kUnsizedDepthStencilFormatInfo = { depth24plus: { renderable: true, color: false, depth: true, stencil: false, storage: false, - copyable: false, + copySrc: false, + copyDst: false, + blockWidth: 1, + blockHeight: 1, }, 'depth24plus-stencil8': { renderable: true, @@ -450,11 +495,246 @@ export const kTextureFormatInfo = { depth: true, stencil: true, storage: false, - copyable: false, + copySrc: false, + copyDst: false, + blockWidth: 1, + blockHeight: 1, }, }; -export const kTextureFormats = keysOf(kTextureFormatInfo); +export const kUnsizedDepthStencilFormats = keysOf(kUnsizedDepthStencilFormatInfo); + +export const kCompressedTextureFormatInfo = { + // BC formats + 'bc1-rgba-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 8, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc1-rgba-unorm-srgb': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 8, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc2-rgba-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc2-rgba-unorm-srgb': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc3-rgba-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc3-rgba-unorm-srgb': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc4-r-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 8, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc4-r-snorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 8, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc5-rg-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc5-rg-snorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc6h-rgb-ufloat': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc6h-rgb-sfloat': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc7-rgba-unorm': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, + 'bc7-rgba-unorm-srgb': { + renderable: false, + color: true, + depth: false, + stencil: false, + storage: false, + copySrc: true, + copyDst: true, + bytesPerBlock: 16, + blockWidth: 4, + blockHeight: 4, + extension: 'texture-compression-bc', + }, +}; + +export const kCompressedTextureFormats = keysOf(kCompressedTextureFormatInfo); + +export const kColorTextureFormatInfo = { + ...kRegularTextureFormatInfo, + ...kCompressedTextureFormatInfo, +}; + +export const kColorTextureFormats = keysOf(kColorTextureFormatInfo); + +export const kEncodableTextureFormatInfo = { + ...kRegularTextureFormatInfo, + ...kSizedDepthStencilFormatInfo, +}; + +export const kEncodableTextureFormats = keysOf(kEncodableTextureFormatInfo); + +export const kSizedTextureFormatInfo = { + ...kRegularTextureFormatInfo, + ...kSizedDepthStencilFormatInfo, + ...kCompressedTextureFormatInfo, +}; + +export const kSizedTextureFormats = keysOf(kSizedTextureFormatInfo); + +export const kDepthStencilFormatInfo = { + ...kSizedDepthStencilFormatInfo, + ...kUnsizedDepthStencilFormatInfo, +}; + +export const kDepthStencilFormats = keysOf(kDepthStencilFormatInfo); + +export const kUncompressedTextureFormatInfo = { + ...kRegularTextureFormatInfo, + ...kSizedDepthStencilFormatInfo, + ...kUnsizedDepthStencilFormatInfo, +}; + +export const kUncompressedTextureFormats = keysOf(kUncompressedTextureFormatInfo); + +export const kAllTextureFormatInfo = { + ...kUncompressedTextureFormatInfo, + ...kCompressedTextureFormatInfo, +}; + +export const kAllTextureFormats = keysOf(kAllTextureFormatInfo); export const kTextureDimensionInfo = { '1d': {}, diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/gpu_test.js b/tests/wpt/webgpu/tests/webgpu/webgpu/gpu_test.js index 92f0e41840b..f350131af3b 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/gpu_test.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/gpu_test.js @@ -223,9 +223,6 @@ got [${failedByteActualValues.join(', ')}]`; let failed = false; switch (filter) { - case 'none': - failed = error !== null; - break; case 'out-of-memory': failed = !(error instanceof GPUOutOfMemoryError); break; diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/idl/constants/flags.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/idl/constants/flags.spec.js index 1de75c84e5d..51b80aa8aa2 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/idl/constants/flags.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/idl/constants/flags.spec.js @@ -3,57 +3,83 @@ **/ export const description = ` Test the values of flags interfaces (e.g. GPUTextureUsage). `; +import { poptions } from '../../../common/framework/params_builder.js'; import { makeTestGroup } from '../../../common/framework/test_group.js'; import { IDLTest } from '../idl_test.js'; export const g = makeTestGroup(IDLTest); -g.test('BufferUsage').fn(t => { - const expected = { - MAP_READ: 0x0001, - MAP_WRITE: 0x0002, - COPY_SRC: 0x0004, - COPY_DST: 0x0008, - INDEX: 0x0010, - VERTEX: 0x0020, - UNIFORM: 0x0040, - STORAGE: 0x0080, - INDIRECT: 0x0100, - }; +const kBufferUsageExp = { + MAP_READ: 0x0001, + MAP_WRITE: 0x0002, + COPY_SRC: 0x0004, + COPY_DST: 0x0008, + INDEX: 0x0010, + VERTEX: 0x0020, + UNIFORM: 0x0040, + STORAGE: 0x0080, + INDIRECT: 0x0100, + QUERY_RESOLVE: 0x0200, +}; - t.assertMembers(GPUBufferUsage, expected); +g.test('BufferUsage,count').fn(t => { + t.assertMemberCount(GPUBufferUsage, kBufferUsageExp); }); +g.test('BufferUsage,values') + .params(poptions('key', Object.keys(kBufferUsageExp))) + .fn(t => { + const { key } = t.params; + t.assertMember(GPUBufferUsage, kBufferUsageExp, key); + }); -g.test('TextureUsage').fn(t => { - const expected = { - COPY_SRC: 0x01, - COPY_DST: 0x02, - SAMPLED: 0x04, - STORAGE: 0x08, - OUTPUT_ATTACHMENT: 0x10, - }; +const kTextureUsageExp = { + COPY_SRC: 0x01, + COPY_DST: 0x02, + SAMPLED: 0x04, + STORAGE: 0x08, + OUTPUT_ATTACHMENT: 0x10, +}; - t.assertMembers(GPUTextureUsage, expected); +g.test('TextureUsage,count').fn(t => { + t.assertMemberCount(GPUTextureUsage, kTextureUsageExp); }); +g.test('TextureUsage,values') + .params(poptions('key', Object.keys(kTextureUsageExp))) + .fn(t => { + const { key } = t.params; + t.assertMember(GPUTextureUsage, kTextureUsageExp, key); + }); -g.test('ColorWrite').fn(t => { - const expected = { - RED: 0x1, - GREEN: 0x2, - BLUE: 0x4, - ALPHA: 0x8, - ALL: 0xf, - }; +const kColorWriteExp = { + RED: 0x1, + GREEN: 0x2, + BLUE: 0x4, + ALPHA: 0x8, + ALL: 0xf, +}; - t.assertMembers(GPUColorWrite, expected); +g.test('ColorWrite,count').fn(t => { + t.assertMemberCount(GPUColorWrite, kColorWriteExp); }); +g.test('ColorWrite,values') + .params(poptions('key', Object.keys(kColorWriteExp))) + .fn(t => { + const { key } = t.params; + t.assertMember(GPUColorWrite, kColorWriteExp, key); + }); -g.test('ShaderStage').fn(t => { - const expected = { - VERTEX: 0x1, - FRAGMENT: 0x2, - COMPUTE: 0x4, - }; +const kShaderStageExp = { + VERTEX: 0x1, + FRAGMENT: 0x2, + COMPUTE: 0x4, +}; - t.assertMembers(GPUShaderStage, expected); +g.test('ShaderStage,count').fn(t => { + t.assertMemberCount(GPUShaderStage, kShaderStageExp); }); +g.test('ShaderStage,values') + .params(poptions('key', Object.keys(kShaderStageExp))) + .fn(t => { + const { key } = t.params; + t.assertMember(GPUShaderStage, kShaderStageExp, key); + }); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/idl/idl_test.js b/tests/wpt/webgpu/tests/webgpu/webgpu/idl/idl_test.js index 231fc0945f8..3943563d2ac 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/idl/idl_test.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/idl/idl_test.js @@ -4,18 +4,24 @@ import { assert } from '../../common/framework/util/util.js'; export class IDLTest extends Fixture { + // TODO: add a helper to check prototype chains + /** - * Asserts that an IDL interface has the expected members. + * Asserts that a member of an IDL interface has the expected value. */ - // TODO: exp should allow sentinel markers for unnameable values, such as methods and attributes - // TODO: handle extensions - // TODO: check prototype chains (maybe as separate method) - assertMembers(act, exp) { + assertMember(act, exp, key) { + assert(key in act, () => `Expected key ${key} missing`); + assert(act[key] === exp[key], () => `Value of [${key}] was ${act[key]}, expected ${exp[key]}`); + } + + /** + * Asserts that an IDL interface has the same number of keys as the + * + * TODO: add a way to check for the types of keys with unknown values, like methods and attributes + * TODO: handle extensions + */ + assertMemberCount(act, exp) { const expKeys = Object.keys(exp); - for (const k of expKeys) { - assert(k in act, () => `Expected key ${k} missing`); - assert(act[k] === exp[k], () => `Value of [${k}] was ${act[k]}, expected ${exp[k]}`); - } const actKeys = Object.keys(act); assert( actKeys.length === expKeys.length, diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/listing.js b/tests/wpt/webgpu/tests/webgpu/webgpu/listing.js index 8736de378a6..3134cf0dd56 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/listing.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/listing.js @@ -121,6 +121,40 @@ export const listing = [ ], "readme": "Positive and negative tests for all the validation rules of the API." }, + { + "file": [ + "api", + "validation", + "copyBufferToBuffer" + ], + "description": "copyBufferToBuffer tests.\n\nTest Plan:\n* Buffer is valid/invalid\n - the source buffer is invalid\n - the destination buffer is invalid\n* Buffer usages\n - the source buffer is created without GPUBufferUsage::COPY_SRC\n - the destination buffer is created without GPUBufferUsage::COPY_DEST\n* CopySize\n - copySize is not a multiple of 4\n - copySize is 0\n* copy offsets\n - sourceOffset is not a multiple of 4\n - destinationOffset is not a multiple of 4\n* Arthimetic overflow\n - (sourceOffset + copySize) is overflow\n - (destinationOffset + copySize) is overflow\n* Out of bounds\n - (sourceOffset + copySize) > size of source buffer\n - (destinationOffset + copySize) > size of destination buffer\n* Source buffer and destination buffer are the same buffer" + }, + { + "file": [ + "api", + "validation", + "copy_between_linear_data_and_texture" + ], + "readme": "writeTexture + copyBufferToTexture + copyTextureToBuffer validation tests.\n\nTest coverage:\n* resource usages:\n\t- texture_usage_must_be_valid: for GPUTextureUsage::COPY_SRC, GPUTextureUsage::COPY_DST flags.\n\t- TODO: buffer_usage_must_be_valid\n\n* textureCopyView:\n\t- texture_must_be_valid: for valid, destroyed, error textures.\n\t- sample_count_must_be_1: for sample count 1 and 4.\n\t- mip_level_must_be_in_range: for various combinations of mipLevel and mipLevelCount.\n\t- texel_block_alignment_on_origin: for all formats and coordinates.\n\n* bufferCopyView:\n\t- TODO: buffer_must_be_valid\n\t- TODO: bytes_per_row_alignment\n\n* linear texture data:\n\t- bound_on_rows_per_image: for various combinations of copyDepth (1, >1), copyHeight, rowsPerImage.\n\t- offset_plus_required_bytes_in_copy_overflow\n\t- required_bytes_in_copy: testing minimal data size and data size too small for various combinations of bytesPerRow, rowsPerImage, copyExtent and offset. for the copy method, bytesPerRow is computed as bytesInACompleteRow aligned to be a multiple of 256 + bytesPerRowPadding * 256.\n\t- texel_block_alignment_on_rows_per_image: for all formats.\n\t- texel_block_alignment_on_offset: for all formats.\n\t- bound_on_bytes_per_row: for all formats and various combinations of bytesPerRow and copyExtent. for writeTexture, bytesPerRow is computed as (blocksPerRow * blockWidth * bytesPerBlock + additionalBytesPerRow) and copyExtent.width is computed as copyWidthInBlocks * blockWidth. for the copy methods, both values are mutliplied by 256.\n\t- bound_on_offset: for various combinations of offset and dataSize.\n\n* texture copy range:\n\t- 1d_texture: copyExtent.height isn't 1, copyExtent.depth isn't 1.\n\t- texel_block_alignment_on_size: for all formats and coordinates.\n\t- texture_range_conditons: for all coordinate and various combinations of origin, copyExtent, textureSize and mipLevel.\n\nTODO: more test coverage for 1D and 3D textures." + }, + { + "file": [ + "api", + "validation", + "copy_between_linear_data_and_texture", + "copyBetweenLinearDataAndTexture_dataRelated" + ], + "description": "" + }, + { + "file": [ + "api", + "validation", + "copy_between_linear_data_and_texture", + "copyBetweenLinearDataAndTexture_textureRelated" + ], + "description": "" + }, { "file": [ "api", @@ -218,7 +252,7 @@ export const listing = [ "resource_usages", "textureUsageInRender" ], - "description": "Texture Usages Validation Tests in Render Pass.\n\nTest Coverage:\n - Tests that read and write usages upon the same texture subresource, or different subresources\n of the same texture. Different subresources of the same texture includes different mip levels,\n different array layers, and different aspects.\n - When read and write usages are binding to the same texture subresource, an error should be\n generated. Otherwise, no error should be generated." + "description": "Texture Usages Validation Tests in Render Pass.\n\nTest Coverage:\n\n - For each combination of two texture usages:\n - For various subresource ranges (different mip levels or array layers) that overlap a given\n subresources or not for color formats:\n - Check that an error is generated when read-write or write-write usages are binding to the\n same texture subresource. Otherwise, no error should be generated. One exception is race\n condition upon two writeonly-storage-texture usages, which is valid.\n\n - For each combination of two texture usages:\n - For various aspects (all, depth-only, stencil-only) that overlap a given subresources or not\n for depth/stencil formats:\n - Check that an error is generated when read-write or write-write usages are binding to the\n same aspect. Otherwise, no error should be generated.\n\n - Test combinations of two shader stages:\n - Texture usages in bindings with invisible shader stages should be tracked. Invisible shader\n stages include shader stage with visibility none and compute shader stage in render pass." }, { "file": [ diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/util/math.js b/tests/wpt/webgpu/tests/webgpu/webgpu/util/math.js index a76f1a00158..4761467b586 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/util/math.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/util/math.js @@ -7,3 +7,5 @@ export function isAligned(n, alignment) { return n === align(n, alignment); } + +export const kMaxSafeMultipleOf8 = Number.MAX_SAFE_INTEGER - 7; diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/layout.js b/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/layout.js index 26d82a7be0a..c3c610bf0d9 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/layout.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/layout.js @@ -1,7 +1,7 @@ /** * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts **/ import { assert, unreachable } from '../../../common/framework/util/util.js'; -import { kTextureFormatInfo } from '../../capability_info.js'; +import { kSizedTextureFormatInfo } from '../../capability_info.js'; import { align, isAligned } from '../math.js'; export const kBytesPerRowAlignment = 256; @@ -30,8 +30,7 @@ export function getTextureCopyLayout(format, dimension, size, options = kDefault const mipSize = getMipSizePassthroughLayers(dimension, size, mipLevel); - const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format]; - assert(!!bytesPerBlock && !!blockWidth && !!blockHeight); + const { blockWidth, blockHeight, bytesPerBlock } = kSizedTextureFormatInfo[format]; assert(isAligned(mipSize[0], blockWidth)); const minBytesPerRow = (mipSize[0] / blockWidth) * bytesPerBlock; @@ -73,8 +72,7 @@ export function fillTextureDataWithTexelValue( size, options = kDefaultLayoutOptions ) { - const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format]; - assert(!!bytesPerBlock && !!blockWidth && !!blockHeight); + const { blockWidth, blockHeight, bytesPerBlock } = kSizedTextureFormatInfo[format]; assert(bytesPerBlock === texelValue.byteLength); const { byteLength, rowsPerImage, bytesPerRow } = getTextureCopyLayout( diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/texelData.js b/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/texelData.js index 8a827c47d21..eadaa096330 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/texelData.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/util/texture/texelData.js @@ -14,7 +14,7 @@ return obj; } import { assert, unreachable } from '../../../common/framework/util/util.js'; -import { kTextureFormatInfo } from '../../capability_info.js'; +import { kUncompressedTextureFormatInfo } from '../../capability_info.js'; import { assertInIntegerRange, float32ToFloatBits, @@ -333,7 +333,7 @@ class TexelDataRepresentationImpl { ]; } - const bytesPerBlock = kTextureFormatInfo[this.format].bytesPerBlock; + const bytesPerBlock = kUncompressedTextureFormatInfo[this.format].bytesPerBlock; assert(!!bytesPerBlock); const data = new ArrayBuffer(bytesPerBlock); diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js b/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js index 1432ff05e1d..9df5ff94419 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/copyImageBitmapToTexture.spec.js @@ -6,7 +6,7 @@ copy imageBitmap To texture tests. import { poptions, params } from '../../common/framework/params_builder.js'; import { makeTestGroup } from '../../common/framework/test_group.js'; import { unreachable } from '../../common/framework/util/util.js'; -import { kTextureFormatInfo } from '../capability_info.js'; +import { kUncompressedTextureFormatInfo } from '../capability_info.js'; import { GPUTest } from '../gpu_test.js'; import { getTexelDataRepresentation } from '../util/texture/texelData.js'; @@ -220,13 +220,14 @@ g.test('from_ImageData') .fn(async t => { const { width, height, alpha, orientation, dstColorFormat } = t.params; - const srcBytesPerPixel = kTextureFormatInfo['rgba8unorm'].bytesPerBlock; + const format = 'rgba8unorm'; + const srcBytesPerPixel = kUncompressedTextureFormatInfo[format].bytesPerBlock; // Generate input contents by iterating 'Color' enum const imagePixels = new Uint8ClampedArray(srcBytesPerPixel * width * height); const startPixel = Color.Red; for (let i = 0, currentPixel = startPixel; i < width * height; ++i) { - const pixels = t.generatePixel(currentPixel, 'rgba8unorm'); + const pixels = t.generatePixel(currentPixel, format); if (currentPixel === Color.TransparentBlack) { currentPixel = Color.Red; } else { @@ -257,7 +258,7 @@ g.test('from_ImageData') }); // Construct expected value for different dst color format - const dstBytesPerPixel = kTextureFormatInfo[dstColorFormat].bytesPerBlock; + const dstBytesPerPixel = kUncompressedTextureFormatInfo[dstColorFormat].bytesPerBlock; const dstPixels = new Uint8ClampedArray(dstBytesPerPixel * width * height); let expectedPixels = new Uint8ClampedArray(dstBytesPerPixel * width * height); for (let i = 0, currentPixel = startPixel; i < width * height; ++i) { diff --git a/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js b/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js index dd58b543b01..a45002835df 100644 --- a/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js +++ b/tests/wpt/webgpu/tests/webgpu/webgpu/web-platform/reftests/gpu_ref_test.js @@ -9,7 +9,9 @@ export async function runRefTest(fn) { ); const adapter = await navigator.gpu.requestAdapter(); + assert(adapter !== null); const device = await adapter.requestDevice(); + assert(device !== null); const queue = device.defaultQueue; await fn({ device, queue });