Skip to content
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

Fix the validation for vertex limits for regular render passes #5156

Merged
merged 2 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Bottom level categories:
#### General
- Fix `panic!` when dropping `Instance` without `InstanceFlags::VALIDATION`. By @hakolao in [#5134](https://github.com/gfx-rs/wgpu/pull/5134)
- Fix `serde` feature not compiling for `wgpu-types`. By @KirmesBude in [#5149](https://github.com/gfx-rs/wgpu/pull/5149)
- Fix the validation of vertex and index ranges. By @nical in [#5144](https://github.com/gfx-rs/wgpu/pull/5144) and [#5156](https://github.com/gfx-rs/wgpu/pull/5156)

#### WGL

Expand Down
29 changes: 22 additions & 7 deletions wgpu-core/src/command/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,18 +378,33 @@ struct VertexState {

impl VertexState {
fn update_limits(&mut self) {
// TODO: This isn't entirely spec-compliant.
// We currently require that the buffer range can fit `stride` * count bytes.
// The spec, however, lets a buffer be a bit smaller as long as the size of the
// last element fits in it (the last element can be smaller than the stride between
// elements).
// Implements the validation from https://gpuweb.github.io/gpuweb/#dom-gpurendercommandsmixin-draw
// Except that the formula is shuffled to extract the number of vertices in order
// to carry the bulk of the computation when changing states intead of when producing
// draws. Draw calls tend to happen at a higher frequency. Here we determine vertex
// limits that can be cheaply checked for each draw call.
self.vertex_limit = u32::MAX as u64;
self.instance_limit = u32::MAX as u64;
for (idx, vbs) in self.inputs.iter().enumerate() {
if vbs.step.stride == 0 || !vbs.bound {
if !vbs.bound {
continue;
}
let limit = vbs.total_size / vbs.step.stride;

let limit = if vbs.total_size < vbs.step.last_stride {
// The buffer cannot fit the last vertex.
0
} else {
if vbs.step.stride == 0 {
// We already checked that the last stride fits, the same
// vertex will be repeated so this slot can accomodate any number of
// vertices.
continue;
}

// The general case.
(vbs.total_size - vbs.step.last_stride) / vbs.step.stride + 1
};

match vbs.step.mode {
VertexStepMode::Vertex => {
if limit < self.vertex_limit {
Expand Down