buffer_view CTS#4652
Conversation
* Validation of buffer type and related builtin functions
* Tests for * bufferLength * bufferView * bufferArrayView
|
Results for build job (at dd3cfe0): +webgpu:api,validation,dispatch:shader_required_buffer_size:* - 19 cases, 76 subcases (~4/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:array_length:* - 78 cases, 832 subcases (~11/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:array_length,functions:* - 78 cases, 1170 subcases (~15/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:read_layout:* - 35 cases, 604 subcases (~17/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:write_layout:* - 35 cases, 604 subcases (~17/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:read:* - 4 cases, 744 subcases (~186/case)
+webgpu:shader,execution,expression,call,builtin,bufferArrayView:write:* - 4 cases, 1224 subcases (~306/case)
+webgpu:shader,execution,expression,call,builtin,bufferLength:sized_buffer:* - 5 cases, 120 subcases (~24/case)
+webgpu:shader,execution,expression,call,builtin,bufferLength:unsized_buffer:* - 5 cases, 80 subcases (~16/case)
+webgpu:shader,execution,expression,call,builtin,bufferLength:max_size_buffer:* - 6 cases, 6 subcases (~1/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:array_length:* - 78 cases, 832 subcases (~11/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:array_length,functions:* - 78 cases, 1542 subcases (~20/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:read_layout:* - 35 cases, 604 subcases (~17/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:write_layout:* - 35 cases, 604 subcases (~17/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:read:* - 4 cases, 856 subcases (~214/case)
+webgpu:shader,execution,expression,call,builtin,bufferView:write:* - 4 cases, 1224 subcases (~306/case)
-webgpu:shader,validation,decl,let:type:* - 21 cases, 21 subcases (~1/case)
-webgpu:shader,validation,decl,let:initializer:* - 10 cases, 10 subcases (~1/case)
[snip - full report in action logs]
-TOTAL: 281361 cases, 2323132 subcases
+TOTAL: 282684 cases, 2338877 subcases |
| }); | ||
|
|
||
| const buffer = t.createBufferTracked({ | ||
| size: t.params.valid ? testcase.size : testcase.size - 4, |
There was a problem hiding this comment.
I had to look up why this uses "- 4".
It comes from the fact that the buffer binding size in createBindGroup must be a multiple of 4. That's just a familiarity thing for me.
No request for change.
| binding_type: 'read-only-storage', | ||
| requires: ['buffer_view'], | ||
| }, | ||
| }; |
There was a problem hiding this comment.
This needs test cases for:
- offset is an override expression
- with initializer
- with pipeline-time-supplied initializer value
- size parameter is an override expression.
- if so, then use that size.
- otherwise use MinTypeSize. (See my question / comment at https://github.com/gpuweb/gpuweb/pull/6291/changes#r3469837734 )
There was a problem hiding this comment.
uh, I think my request is nonsense because the size param has to be a const-expression. (!)
There was a problem hiding this comment.
Alan reminded me that the case here is using an override expression for the function arguments; not for the declarations of the buffers
| requires: ['buffer_view'], | ||
| }, | ||
| }; | ||
|
|
There was a problem hiding this comment.
Also, the bufferArrayView cases less rich than the bufferView cases.
Interesting ones missing for bufferArrayView
- compute max value across multiple uses in a shader
- multiple uses in the shader, but only pay attention to the ones statically used by the shader in the pipeline
| ): boolean { | ||
| if (size === 0) { | ||
| // bufferView case | ||
| return offset + (type.arrayOffset ?? 0) + type.stride < bufferSize; |
There was a problem hiding this comment.
Should this be less-than-or-equal?
Also on line 45.
| } | ||
| } | ||
|
|
||
| export function calculateArrayLength( |
There was a problem hiding this comment.
Worth saying this returns the element count. That's a bit less ambiguous
| decls: `@group(0) @binding(0) var<storage> b : buffer;`, | ||
| }, | ||
| buffer_sized: { | ||
| code: `let x = buffer<128> = b;`, |
| code: `let x : ptr<uniform, buffer<64>> = &b;`, | ||
| valid: false, | ||
| decls: `@group(0) @binding(0) var<uniform> b : buffer<128>;`, | ||
| }, |
There was a problem hiding this comment.
another case:
- workgroup sized buffer with override size, assign its address to ptr-workgr-sized-buffer but mismatched override identifier.
dneto0
left a comment
There was a problem hiding this comment.
Finished reviewing. This is a very impressive suite. Thanks for creating it!
I also suggest adding additional validation test cases for arrayLength, i.e. in src/webgpu/shader/validation/expression/call/arrayLength. Sized and unsized buffer types should be tested.
| code: `const x = 0; alias T = buffer<x>;`, | ||
| valid: false, | ||
| }, | ||
| const_functio: { |
| expected = t.params.aspace === 'workgroup'; | ||
| } | ||
| t.expectCompileResult(expected, wgsl); | ||
| }); |
There was a problem hiding this comment.
Could add a case testing pointer types.
alias PT = ptr<address_space, T>;
(with shenanigans for read-only/read_write access modes)
| binding_type: 'read-only-storage', | ||
| requires: ['buffer_view'], | ||
| }, | ||
| }; |
There was a problem hiding this comment.
Alan reminded me that the case here is using an override expression for the function arguments; not for the declarations of the buffers
| let mvar = ''; | ||
| let fvar = ''; | ||
| switch (t.params.aspace) { | ||
| case 'function': |
There was a problem hiding this comment.
now that immedates have landed, please add that case. Should always fail, so no need to skip if immediates are not supported. :-)
| matches: ['ptrWorkgroupOverrideExpr'], | ||
| needsUnrestrictedPointerParameters: true, | ||
| }, | ||
|
|
There was a problem hiding this comment.
this is a glorious set of tests. I love how explicit these are.
| t.expectCompileResult(type === Type.u32, wgsl); | ||
| }); | ||
|
|
||
| g.test('data_type') |
There was a problem hiding this comment.
Please add a tests:
- calling bufferLength on other types: e .g. scalar, array, ptr-to-scalar, ptr-to-array. (don't have to do too much here)
- wrong number of parameters: 0, and 2.
| t.params.bufferSize / 2 | ||
| }>>, gidx : u32) -> u32 { | ||
| return unsizedLength(p, gidx); | ||
| } |
There was a problem hiding this comment.
This is a great test.
Suggest another scenario:
- call to sized-N param that calls into sized-N/2 param --> yields N/2
| fn main() { | ||
| let val = ${testcase.f16 ? 'f16' : testcase.f32 ? 'f32' : 'u32'}(in); | ||
| let ptr = ${call_expr}; | ||
| (*${t.params.assign === 'call' ? call_expr : 'ptr'})${testcase.access} = val; |
There was a problem hiding this comment.
Really great to see both 'let' and 'call' variations here!
| } | ||
| `; | ||
|
|
||
| runReadWriteTest(false, t, wgsl, ele_ty, ty, t.params.aspace, t.params.offset, bufferSize); |
There was a problem hiding this comment.
Very impressed and happy with the creation and use of readWriteTest to clarify so much of the mechanics!
| t.params.bufferSize / 2 | ||
| }>>, gidx : u32) -> u32 { | ||
| return unsizedLength(p, gidx); | ||
| } |
There was a problem hiding this comment.
Similar to arrayView, suggest another scenario:
- call to sized-N param that calls into sized-N/2 param --> yields N/2
buffer_view validation and execution CTS tests.
Issue: #
Requirements for PR author:
.unimplemented()./** documented */and new helper files are found inhelper_index.txt.Requirements for reviewer sign-off:
When landing this PR, be sure to make any necessary issue status updates.