mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Auto merge of #27614 - kunalmohan:webgpu-cts, r=kvark
Minor fixes and update cts <!-- Please describe your changes on the following line: --> - Prevent redundant buffer and texture destroy calls. - More subtests for B2B copy pass now. - All tests under `setViewport()` and `setScissorRect()` pass now. - Tests for `createTexture()` do not crash. More than 50% of them pass now. r?@kvark --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
9e6da58d77
17 changed files with 1407 additions and 98 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -7028,7 +7028,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#1d0e0ce37ede5ec53000ab252c27b8cf856865b2"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#59f0996eabd43e882d4bfc73ee5b4ed912617abf"
|
||||
dependencies = [
|
||||
"arrayvec 0.5.1",
|
||||
"bitflags",
|
||||
|
@ -7055,7 +7055,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#1d0e0ce37ede5ec53000ab252c27b8cf856865b2"
|
||||
source = "git+https://github.com/gfx-rs/wgpu#59f0996eabd43e882d4bfc73ee5b4ed912617abf"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"serde",
|
||||
|
|
|
@ -184,6 +184,7 @@ impl GPUBufferMethods for GPUBuffer {
|
|||
GPUBufferState::Mapped | GPUBufferState::MappedAtCreation => {
|
||||
self.Unmap();
|
||||
},
|
||||
GPUBufferState::Destroyed => return,
|
||||
_ => {},
|
||||
};
|
||||
if let Err(e) = self
|
||||
|
|
|
@ -18,6 +18,7 @@ use crate::dom::gpudevice::{
|
|||
};
|
||||
use crate::dom::gputextureview::GPUTextureView;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use std::num::NonZeroU32;
|
||||
use std::string::String;
|
||||
use webgpu::{
|
||||
|
@ -40,6 +41,7 @@ pub struct GPUTexture {
|
|||
dimension: GPUTextureDimension,
|
||||
format: GPUTextureFormat,
|
||||
texture_usage: u32,
|
||||
destroyed: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GPUTexture {
|
||||
|
@ -67,6 +69,7 @@ impl GPUTexture {
|
|||
dimension,
|
||||
format,
|
||||
texture_usage,
|
||||
destroyed: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,6 +200,9 @@ impl GPUTextureMethods for GPUTexture {
|
|||
|
||||
/// https://gpuweb.github.io/gpuweb/#dom-gputexture-destroy
|
||||
fn Destroy(&self) {
|
||||
if self.destroyed.get() {
|
||||
return;
|
||||
}
|
||||
if let Err(e) = self
|
||||
.channel
|
||||
.0
|
||||
|
@ -207,5 +213,6 @@ impl GPUTextureMethods for GPUTexture {
|
|||
self.texture.0, e
|
||||
);
|
||||
};
|
||||
self.destroyed.set(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ use servo_config::pref;
|
|||
use smallvec::SmallVec;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZeroU64;
|
||||
use std::rc::Rc;
|
||||
|
@ -475,9 +474,7 @@ impl<'a> WGPU<'a> {
|
|||
))
|
||||
.map_err(|e| format!("{:?}", e))
|
||||
};
|
||||
if result.is_err() {
|
||||
self.encoder_record_error(command_encoder_id, result.clone());
|
||||
}
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
self.send_result(device_id, scope_id, result);
|
||||
},
|
||||
WebGPURequest::CopyBufferToBuffer {
|
||||
|
@ -497,7 +494,7 @@ impl<'a> WGPU<'a> {
|
|||
destination_offset,
|
||||
size
|
||||
));
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::CopyBufferToTexture {
|
||||
command_encoder_id,
|
||||
|
@ -512,7 +509,7 @@ impl<'a> WGPU<'a> {
|
|||
&destination,
|
||||
©_size
|
||||
));
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::CopyTextureToBuffer {
|
||||
command_encoder_id,
|
||||
|
@ -527,7 +524,7 @@ impl<'a> WGPU<'a> {
|
|||
&destination,
|
||||
©_size
|
||||
));
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::CopyTextureToTexture {
|
||||
command_encoder_id,
|
||||
|
@ -542,7 +539,7 @@ impl<'a> WGPU<'a> {
|
|||
&destination,
|
||||
©_size
|
||||
));
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::CreateBindGroup {
|
||||
device_id,
|
||||
|
@ -985,7 +982,7 @@ impl<'a> WGPU<'a> {
|
|||
} else {
|
||||
Err(String::from("Invalid ComputePass"))
|
||||
};
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::RunRenderPass {
|
||||
command_encoder_id,
|
||||
|
@ -1000,7 +997,7 @@ impl<'a> WGPU<'a> {
|
|||
} else {
|
||||
Err(String::from("Invalid RenderPass"))
|
||||
};
|
||||
self.encoder_record_error(command_encoder_id, result);
|
||||
self.encoder_record_error(command_encoder_id, &result);
|
||||
},
|
||||
WebGPURequest::Submit {
|
||||
queue_id,
|
||||
|
@ -1279,12 +1276,13 @@ impl<'a> WGPU<'a> {
|
|||
fn encoder_record_error<U, T: std::fmt::Debug>(
|
||||
&self,
|
||||
encoder_id: id::CommandEncoderId,
|
||||
result: Result<U, T>,
|
||||
result: &Result<U, T>,
|
||||
) {
|
||||
if let Err(e) = result {
|
||||
if let Entry::Vacant(v) = self.error_command_encoders.borrow_mut().entry(encoder_id) {
|
||||
v.insert(format!("{:?}", e));
|
||||
}
|
||||
if let Err(ref e) = result {
|
||||
self.error_command_encoders
|
||||
.borrow_mut()
|
||||
.entry(encoder_id)
|
||||
.or_insert_with(|| format!("{:?}", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
[]
|
||||
],
|
||||
"params_utils.js": [
|
||||
"a95d01b9c8058076af5cf49d4ab82b5c74367a5b",
|
||||
"d4ffd25372d2d3e975c683ca8a17c2c82d5c8687",
|
||||
[]
|
||||
],
|
||||
"query": {
|
||||
|
@ -98,7 +98,7 @@
|
|||
[]
|
||||
],
|
||||
"encode_selectively.js": [
|
||||
"62cb55ee039b7cc04dfdf751ce2241ba5864cac6",
|
||||
"cb365deb4bb688e8ae5eebdef24a2ffcb3d857ef",
|
||||
[]
|
||||
],
|
||||
"json_param_value.js": [
|
||||
|
@ -106,7 +106,7 @@
|
|||
[]
|
||||
],
|
||||
"parseQuery.js": [
|
||||
"6c10baab0b2f97dc09e633201dae6618842fbd69",
|
||||
"8bfd88bc9b66a41e08b3283b13b65bb3da0c10fe",
|
||||
[]
|
||||
],
|
||||
"query.js": [
|
||||
|
@ -161,7 +161,7 @@
|
|||
]
|
||||
},
|
||||
"version.js": [
|
||||
"794e3cdef44214801f15234a61aaf5af338f97fc",
|
||||
"74eef63b8a1fa6042d1d8352b25eaf95d4b25985",
|
||||
[]
|
||||
]
|
||||
},
|
||||
|
@ -223,6 +223,10 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"copyBetweenLinearDataAndTexture.spec.js": [
|
||||
"d2b89189e2c65d50f4f6f0c20f32a7f6512c5b35",
|
||||
[]
|
||||
],
|
||||
"fences.spec.js": [
|
||||
"98f913008b8af33e1dc866f5714388d4ec9e050d",
|
||||
[]
|
||||
|
@ -311,7 +315,7 @@
|
|||
],
|
||||
"resource_usages": {
|
||||
"textureUsageInRender.spec.js": [
|
||||
"12efa65ce2d9e9ed67cb2be398a0466424d38015",
|
||||
"b036245663df8d684067eff7c79861253205dbca",
|
||||
[]
|
||||
]
|
||||
},
|
||||
|
@ -324,7 +328,7 @@
|
|||
[]
|
||||
],
|
||||
"setScissorRect.spec.js": [
|
||||
"7934c007286c8c4e9702eaaadb14b288a78e8fb1",
|
||||
"c049e92e70e3ad9a5f71f88a863e5a86cc74fc4e",
|
||||
[]
|
||||
],
|
||||
"setStencilReference.spec.js": [
|
||||
|
@ -350,7 +354,7 @@
|
|||
[]
|
||||
],
|
||||
"gpu_test.js": [
|
||||
"f350131af3babe9729dec35261f7c445e2bf41d2",
|
||||
"21cb10f1429e495b2f32b1d51a09b8584f63707d",
|
||||
[]
|
||||
],
|
||||
"idl": {
|
||||
|
@ -366,7 +370,7 @@
|
|||
]
|
||||
},
|
||||
"listing.js": [
|
||||
"3134cf0dd5693705ed82f0828f4dbd93fedf358e",
|
||||
"cbb23b30ec894c103a957f944b18be1e019ed571",
|
||||
[]
|
||||
],
|
||||
"util": {
|
||||
|
@ -380,7 +384,7 @@
|
|||
],
|
||||
"texture": {
|
||||
"layout.js": [
|
||||
"c3c610bf0d93ebe66abf81d8f2017deba62641a3",
|
||||
"927798985fc772a4c9e9ea7a62335ab693b43991",
|
||||
[]
|
||||
],
|
||||
"subresource.js": [
|
||||
|
@ -435,7 +439,7 @@
|
|||
"testharness": {
|
||||
"webgpu": {
|
||||
"cts.html": [
|
||||
"28d69b38d20367b4c61e72e834f518a11e8de411",
|
||||
"63357f7e996ecadde32f6816dc131b94e9ab976c",
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,operation,buffers,map_detach:*",
|
||||
{}
|
||||
|
@ -456,6 +460,10 @@
|
|||
"webgpu/cts.html?q=webgpu:api,operation,command_buffer,render,basic:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,operation,copyBetweenLinearDataAndTexture:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,operation,fences:*",
|
||||
{}
|
||||
|
@ -484,10 +492,6 @@
|
|||
"webgpu/cts.html?q=webgpu:api,validation,createPipelineLayout:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,createTexture:*",
|
||||
{}
|
||||
],
|
||||
[
|
||||
"webgpu/cts.html?q=webgpu:api,validation,error_scope:*",
|
||||
{}
|
||||
|
|
|
@ -30,36 +30,95 @@
|
|||
|
||||
|
||||
[cts.html?q=webgpu:api,validation,createTexture:*]
|
||||
expected: CRASH
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc2-rgba-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc3-rgba-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_mipLevelCount:width=32;height=31;mipLevelCount=7]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="r8snorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_submit_a_destroyed_texture_before_and_after_encode:destroyBeforeEncode=false;destroyAfterEncode=true]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="rg11b10float"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_submit_a_destroyed_texture_before_and_after_encode:destroyBeforeEncode=true;destroyAfterEncode=false]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_sampleCount:sampleCount=2]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc4-r-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_sampleCount:sampleCount=8]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_sampleCount:sampleCount=16]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_sampleCount:sampleCount=4;arrayLayerCount=2]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_mipLevelCount:width=32;height=32;mipLevelCount=0]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc1-rgba-unorm-srgb"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc6h-rgb-ufloat"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc7-rgba-unorm-srgb"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_mipLevelCount:width=32;height=32;mipLevelCount=100]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc5-rg-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc6h-rgb-sfloat"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc7-rgba-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_sampleCount:sampleCount=4;mipLevelCount=2]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="rg8snorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc1-rgba-unorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc4-r-snorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc3-rgba-unorm-srgb"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="rgba8snorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc5-rg-snorm"]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:validation_of_mipLevelCount:width=31;height=32;mipLevelCount=7]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,createTexture:it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format:format="bc2-rgba-unorm-srgb"]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[cts.html?q=webgpu:api,validation,setViewport:*]
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=-1;minDepth=0;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=1;minDepth=10;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=0;minDepth=0;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=1;minDepth=-1;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=0;height=1;minDepth=0;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=1;minDepth=0;maxDepth=-1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=0;height=0;minDepth=0;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=-1;height=1;minDepth=0;maxDepth=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setViewport:use_of_setViewport:x=0;y=0;width=1;height=1;minDepth=0;maxDepth=10]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[cts.html?q=webgpu:web-platform,copyImageBitmapToTexture:*]
|
||||
expected: TIMEOUT
|
||||
|
@ -183,15 +242,6 @@
|
|||
|
||||
|
||||
[cts.html?q=webgpu:api,validation,setScissorRect:*]
|
||||
[webgpu:api,validation,setScissorRect:use_of_setScissorRect:x=0;y=0;width=0;height=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setScissorRect:use_of_setScissorRect:x=0;y=0;width=0;height=0]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,setScissorRect:use_of_setScissorRect:x=0;y=0;width=1;height=0]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[cts.html?q=webgpu:web-platform,canvas,context_creation:*]
|
||||
|
||||
|
@ -222,15 +272,9 @@
|
|||
[cts.html?q=webgpu:api,operation,command_buffer,render,basic:*]
|
||||
|
||||
[cts.html?q=webgpu:api,validation,copyBufferToBuffer:*]
|
||||
[webgpu:api,validation,copyBufferToBuffer:copy_within_same_buffer:srcOffset=4;dstOffset=0;copySize=8]
|
||||
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=512;dstUsage=8]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -243,9 +287,6 @@
|
|||
[webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=512;dstUsage=1]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,copyBufferToBuffer:copy_out_of_bounds:srcOffset=36;dstOffset=0;copySize=0]
|
||||
expected: FAIL
|
||||
|
||||
[webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=8;dstUsage=512]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -255,15 +296,9 @@
|
|||
[webgpu:api,validation,copyBufferToBuffer:buffer_usage:srcUsage=1;dstUsage=512]
|
||||
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=512]
|
||||
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=4;dstUsage=512]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -279,9 +314,6 @@
|
|||
[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=512;dstUsage=64]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -303,3 +335,6 @@
|
|||
|
||||
[cts.html?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_dataRelated:*]
|
||||
expected: CRASH
|
||||
|
||||
[cts.html?q=webgpu:api,operation,copyBetweenLinearDataAndTexture:*]
|
||||
expected: TIMEOUT
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
**/ import { comparePublicParamsPaths, Ordering } from './query/compare.js';
|
||||
import { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js';
|
||||
// Consider adding more types here if needed
|
||||
//
|
||||
// TODO: This type isn't actually used to constrain what you're allowed to do in `.params()`, so
|
||||
// it's not really serving its purpose. Figure out how to fix that?
|
||||
|
||||
export function paramKeyIsPublic(key) {
|
||||
return !key.startsWith('_');
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
ret = ret.replace(/%3D/g, '='); // for params (k=v)
|
||||
ret = ret.replace(/%5B/g, '['); // for JSON arrays
|
||||
ret = ret.replace(/%5D/g, ']'); // for JSON arrays
|
||||
ret = ret.replace(/%7B/g, '{'); // for JSON objects
|
||||
ret = ret.replace(/%7D/g, '}'); // for JSON objects
|
||||
ret = ret.replace(/%E2%9C%97/g, '✗'); // for jsUndefinedMagicValue
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,29 @@ function parseQueryImpl(s) {
|
|||
// Undo encodeURIComponentSelectively
|
||||
s = decodeURIComponent(s);
|
||||
|
||||
// bigParts are: suite, group, test, params (note kBigSeparator could appear in params)
|
||||
const [suite, fileString, testString, paramsString] = s.split(kBigSeparator, 4);
|
||||
assert(fileString !== undefined, `filter string must have at least one ${kBigSeparator}`);
|
||||
// bigParts are: suite, file, test, params (note kBigSeparator could appear in params)
|
||||
let suite;
|
||||
let fileString;
|
||||
let testString;
|
||||
let paramsString;
|
||||
{
|
||||
const i1 = s.indexOf(kBigSeparator);
|
||||
assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`);
|
||||
suite = s.substring(0, i1);
|
||||
const i2 = s.indexOf(kBigSeparator, i1 + 1);
|
||||
if (i2 === -1) {
|
||||
fileString = s.substring(i1 + 1);
|
||||
} else {
|
||||
fileString = s.substring(i1 + 1, i2);
|
||||
const i3 = s.indexOf(kBigSeparator, i2 + 1);
|
||||
if (i3 === -1) {
|
||||
testString = s.substring(i2 + 1);
|
||||
} else {
|
||||
testString = s.substring(i2 + 1, i3);
|
||||
paramsString = s.substring(i3 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
|
||||
|
||||
export const version = 'fa4873f0a303566ca6f34744a253d96f5e462d3d';
|
||||
export const version = 'c1df7f4ff1adcde985384633e7cffa52d53e3535';
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<meta name=variant content='?q=webgpu:api,operation,command_buffer,basic:*'>
|
||||
<meta name=variant content='?q=webgpu:api,operation,command_buffer,copies:*'>
|
||||
<meta name=variant content='?q=webgpu:api,operation,command_buffer,render,basic:*'>
|
||||
<meta name=variant content='?q=webgpu:api,operation,copyBetweenLinearDataAndTexture:*'>
|
||||
<meta name=variant content='?q=webgpu:api,operation,fences:*'>
|
||||
<meta name=variant content='?q=webgpu:api,operation,render_pass,storeOp:*'>
|
||||
<!--<meta name=variant content='?q=webgpu:api,operation,resource_init,copied_texture_clear:*'>-->
|
||||
|
@ -42,7 +43,7 @@
|
|||
<meta name=variant content='?q=webgpu:api,validation,createBindGroup:*'>
|
||||
<!--<meta name=variant content='?q=webgpu:api,validation,createBindGroupLayout:*'>-->
|
||||
<meta name=variant content='?q=webgpu:api,validation,createPipelineLayout:*'>
|
||||
<meta name=variant content='?q=webgpu:api,validation,createTexture:*'>
|
||||
<!--<meta name=variant content='?q=webgpu:api,validation,createTexture:*'>-->
|
||||
<!--<meta name=variant content='?q=webgpu:api,validation,createView:*'>-->
|
||||
<meta name=variant content='?q=webgpu:api,validation,error_scope:*'>
|
||||
<meta name=variant content='?q=webgpu:api,validation,fences:*'>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,13 +21,22 @@ Test Coverage:
|
|||
- 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.
|
||||
|
||||
- Tests replaced bindings:
|
||||
- Texture usages via bindings replaced by another setBindGroup() upon the same bindGroup index
|
||||
in current scope should be tracked.
|
||||
|
||||
- Test texture usages in bundle:
|
||||
- Texture usages in bundle should be tracked if that bundle is executed in the current scope.
|
||||
`;
|
||||
import { poptions, params } from '../../../../common/framework/params_builder.js';
|
||||
import { pbool, poptions, params } from '../../../../common/framework/params_builder.js';
|
||||
import { makeTestGroup } from '../../../../common/framework/test_group.js';
|
||||
import {
|
||||
kShaderStages,
|
||||
kDepthStencilFormats,
|
||||
kDepthStencilFormatInfo,
|
||||
kTextureBindingTypes,
|
||||
kTextureBindingTypeInfo,
|
||||
kShaderStages,
|
||||
} from '../../../capability_info.js';
|
||||
import { ValidationTest } from '../validation_test.js';
|
||||
|
||||
|
@ -52,6 +61,22 @@ class TextureUsageTracking extends ValidationTest {
|
|||
usage,
|
||||
});
|
||||
}
|
||||
|
||||
createBindGroup(index, view, bindingType, bindingTexFormat) {
|
||||
return this.device.createBindGroup({
|
||||
entries: [{ binding: index, resource: view }],
|
||||
layout: this.device.createBindGroupLayout({
|
||||
entries: [
|
||||
{
|
||||
binding: index,
|
||||
visibility: GPUShaderStage.FRAGMENT,
|
||||
type: bindingType,
|
||||
storageTextureFormat: bindingTexFormat,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const g = makeTestGroup(TextureUsageTracking);
|
||||
|
@ -400,3 +425,158 @@ g.test('shader_stages_and_visibility')
|
|||
encoder.finish();
|
||||
});
|
||||
});
|
||||
|
||||
// We should track the texture usages in bindings which are replaced by another setBindGroup()
|
||||
// call site upon the same index in the same render pass.
|
||||
g.test('replaced_binding')
|
||||
.params(poptions('bindingType', kTextureBindingTypes))
|
||||
.fn(async t => {
|
||||
const { bindingType } = t.params;
|
||||
const info = kTextureBindingTypeInfo[bindingType];
|
||||
const bindingTexFormat = info.resource === 'storageTex' ? 'rgba8unorm' : undefined;
|
||||
|
||||
const sampledView = t.createTexture().createView();
|
||||
const sampledStorageView = t
|
||||
.createTexture({ usage: GPUTextureUsage.STORAGE | GPUTextureUsage.SAMPLED })
|
||||
.createView();
|
||||
|
||||
// Create bindGroup0. It has two bindings. These two bindings use different views/subresources.
|
||||
const bglEntries0 = [
|
||||
{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type: 'sampled-texture' },
|
||||
{
|
||||
binding: 1,
|
||||
visibility: GPUShaderStage.FRAGMENT,
|
||||
type: bindingType,
|
||||
storageTextureFormat: bindingTexFormat,
|
||||
},
|
||||
];
|
||||
|
||||
const bgEntries0 = [
|
||||
{ binding: 0, resource: sampledView },
|
||||
{ binding: 1, resource: sampledStorageView },
|
||||
];
|
||||
|
||||
const bindGroup0 = t.device.createBindGroup({
|
||||
entries: bgEntries0,
|
||||
layout: t.device.createBindGroupLayout({ entries: bglEntries0 }),
|
||||
});
|
||||
|
||||
// Create bindGroup1. It has one binding, which use the same view/subresoure of a binding in
|
||||
// bindGroup0. So it may or may not conflicts with that binding in bindGroup0.
|
||||
const bindGroup1 = t.createBindGroup(0, sampledStorageView, 'sampled-texture', undefined);
|
||||
|
||||
const encoder = t.device.createCommandEncoder();
|
||||
const pass = encoder.beginRenderPass({
|
||||
colorAttachments: [
|
||||
{
|
||||
attachment: t.createTexture().createView(),
|
||||
loadValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
|
||||
storeOp: 'store',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// Set bindGroup0 and bindGroup1. bindGroup0 is replaced by bindGroup1 in the current pass.
|
||||
// But bindings in bindGroup0 should be tracked too.
|
||||
pass.setBindGroup(0, bindGroup0);
|
||||
pass.setBindGroup(0, bindGroup1);
|
||||
pass.endPass();
|
||||
|
||||
const success = bindingType === 'writeonly-storage-texture' ? false : true;
|
||||
t.expectValidationError(() => {
|
||||
encoder.finish();
|
||||
}, !success);
|
||||
});
|
||||
|
||||
g.test('bindings_in_bundle')
|
||||
.params(
|
||||
params()
|
||||
.combine(pbool('binding0InBundle'))
|
||||
.combine(pbool('binding1InBundle'))
|
||||
.combine(poptions('type0', ['render-target', ...kTextureBindingTypes]))
|
||||
.combine(poptions('type1', ['render-target', ...kTextureBindingTypes]))
|
||||
.unless(
|
||||
({ binding0InBundle, binding1InBundle, type0, type1 }) =>
|
||||
// We can't set 'render-target' in bundle, so we need to exclude it from bundle.
|
||||
// In addition, if both bindings are non-bundle, there is no need to test it because
|
||||
// we have far more comprehensive test cases for that situation in this file.
|
||||
(binding0InBundle && type0 === 'render-target') ||
|
||||
(binding1InBundle && type1 === 'render-target') ||
|
||||
(!binding0InBundle && !binding1InBundle)
|
||||
)
|
||||
)
|
||||
.fn(async t => {
|
||||
const { binding0InBundle, binding1InBundle, type0, type1 } = t.params;
|
||||
|
||||
// Two bindings are attached to the same texture view.
|
||||
const view = t
|
||||
.createTexture({
|
||||
usage:
|
||||
GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.STORAGE | GPUTextureUsage.SAMPLED,
|
||||
})
|
||||
.createView();
|
||||
|
||||
const bindGroups = [];
|
||||
if (type0 !== 'render-target') {
|
||||
const binding0TexFormat = type0 === 'sampled-texture' ? undefined : 'rgba8unorm';
|
||||
bindGroups[0] = t.createBindGroup(0, view, type0, binding0TexFormat);
|
||||
}
|
||||
if (type1 !== 'render-target') {
|
||||
const binding1TexFormat = type1 === 'sampled-texture' ? undefined : 'rgba8unorm';
|
||||
bindGroups[1] = t.createBindGroup(1, view, type1, binding1TexFormat);
|
||||
}
|
||||
|
||||
const encoder = t.device.createCommandEncoder();
|
||||
const pass = encoder.beginRenderPass({
|
||||
colorAttachments: [
|
||||
{
|
||||
attachment:
|
||||
// At least one binding is in bundle, which means that its type is not 'render-target'.
|
||||
// As a result, only one binding's type is 'render-target' at most.
|
||||
type0 === 'render-target' || type1 === 'render-target'
|
||||
? view
|
||||
: t.createTexture().createView(),
|
||||
loadValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
|
||||
storeOp: 'store',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const bindingsInBundle = [binding0InBundle, binding1InBundle];
|
||||
for (let i = 0; i < 2; i++) {
|
||||
// Create a bundle for each bind group if its bindings is required to be in bundle on purpose.
|
||||
// Otherwise, call setBindGroup directly in pass if needed (when its binding is not
|
||||
// 'render-target').
|
||||
if (bindingsInBundle[i]) {
|
||||
const bundleEncoder = t.device.createRenderBundleEncoder({
|
||||
colorFormats: ['rgba8unorm'],
|
||||
});
|
||||
|
||||
bundleEncoder.setBindGroup(i, bindGroups[i]);
|
||||
const bundleInPass = bundleEncoder.finish();
|
||||
pass.executeBundles([bundleInPass]);
|
||||
} else if (bindGroups[i] !== undefined) {
|
||||
pass.setBindGroup(i, bindGroups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pass.endPass();
|
||||
|
||||
let success = false;
|
||||
if (
|
||||
(type0 === 'sampled-texture' || type0 === 'readonly-storage-texture') &&
|
||||
(type1 === 'sampled-texture' || type1 === 'readonly-storage-texture')
|
||||
) {
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (type0 === 'writeonly-storage-texture' && type1 === 'writeonly-storage-texture') {
|
||||
success = true;
|
||||
}
|
||||
|
||||
// Resource usages in bundle should be tracked. And validation error should be reported
|
||||
// if needed.
|
||||
t.expectValidationError(() => {
|
||||
encoder.finish();
|
||||
}, !success);
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ g.test('use_of_setScissorRect')
|
|||
{ x: 0, y: 0, width: 0, height: 1, _success: false }, // Width of zero is not allowed
|
||||
{ x: 0, y: 0, width: 1, height: 0, _success: false }, // Height of zero is not allowed
|
||||
{ x: 0, y: 0, width: 0, height: 0, _success: false }, // Both width and height of zero are not allowed
|
||||
{ x: 0, y: 0, width: TEXTURE_WIDTH + 1, height: TEXTURE_HEIGHT + 1, _success: true }, // Scissor larger than the framebuffer is allowed
|
||||
{ x: 0, y: 0, width: TEXTURE_WIDTH + 1, height: TEXTURE_HEIGHT + 1, _success: false }, // Scissor larger than the framebuffer is not allowed
|
||||
])
|
||||
.fn(async t => {
|
||||
const { x, y, width, height, _success } = t.params;
|
||||
|
|
|
@ -18,6 +18,7 @@ import { DevicePool, TestOOMedShouldAttemptGC } from '../common/framework/gpu/de
|
|||
import { attemptGarbageCollection } from '../common/framework/util/collect_garbage.js';
|
||||
import { assert } from '../common/framework/util/util.js';
|
||||
|
||||
import { align } from './util/math.js';
|
||||
import { fillTextureDataWithTexelValue, getTextureCopyLayout } from './util/texture/layout.js';
|
||||
import { getTexelDataRepresentation } from './util/texture/texelData.js';
|
||||
|
||||
|
@ -76,6 +77,9 @@ export class GPUTest extends Fixture {
|
|||
}
|
||||
|
||||
createCopyForMapRead(src, srcOffset, size) {
|
||||
assert(srcOffset % 4 === 0);
|
||||
assert(size % 4 === 0);
|
||||
|
||||
const dst = this.device.createBuffer({
|
||||
size,
|
||||
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
|
||||
|
@ -91,14 +95,31 @@ export class GPUTest extends Fixture {
|
|||
|
||||
// TODO: add an expectContents for textures, which logs data: uris on failure
|
||||
|
||||
// Offset and size passed to createCopyForMapRead must be divisible by 4. For that
|
||||
// we might need to copy more bytes from the buffer than we want to map.
|
||||
// begin and end values represent the part of the copied buffer that stores the contents
|
||||
// we initially wanted to map.
|
||||
// The copy will not cause an OOB error because the buffer size must be 4-aligned.
|
||||
createAlignedCopyForMapRead(src, size, offset) {
|
||||
const alignedOffset = Math.floor(offset / 4) * 4;
|
||||
const offsetDifference = offset - alignedOffset;
|
||||
const alignedSize = align(size + offsetDifference, 4);
|
||||
const dst = this.createCopyForMapRead(src, alignedOffset, alignedSize);
|
||||
return { dst, begin: offsetDifference, end: offsetDifference + size };
|
||||
}
|
||||
|
||||
expectContents(src, expected, srcOffset = 0) {
|
||||
const dst = this.createCopyForMapRead(src, srcOffset, expected.buffer.byteLength);
|
||||
const { dst, begin, end } = this.createAlignedCopyForMapRead(
|
||||
src,
|
||||
expected.byteLength,
|
||||
srcOffset
|
||||
);
|
||||
|
||||
this.eventualAsyncExpectation(async niceStack => {
|
||||
const constructor = expected.constructor;
|
||||
await dst.mapAsync(GPUMapMode.READ);
|
||||
const actual = new constructor(dst.getMappedRange());
|
||||
const check = this.checkBuffer(actual, expected);
|
||||
const check = this.checkBuffer(actual.subarray(begin, end), expected);
|
||||
if (check !== undefined) {
|
||||
niceStack.message = check;
|
||||
this.rec.expectationFailed(niceStack);
|
||||
|
|
|
@ -81,6 +81,14 @@ export const listing = [
|
|||
],
|
||||
"description": "Basic command buffer rendering tests."
|
||||
},
|
||||
{
|
||||
"file": [
|
||||
"api",
|
||||
"operation",
|
||||
"copyBetweenLinearDataAndTexture"
|
||||
],
|
||||
"description": "writeTexture + copyBufferToTexture + copyTextureToBuffer operation tests.\n\n* copy_with_various_rows_per_image_and_bytes_per_row: test that copying data with various bytesPerRow (including { ==, > } bytesInACompleteRow) and rowsPerImage (including { ==, > } copyExtent.height) values and minimum required bytes in copy works for every format. Also covers special code paths:\n - bufferSize - offset < bytesPerImage * copyExtent.depth\n - when bytesPerRow is not a multiple of 512 and copyExtent.depth > 1: copyExtent.depth % 2 == { 0, 1 }\n - bytesPerRow == bytesInACompleteCopyImage\n\n* copy_with_various_offsets_and_data_sizes: test that copying data with various offset (including { ==, > } 0 and is/isn't power of 2) values and additional data paddings works for every format with 2d and 2d-array textures. Also covers special code paths:\n - offset + bytesInCopyExtentPerRow { ==, > } bytesPerRow\n - offset > bytesInACompleteCopyImage\n\n* copy_with_various_origins_and_copy_extents: test that copying slices of a texture works with various origin (including { origin.x, origin.y, origin.z } { ==, > } 0 and is/isn't power of 2) and copyExtent (including { copyExtent.x, copyExtent.y, copyExtent.z } { ==, > } 0 and is/isn't power of 2) values (also including {origin._ + copyExtent._ { ==, < } the subresource size of textureCopyView) works for all formats. origin and copyExtent values are passed as [number, number, number] instead of GPUExtent3DDict.\n\n* copy_various_mip_levels: test that copying various mip levels works for all formats. Also covers special code paths:\n - the physical size of the subresouce is not equal to the logical size\n - bufferSize - offset < bytesPerImage * copyExtent.depth and copyExtent needs to be clamped\n\n* copy_with_no_image_or_slice_padding_and_undefined_values: test that when copying a single row we can set any bytesPerRow value and when copying a single slice we can set rowsPerImage to 0. Also test setting offset, rowsPerImage, mipLevel, origin, origin.{x,y,z} to undefined.\n\n* TODO:\n - add another initMethod which renders the texture\n - because of expectContests 4-bytes alignment we don't test CopyT2B with buffer size not divisible by 4\n - add tests for 1d / 3d textures"
|
||||
},
|
||||
{
|
||||
"file": [
|
||||
"api",
|
||||
|
@ -252,7 +260,7 @@ export const listing = [
|
|||
"resource_usages",
|
||||
"textureUsageInRender"
|
||||
],
|
||||
"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."
|
||||
"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.\n\n - Tests replaced bindings:\n - Texture usages via bindings replaced by another setBindGroup() upon the same bindGroup index\n in current scope should be tracked.\n\n - Test texture usages in bundle:\n - Texture usages in bundle should be tracked if that bundle is executed in the current scope."
|
||||
},
|
||||
{
|
||||
"file": [
|
||||
|
|
|
@ -32,7 +32,10 @@ export function getTextureCopyLayout(format, dimension, size, options = kDefault
|
|||
|
||||
const { blockWidth, blockHeight, bytesPerBlock } = kSizedTextureFormatInfo[format];
|
||||
|
||||
assert(isAligned(mipSize[0], blockWidth));
|
||||
// We align mipSize to be the physical size of the texture subresource.
|
||||
mipSize[0] = align(mipSize[0], blockWidth);
|
||||
mipSize[1] = align(mipSize[1], blockHeight);
|
||||
|
||||
const minBytesPerRow = (mipSize[0] / blockWidth) * bytesPerBlock;
|
||||
const alignedMinBytesPerRow = align(minBytesPerRow, kBytesPerRowAlignment);
|
||||
if (bytesPerRow !== undefined) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue