mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-26 16:53:48 +00:00
hal/gles: fix dirty vertex buffers that are unused
This commit is contained in:
parent
36ce638381
commit
9219489894
@ -28,6 +28,7 @@ pub(super) struct State {
|
|||||||
has_pass_label: bool,
|
has_pass_label: bool,
|
||||||
instance_vbuf_mask: usize,
|
instance_vbuf_mask: usize,
|
||||||
dirty_vbuf_mask: usize,
|
dirty_vbuf_mask: usize,
|
||||||
|
active_first_instance: u32,
|
||||||
push_offset_to_uniform: ArrayVec<super::UniformDesc, { super::MAX_PUSH_CONSTANTS }>,
|
push_offset_to_uniform: ArrayVec<super::UniformDesc, { super::MAX_PUSH_CONSTANTS }>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,34 +92,44 @@ impl super::CommandEncoder {
|
|||||||
.private_caps
|
.private_caps
|
||||||
.contains(super::PrivateCapabilities::VERTEX_BUFFER_LAYOUT)
|
.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 {
|
if self.state.dirty_vbuf_mask & (1 << index) == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let vb = vb.as_ref().unwrap();
|
let (buffer_desc, vb) = match *pair {
|
||||||
let instance_offset = match vb_desc.step {
|
// Not all dirty bindings are necessarily filled. Some may be unused.
|
||||||
wgt::VertexStepMode::Vertex => 0,
|
(_, None) => continue,
|
||||||
wgt::VertexStepMode::Instance => first_instance * vb_desc.stride,
|
(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 {
|
self.cmd_buffer.commands.push(C::SetVertexBuffer {
|
||||||
index: index as u32,
|
index: index as u32,
|
||||||
buffer: super::BufferBinding {
|
buffer: super::BufferBinding {
|
||||||
raw: vb.raw,
|
raw: vb.raw,
|
||||||
offset: vb.offset + instance_offset as wgt::BufferAddress,
|
offset: vb.offset + instance_offset as wgt::BufferAddress,
|
||||||
},
|
},
|
||||||
buffer_desc: vb_desc.clone(),
|
buffer_desc,
|
||||||
});
|
});
|
||||||
|
self.state.dirty_vbuf_mask ^= 1 << index;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let mut vbuf_mask = 0;
|
||||||
for attribute in self.state.vertex_attributes.iter() {
|
for attribute in self.state.vertex_attributes.iter() {
|
||||||
if self.state.dirty_vbuf_mask & (1 << attribute.buffer_index) == 0 {
|
if self.state.dirty_vbuf_mask & (1 << attribute.buffer_index) == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (buffer_desc, buffer) =
|
let (buffer_desc, vb) =
|
||||||
self.state.vertex_buffers[attribute.buffer_index as usize].clone();
|
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 mut attribute_desc = attribute.clone();
|
||||||
let vb = buffer.unwrap();
|
|
||||||
attribute_desc.offset += vb.offset as u32;
|
attribute_desc.offset += vb.offset as u32;
|
||||||
if buffer_desc.step == wgt::VertexStepMode::Instance {
|
if buffer_desc.step == wgt::VertexStepMode::Instance {
|
||||||
attribute_desc.offset += buffer_desc.stride * first_instance;
|
attribute_desc.offset += buffer_desc.stride * first_instance;
|
||||||
@ -129,7 +140,9 @@ impl super::CommandEncoder {
|
|||||||
buffer_desc,
|
buffer_desc,
|
||||||
attribute_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) {
|
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.dirty_vbuf_mask |= self.state.instance_vbuf_mask;
|
||||||
|
self.state.active_first_instance = first_instance;
|
||||||
}
|
}
|
||||||
if self.state.dirty_vbuf_mask != 0 {
|
if self.state.dirty_vbuf_mask != 0 {
|
||||||
self.rebind_vertex_data(first_instance);
|
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.instance_vbuf_mask = 0;
|
||||||
self.state.dirty_vbuf_mask = 0;
|
self.state.dirty_vbuf_mask = 0;
|
||||||
|
self.state.active_first_instance = 0;
|
||||||
self.state.color_targets.clear();
|
self.state.color_targets.clear();
|
||||||
self.state.vertex_attributes.clear();
|
self.state.vertex_attributes.clear();
|
||||||
self.state.primitive = super::PrimitiveState::default();
|
self.state.primitive = super::PrimitiveState::default();
|
||||||
|
Loading…
Reference in New Issue
Block a user