Expand transform buffers when they're full
This commit is contained in:
parent
ec960b8f94
commit
f339d048b2
|
@ -57,12 +57,16 @@ struct TransformBufferIndices {
|
|||
}
|
||||
|
||||
struct TransformBuffers {
|
||||
//transform_layout: wgpu::BindGroupLayout,
|
||||
/// A vector storing the EntityId and
|
||||
just_updated: HashMap<EntityId, TransformBufferIndices>,
|
||||
not_updated: HashMap<EntityId, TransformBufferIndices>,
|
||||
dead_indices: VecDeque<TransformBufferIndices>,
|
||||
next_indices: TransformBufferIndices,
|
||||
buffer_bindgroups: Vec<(wgpu::Buffer, wgpu::BindGroup)>,
|
||||
/// (transform count, buffer, bindgroup)
|
||||
buffer_bindgroups: Vec<(usize, wgpu::Buffer, wgpu::BindGroup)>,
|
||||
/// The max amount of transforms in a buffer
|
||||
max_transform_count: usize,
|
||||
}
|
||||
|
||||
impl TransformBuffers {
|
||||
|
@ -72,25 +76,31 @@ impl TransformBuffers {
|
|||
.expect("Use 'insert_entity' for new entities");
|
||||
self.just_updated.insert(entity, indices);
|
||||
|
||||
let (buffer, _) = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
|
||||
let (_, buffer, _) = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
|
||||
queue.write_buffer(buffer, indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as u64, bytemuck::bytes_of(&transform));
|
||||
}
|
||||
|
||||
/// Insert a new entity into the buffer, returns where it was stored.
|
||||
fn insert_entity(&mut self, queue: &wgpu::Queue, limits: &Limits, entity: EntityId, transform: glam::Mat4) -> TransformBufferIndices {
|
||||
// get a dead index, or create a new one
|
||||
let indices = if let Some(index) = self.dead_indices.pop_front() {
|
||||
index
|
||||
let (indices, buffer) = if let Some(index) = self.dead_indices.pop_front() {
|
||||
let (_, buffer, _) = self.buffer_bindgroups.get(index.buffer_index).unwrap();
|
||||
(index, &*buffer)
|
||||
} else {
|
||||
// TODO: Create new buffer if this one is full
|
||||
let indices = &mut self.next_indices;
|
||||
let new = indices.clone();
|
||||
let this_idx = indices.clone();
|
||||
let (count, buffer, _) = self.buffer_bindgroups.get_mut(indices.buffer_index).unwrap();
|
||||
|
||||
if count.clone() >= self.max_transform_count {
|
||||
panic!("Transform buffer is filled and 'next_indices' was not incremented! Was a new buffer created?");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
indices.transform_index += 1;
|
||||
|
||||
new
|
||||
(this_idx, &*buffer)
|
||||
};
|
||||
|
||||
let (buffer, _) = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
|
||||
queue.write_buffer(buffer, Self::get_offset_for(limits, indices), bytemuck::bytes_of(&transform));
|
||||
|
||||
self.just_updated.insert(entity, indices);
|
||||
|
@ -112,6 +122,15 @@ impl TransformBuffers {
|
|||
fn get_offset_for(limits: &Limits, indices: TransformBufferIndices) -> u64 {
|
||||
indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as u64
|
||||
}
|
||||
|
||||
/// Returns whether or not the transform buffers should be expanded
|
||||
fn should_expand(&self) -> bool {
|
||||
if let Some(( count, _, _ )) = self.buffer_bindgroups.last() {
|
||||
count.clone() >= self.max_transform_count
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BasicRenderer {
|
||||
|
@ -280,7 +299,8 @@ impl BasicRenderer {
|
|||
// create create the transform buffer storage
|
||||
//let transforms = AVec::new(render_limits.min_uniform_buffer_offset_alignment as usize);
|
||||
let transform_buffers = TransformBuffers {
|
||||
buffer_bindgroups: vec![( transform_buffer, transform_bind_group )],
|
||||
max_transform_count: (render_limits.max_uniform_buffer_binding_size / mem::size_of::<glam::Mat4>() as u32) as usize,
|
||||
buffer_bindgroups: vec![( 0, transform_buffer, transform_bind_group )],
|
||||
just_updated: HashMap::new(),
|
||||
not_updated: HashMap::new(),
|
||||
dead_indices: VecDeque::new(),
|
||||
|
@ -438,6 +458,42 @@ impl BasicRenderer {
|
|||
transform_index: transform_indices
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_transform_buffers(&mut self) -> TransformBufferIndices {
|
||||
let buffers = &mut self.transform_buffers;
|
||||
|
||||
let transform_buffer = self.device.create_buffer(
|
||||
&wgpu::BufferDescriptor {
|
||||
label: Some(&format!("Transform Buffer {}", buffers.buffer_bindgroups.len())),
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
size: self.render_limits.max_uniform_buffer_binding_size as u64,
|
||||
mapped_at_creation: false,
|
||||
}
|
||||
);
|
||||
|
||||
let stride = self.render_limits.min_uniform_buffer_offset_alignment as usize + mem::size_of::<glam::Mat4>();
|
||||
let transform_bind_group = self.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &self.transform_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(
|
||||
wgpu::BufferBinding {
|
||||
buffer: &transform_buffer,
|
||||
offset: 0,
|
||||
size: Some(NonZeroU64::new(stride as u64).unwrap())
|
||||
}
|
||||
)
|
||||
}
|
||||
],
|
||||
label: Some("transform_bind_group"),
|
||||
});
|
||||
|
||||
let indices = TransformBufferIndices { buffer_index: buffers.buffer_bindgroups.len(), transform_index: 0 };
|
||||
buffers.buffer_bindgroups.push(( 0, transform_buffer, transform_bind_group ));
|
||||
buffers.next_indices = indices;
|
||||
indices
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderer for BasicRenderer {
|
||||
|
@ -448,15 +504,25 @@ impl Renderer for BasicRenderer {
|
|||
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None);
|
||||
self.render_jobs.push_back(job);
|
||||
|
||||
if self.buffer_storage.get(&entity).is_none() {
|
||||
if self.buffer_storage.get(&entity).is_none() { // TODO: Delete dead entites from buffer_storage
|
||||
// check if the transform buffers need to be expanded
|
||||
if self.transform_buffers.should_expand() {
|
||||
self.expand_transform_buffers();
|
||||
}
|
||||
|
||||
// insert transform into buffers
|
||||
let indices = self.transform_buffers.insert_entity(&self.queue, &self.render_limits,
|
||||
entity, transform.transform.calculate_mat4());
|
||||
|
||||
// create the mesh's buffers
|
||||
let buffers = self.create_model_buffers(model, indices);
|
||||
self.buffer_storage.insert(entity, buffers);
|
||||
} else {
|
||||
// update entity transforms
|
||||
self.transform_buffers.update_entity(&self.queue, &self.render_limits,
|
||||
entity, transform.transform.calculate_mat4());
|
||||
|
||||
// TODO: Update model buffers in storage
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,7 +578,7 @@ impl Renderer for BasicRenderer {
|
|||
|
||||
// Get the bindgroup for job's transform and bind to it using an offset.
|
||||
let transform_indices = buffers.transform_index;
|
||||
let (_, bindgroup) = self.transform_buffers.buffer_bindgroups.get(transform_indices.buffer_index).unwrap();
|
||||
let (_, _, bindgroup) = self.transform_buffers.buffer_bindgroups.get(transform_indices.buffer_index).unwrap();
|
||||
let offset = TransformBuffers::get_offset_for(&self.render_limits, transform_indices);
|
||||
render_pass.set_bind_group(1, bindgroup, &[ offset as u32, ]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue