hal/gles: fix dirty vertex buffers that are unused

This commit is contained in:
Dzmitry Malyshau 2022-01-28 00:54:41 -05:00
parent 36ce638381
commit 9219489894

View File

@ -28,6 +28,7 @@ pub(super) struct State {
has_pass_label: bool,
instance_vbuf_mask: usize,
dirty_vbuf_mask: usize,
active_first_instance: u32,
push_offset_to_uniform: ArrayVec<super::UniformDesc, { super::MAX_PUSH_CONSTANTS }>,
}
@ -91,34 +92,44 @@ impl super::CommandEncoder {
.private_caps
.contains(super::PrivateCapabilities::VERTEX_BUFFER_LAYOUT)
{
for (index, &(ref vb_desc, ref vb)) in self.state.vertex_buffers.iter().enumerate() {
for (index, pair) in self.state.vertex_buffers.iter().enumerate() {
if self.state.dirty_vbuf_mask & (1 << index) == 0 {
continue;
}
let vb = vb.as_ref().unwrap();
let instance_offset = match vb_desc.step {
wgt::VertexStepMode::Vertex => 0,
wgt::VertexStepMode::Instance => first_instance * vb_desc.stride,
let (buffer_desc, vb) = match *pair {
// Not all dirty bindings are necessarily filled. Some may be unused.
(_, None) => continue,
(ref vb_desc, Some(ref vb)) => (vb_desc.clone(), vb),
};
let instance_offset = match buffer_desc.step {
wgt::VertexStepMode::Vertex => 0,
wgt::VertexStepMode::Instance => first_instance * buffer_desc.stride,
};
self.cmd_buffer.commands.push(C::SetVertexBuffer {
index: index as u32,
buffer: super::BufferBinding {
raw: vb.raw,
offset: vb.offset + instance_offset as wgt::BufferAddress,
},
buffer_desc: vb_desc.clone(),
buffer_desc,
});
self.state.dirty_vbuf_mask ^= 1 << index;
}
} else {
let mut vbuf_mask = 0;
for attribute in self.state.vertex_attributes.iter() {
if self.state.dirty_vbuf_mask & (1 << attribute.buffer_index) == 0 {
continue;
}
let (buffer_desc, buffer) =
self.state.vertex_buffers[attribute.buffer_index as usize].clone();
let (buffer_desc, vb) =
match self.state.vertex_buffers[attribute.buffer_index as usize] {
// Not all dirty bindings are necessarily filled. Some may be unused.
(_, None) => continue,
(ref vb_desc, Some(ref vb)) => (vb_desc.clone(), vb),
};
let mut attribute_desc = attribute.clone();
let vb = buffer.unwrap();
attribute_desc.offset += vb.offset as u32;
if buffer_desc.step == wgt::VertexStepMode::Instance {
attribute_desc.offset += buffer_desc.stride * first_instance;
@ -129,7 +140,9 @@ impl super::CommandEncoder {
buffer_desc,
attribute_desc,
});
vbuf_mask |= 1 << attribute.buffer_index;
}
self.state.dirty_vbuf_mask ^= vbuf_mask;
}
}
@ -151,13 +164,13 @@ impl super::CommandEncoder {
}
fn prepare_draw(&mut self, first_instance: u32) {
if first_instance != 0 {
if first_instance != self.state.active_first_instance {
// rebind all per-instance buffers on first-instance change
self.state.dirty_vbuf_mask |= self.state.instance_vbuf_mask;
self.state.active_first_instance = first_instance;
}
if self.state.dirty_vbuf_mask != 0 {
self.rebind_vertex_data(first_instance);
let vertex_rate_mask = self.state.dirty_vbuf_mask & !self.state.instance_vbuf_mask;
self.state.dirty_vbuf_mask ^= vertex_rate_mask;
}
}
@ -539,6 +552,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
}
self.state.instance_vbuf_mask = 0;
self.state.dirty_vbuf_mask = 0;
self.state.active_first_instance = 0;
self.state.color_targets.clear();
self.state.vertex_attributes.clear();
self.state.primitive = super::PrimitiveState::default();