-
Notifications
You must be signed in to change notification settings - Fork 103
Add immediate size validation cases for pipeline creation #4573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add immediate size validation cases for pipeline creation #4573
Conversation
|
Results for build job (at 264b3a4): +webgpu:api,validation,compute_pipeline:pipeline_creation_immediate_size_mismatch:* - 12 cases, 12 subcases (~1/case)
-webgpu:api,validation,render_pipeline,misc:external_texture:* - 1 cases, 1 subcases (~1/case)
+webgpu:api,validation,render_pipeline,misc:external_texture:* - 2 cases, 2 subcases (~1/case)
+webgpu:api,validation,render_pipeline,misc:pipeline_creation_immediate_size_mismatch:* - 18 cases, 18 subcases (~1/case)
-TOTAL: 285993 cases, 2344970 subcases
+TOTAL: 286024 cases, 2345001 subcases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds validation test cases for immediate data size checks during pipeline creation. The tests verify that pipeline creation fails when shaders use immediate data larger than the immediateSize specified in the pipeline layout or larger than maxImmediateSize when using automatic layout.
Changes:
- Added helper function
supportsImmediateDatato check browser support for immediate data - Added
pipeline_creation_immediate_size_mismatchtest for compute pipelines - Added
pipeline_creation_immediate_size_mismatchtest for render pipelines
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| src/common/util/util.ts | Added supportsImmediateData helper function to detect immediate data feature support |
| src/webgpu/api/validation/compute_pipeline.spec.ts | Added test to validate immediate size checks during compute pipeline creation |
| src/webgpu/api/validation/render_pipeline/misc.spec.ts | Added test to validate immediate size checks during render pipeline creation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cf15532 to
2127eae
Compare
ab59c0d to
7edddc0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add cases to validate immediate size checks during both compute and render pipeline creation.
7edddc0 to
438463e
Compare
|
@shaoboyan091 sorry I've been slow at picking up these re-reviews. To make it a bit easier could you please "resolve" any copilot review comments before sending for review? (either by addressing them or by ignoring them) Having them open makes it harder to review the PR, but I've also noticed that it generates some useful suggestions so I don't want to necessarily ignore them either. |
|
@kainino0x Sure, will do. Thanks! |
kainino0x
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One major comment, and a few nits
| assert(t.device.limits.maxImmediateSize !== undefined); | ||
| const maxImmediateSize = t.device.limits.maxImmediateSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
| assert(t.device.limits.maxImmediateSize !== undefined); | |
| const maxImmediateSize = t.device.limits.maxImmediateSize; | |
| const maxImmediateSize = t.device.limits.maxImmediateSize; | |
| assert(maxImmediateSize !== undefined); |
| .params(u => { | ||
| const kNumericCases = [ | ||
| { shaderSize: 16, layoutSize: 16 }, // Equal | ||
| { shaderSize: 12, layoutSize: 16 }, // Shader smaller | ||
| { shaderSize: 20, layoutSize: 16 }, // Shader larger (small diff) | ||
| { shaderSize: 32, layoutSize: 16 }, // Shader larger | ||
| ] as const; | ||
| const kMaxLimitsCases = [ | ||
| { shaderSize: 'max', layoutSize: 'auto' }, // Shader equal to limit (auto layout) | ||
| { shaderSize: 'exceedLimits', layoutSize: 'auto' }, // Shader larger than limit (auto layout) | ||
| ] as const; | ||
| return u | ||
| .combine('isAsync', [true, false]) | ||
| .combineWithParams([...kNumericCases, ...kMaxLimitsCases] as const); | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This pattern is interesting, but I think I find it slightly harder to read than the more typical pattern that makes it clearer that these two arrays will be part of the same combineWithParams call:
.params(u => u
.combine('isAsync', [true, false])
.combineWithParams([
// Numeric cases
/* ... */
// Max-limit cases
/* ... */
])
Though the header comments aren't really necessary because it's already obvious what it means.
| .params(u => { | |
| const kNumericCases = [ | |
| { shaderSize: 16, layoutSize: 16 }, // Equal | |
| { shaderSize: 12, layoutSize: 16 }, // Shader smaller | |
| { shaderSize: 20, layoutSize: 16 }, // Shader larger (small diff) | |
| { shaderSize: 32, layoutSize: 16 }, // Shader larger | |
| ] as const; | |
| const kMaxLimitsCases = [ | |
| { shaderSize: 'max', layoutSize: 'auto' }, // Shader equal to limit (auto layout) | |
| { shaderSize: 'exceedLimits', layoutSize: 'auto' }, // Shader larger than limit (auto layout) | |
| ] as const; | |
| return u | |
| .combine('isAsync', [true, false]) | |
| .combineWithParams([...kNumericCases, ...kMaxLimitsCases] as const); | |
| }) | |
| .params(u => u | |
| .combine('isAsync', [true, false]) | |
| .combineWithParams([ | |
| { shaderSize: 16, layoutSize: 16 }, // Equal | |
| { shaderSize: 12, layoutSize: 16 }, // Shader smaller | |
| { shaderSize: 20, layoutSize: 16 }, // Shader larger (small diff) | |
| { shaderSize: 32, layoutSize: 16 }, // Shader larger | |
| { shaderSize: 'max', layoutSize: 'auto' }, // Shader equal to limit (auto layout) | |
| { shaderSize: 'exceedLimits', layoutSize: 'auto' }, // Shader larger than limit (auto layout) | |
| ] as const) | |
| ) |
| } else if (shaderSize === 'exceedLimits') { | ||
| actualShaderSize = validSize + 4; | ||
| } else { | ||
| actualShaderSize = shaderSize as number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think the type narrowing makes this cast unnecessary
| actualShaderSize = shaderSize as number; | |
| actualShaderSize = shaderSize; |
| } | ||
|
|
||
| const numFields = actualShaderSize / 4; | ||
| const fields = Array.from({ length: numFields }, (_, i) => `m${i}: u32`).join(', '); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use range from src/common/util/util.ts
| { vertexSize: 'exceedLimits', fragmentSize: 0, layoutSize: 'auto' }, // Vertex > Limit | ||
| { vertexSize: 0, fragmentSize: 'exceedLimits', layoutSize: 'auto' }, // Fragment > Limit | ||
| ] as const; | ||
| return u |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same suggestion here
| assert(t.device.limits.maxImmediateSize !== undefined); | ||
| const maxImmediateSize = t.device.limits.maxImmediateSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
| return `@fragment fn main_fragment() -> @location(0) vec4<f32> { return vec4<f32>(0.0, 1.0, 0.0, 1.0); }`; | ||
| } | ||
| const numFields = size / 4; | ||
| const fields = Array.from({ length: numFields }, (_, i) => `m${i}: u32`).join(', '); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
| vtu.doCreateRenderPipelineTest(t, isAsync, success, descriptor); | ||
| }); | ||
|
|
||
| g.test('pipeline_creation_immediate_size_mismatch') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The render and compute tests are extremely similar, I would prefer to put them together in the same file (and probably share some code), e.g. api/validation/pipeline/immediates.spec.ts
Not sure how easy this is to do - consider it, but it's not that important.
| // When the shader exceeds the device's maxImmediateSize, the error occurs | ||
| // at shader module creation time, not pipeline creation time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be validated here, if we can avoid it. createShaderModule doesn't know whether a given entry point is going to be used or not. I am pretty sure WebGPU doesn't normally validate features or limits in createShaderModule.
Also, if we do end up allowing arrays, then overrides might be able to change the size of the immediate data, in which case we would have to duplicate the validation in pipeline creation.
| // When the shader exceeds the device's maxImmediateSize, the error occurs | ||
| // at shader module creation time, not pipeline creation time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
Add cases to validate immediate size checks during both compute and render pipeline creation.
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.