Improve vertex state error messages

This commit is contained in:
Connor Fitzgerald
2020-12-21 17:28:41 -05:00
parent 94579d8125
commit 1da153f3bd
3 changed files with 77 additions and 23 deletions

View File

@@ -313,20 +313,22 @@ impl RenderBundleEncoder {
first_instance,
} => {
let scope = PassErrorScope::Draw;
let (vertex_limit, instance_limit) = state.vertex_limits();
let vertex_limits = state.vertex_limits();
let last_vertex = first_vertex + vertex_count;
if last_vertex > vertex_limit {
if last_vertex > vertex_limits.vertex_limit {
return Err(DrawError::VertexBeyondLimit {
last_vertex,
vertex_limit,
vertex_limit: vertex_limits.vertex_limit,
slot: vertex_limits.vertex_limit_slot,
})
.map_pass_err(scope);
}
let last_instance = first_instance + instance_count;
if last_instance > instance_limit {
if last_instance > vertex_limits.instance_limit {
return Err(DrawError::InstanceBeyondLimit {
last_instance,
instance_limit,
instance_limit: vertex_limits.instance_limit,
slot: vertex_limits.instance_limit_slot,
})
.map_pass_err(scope);
}
@@ -343,7 +345,7 @@ impl RenderBundleEncoder {
} => {
let scope = PassErrorScope::DrawIndexed;
//TODO: validate that base_vertex + max_index() is within the provided range
let (_, instance_limit) = state.vertex_limits();
let vertex_limits = state.vertex_limits();
let index_limit = state.index.limit();
let last_index = first_index + index_count;
if last_index > index_limit {
@@ -354,10 +356,11 @@ impl RenderBundleEncoder {
.map_pass_err(scope);
}
let last_instance = first_instance + instance_count;
if last_instance > instance_limit {
if last_instance > vertex_limits.instance_limit {
return Err(DrawError::InstanceBeyondLimit {
last_instance,
instance_limit,
instance_limit: vertex_limits.instance_limit,
slot: vertex_limits.instance_limit_slot,
})
.map_pass_err(scope);
}
@@ -855,6 +858,18 @@ impl PushConstantState {
}
}
#[derive(Debug)]
struct VertexLimitState {
/// Length of the shortest vertex rate vertex buffer
vertex_limit: u32,
/// Buffer slot which the shortest vertex rate vertex buffer is bound to
vertex_limit_slot: u32,
/// Length of the shortest instance rate vertex buffer
instance_limit: u32,
/// Buffer slot which the shortest instance rate vertex buffer is bound to
instance_limit_slot: u32,
}
#[derive(Debug)]
struct State {
trackers: TrackerSet,
@@ -869,20 +884,34 @@ struct State {
}
impl State {
fn vertex_limits(&self) -> (u32, u32) {
let mut vertex_limit = !0;
let mut instance_limit = !0;
for vbs in &self.vertex {
fn vertex_limits(&self) -> VertexLimitState {
let mut vert_state = VertexLimitState {
vertex_limit: u32::MAX,
vertex_limit_slot: 0,
instance_limit: u32::MAX,
instance_limit_slot: 0,
};
for (idx, vbs) in self.vertex.iter().enumerate() {
if vbs.stride == 0 {
continue;
}
let limit = ((vbs.range.end - vbs.range.start) / vbs.stride) as u32;
match vbs.rate {
wgt::InputStepMode::Vertex => vertex_limit = vertex_limit.min(limit),
wgt::InputStepMode::Instance => instance_limit = instance_limit.min(limit),
wgt::InputStepMode::Vertex => {
if limit < vert_state.vertex_limit {
vert_state.vertex_limit = limit;
vert_state.vertex_limit_slot = idx as _;
}
}
wgt::InputStepMode::Instance => {
if limit < vert_state.instance_limit {
vert_state.instance_limit = limit;
vert_state.instance_limit_slot = idx as _;
}
}
}
}
(vertex_limit, instance_limit)
vert_state
}
fn invalidate_group_from(&mut self, slot: usize) {

View File

@@ -36,12 +36,17 @@ pub enum DrawError {
//expected: BindGroupLayoutId,
//provided: Option<(BindGroupLayoutId, BindGroupId)>,
},
#[error("vertex {last_vertex} extends beyond limit {vertex_limit}. Did you bind the correct `Vertex` step-rate vertex buffer?")]
VertexBeyondLimit { last_vertex: u32, vertex_limit: u32 },
#[error("instance {last_instance} extends beyond limit {instance_limit}. Did you bind the correct `Instance` step-rate vertex buffer?")]
#[error("vertex {last_vertex} extends beyond limit {vertex_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Vertex` step-rate vertex buffer?")]
VertexBeyondLimit {
last_vertex: u32,
vertex_limit: u32,
slot: u32,
},
#[error("instance {last_instance} extends beyond limit {instance_limit} imposed by the buffer in slot {slot}. Did you bind the correct `Instance` step-rate vertex buffer?")]
InstanceBeyondLimit {
last_instance: u32,
instance_limit: u32,
slot: u32,
},
#[error("index {last_index} extends beyond limit {index_limit}. Did you bind the correct index buffer?")]
IndexBeyondLimit { last_index: u32, index_limit: u32 },

View File

@@ -274,23 +274,40 @@ impl VertexBufferState {
#[derive(Debug, Default)]
struct VertexState {
inputs: ArrayVec<[VertexBufferState; MAX_VERTEX_BUFFERS]>,
/// Length of the shortest vertex rate vertex buffer
vertex_limit: u32,
/// Buffer slot which the shortest vertex rate vertex buffer is bound to
vertex_limit_slot: u32,
/// Length of the shortest instance rate vertex buffer
instance_limit: u32,
/// Buffer slot which the shortest instance rate vertex buffer is bound to
instance_limit_slot: u32,
/// Total amount of buffers required by the pipeline.
buffers_required: u32,
}
impl VertexState {
fn update_limits(&mut self) {
self.vertex_limit = !0;
self.instance_limit = !0;
for vbs in &self.inputs {
self.vertex_limit = u32::MAX;
self.instance_limit = u32::MAX;
for (idx, vbs) in self.inputs.iter().enumerate() {
if vbs.stride == 0 || !vbs.bound {
continue;
}
let limit = (vbs.total_size / vbs.stride) as u32;
match vbs.rate {
InputStepMode::Vertex => self.vertex_limit = self.vertex_limit.min(limit),
InputStepMode::Instance => self.instance_limit = self.instance_limit.min(limit),
InputStepMode::Vertex => {
if limit < self.vertex_limit {
self.vertex_limit = limit;
self.vertex_limit_slot = idx as _;
}
}
InputStepMode::Instance => {
if limit < self.instance_limit {
self.instance_limit = limit;
self.instance_limit_slot = idx as _;
}
}
}
}
}
@@ -1427,6 +1444,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return Err(DrawError::VertexBeyondLimit {
last_vertex,
vertex_limit,
slot: state.vertex.vertex_limit_slot,
})
.map_pass_err(scope);
}
@@ -1436,6 +1454,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return Err(DrawError::InstanceBeyondLimit {
last_instance,
instance_limit,
slot: state.vertex.instance_limit_slot,
})
.map_pass_err(scope);
}
@@ -1473,6 +1492,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return Err(DrawError::InstanceBeyondLimit {
last_instance,
instance_limit,
slot: state.vertex.instance_limit_slot,
})
.map_pass_err(scope);
}