Expand transform buffers when they're full
This commit is contained in:
parent
ec960b8f94
commit
f339d048b2
|
@ -57,12 +57,16 @@ struct TransformBufferIndices {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TransformBuffers {
|
struct TransformBuffers {
|
||||||
|
//transform_layout: wgpu::BindGroupLayout,
|
||||||
/// A vector storing the EntityId and
|
/// A vector storing the EntityId and
|
||||||
just_updated: HashMap<EntityId, TransformBufferIndices>,
|
just_updated: HashMap<EntityId, TransformBufferIndices>,
|
||||||
not_updated: HashMap<EntityId, TransformBufferIndices>,
|
not_updated: HashMap<EntityId, TransformBufferIndices>,
|
||||||
dead_indices: VecDeque<TransformBufferIndices>,
|
dead_indices: VecDeque<TransformBufferIndices>,
|
||||||
next_indices: 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 {
|
impl TransformBuffers {
|
||||||
|
@ -72,25 +76,31 @@ impl TransformBuffers {
|
||||||
.expect("Use 'insert_entity' for new entities");
|
.expect("Use 'insert_entity' for new entities");
|
||||||
self.just_updated.insert(entity, indices);
|
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));
|
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.
|
/// 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 {
|
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
|
// get a dead index, or create a new one
|
||||||
let indices = if let Some(index) = self.dead_indices.pop_front() {
|
let (indices, buffer) = if let Some(index) = self.dead_indices.pop_front() {
|
||||||
index
|
let (_, buffer, _) = self.buffer_bindgroups.get(index.buffer_index).unwrap();
|
||||||
|
(index, &*buffer)
|
||||||
} else {
|
} else {
|
||||||
// TODO: Create new buffer if this one is full
|
|
||||||
let indices = &mut self.next_indices;
|
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;
|
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));
|
queue.write_buffer(buffer, Self::get_offset_for(limits, indices), bytemuck::bytes_of(&transform));
|
||||||
|
|
||||||
self.just_updated.insert(entity, indices);
|
self.just_updated.insert(entity, indices);
|
||||||
|
@ -112,6 +122,15 @@ impl TransformBuffers {
|
||||||
fn get_offset_for(limits: &Limits, indices: TransformBufferIndices) -> u64 {
|
fn get_offset_for(limits: &Limits, indices: TransformBufferIndices) -> u64 {
|
||||||
indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as 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 {
|
pub struct BasicRenderer {
|
||||||
|
@ -280,7 +299,8 @@ impl BasicRenderer {
|
||||||
// create create the transform buffer storage
|
// create create the transform buffer storage
|
||||||
//let transforms = AVec::new(render_limits.min_uniform_buffer_offset_alignment as usize);
|
//let transforms = AVec::new(render_limits.min_uniform_buffer_offset_alignment as usize);
|
||||||
let transform_buffers = TransformBuffers {
|
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(),
|
just_updated: HashMap::new(),
|
||||||
not_updated: HashMap::new(),
|
not_updated: HashMap::new(),
|
||||||
dead_indices: VecDeque::new(),
|
dead_indices: VecDeque::new(),
|
||||||
|
@ -438,6 +458,42 @@ impl BasicRenderer {
|
||||||
transform_index: transform_indices
|
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 {
|
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);
|
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None);
|
||||||
self.render_jobs.push_back(job);
|
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,
|
let indices = self.transform_buffers.insert_entity(&self.queue, &self.render_limits,
|
||||||
entity, transform.transform.calculate_mat4());
|
entity, transform.transform.calculate_mat4());
|
||||||
|
|
||||||
|
// create the mesh's buffers
|
||||||
let buffers = self.create_model_buffers(model, indices);
|
let buffers = self.create_model_buffers(model, indices);
|
||||||
self.buffer_storage.insert(entity, buffers);
|
self.buffer_storage.insert(entity, buffers);
|
||||||
} else {
|
} else {
|
||||||
|
// update entity transforms
|
||||||
self.transform_buffers.update_entity(&self.queue, &self.render_limits,
|
self.transform_buffers.update_entity(&self.queue, &self.render_limits,
|
||||||
entity, transform.transform.calculate_mat4());
|
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.
|
// Get the bindgroup for job's transform and bind to it using an offset.
|
||||||
let transform_indices = buffers.transform_index;
|
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);
|
let offset = TransformBuffers::get_offset_for(&self.render_limits, transform_indices);
|
||||||
render_pass.set_bind_group(1, bindgroup, &[ offset as u32, ]);
|
render_pass.set_bind_group(1, bindgroup, &[ offset as u32, ]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue