Use an actual render queue instead of a HashMap
This commit is contained in:
parent
645dd93f21
commit
b957414143
|
@ -10,6 +10,7 @@ mkShell rec {
|
|||
trunk
|
||||
valgrind
|
||||
heaptrack
|
||||
mold
|
||||
];
|
||||
buildInputs = [
|
||||
udev alsa-lib vulkan-loader
|
||||
|
|
|
@ -16,6 +16,12 @@ impl Default for Transform {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<glam::Mat4> for Transform {
|
||||
fn into(self) -> glam::Mat4 {
|
||||
self.matrix
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Transform {
|
||||
pub fn new() -> Self {
|
||||
|
@ -28,6 +34,10 @@ impl Transform {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_matrix(&self) -> glam::Mat4 {
|
||||
self.matrix
|
||||
}
|
||||
|
||||
/// Create Transform from scale, rotation (in degrees), and translation
|
||||
pub fn from_scale_rotation_deg_translation(scale: Vec3, mut rotation: Vec3, translation: Vec3) -> Self {
|
||||
rotation.x = angle::degrees_to_radians(rotation.x);
|
||||
|
@ -147,8 +157,6 @@ impl Transform {
|
|||
rot
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn scale(&mut self, scale: Vec3) -> &mut Self {
|
||||
let scale = Mat4::from_scale(scale);
|
||||
self.matrix *= scale;
|
||||
|
|
|
@ -9,12 +9,12 @@ pub struct RenderJob {
|
|||
material: Material,
|
||||
entity: Entity,
|
||||
|
||||
pub transform: Option<Transform>,
|
||||
pub last_transform: Option<Transform>, // TODO: render interpolation
|
||||
transform: Transform,
|
||||
last_transform: Option<Transform>, // TODO: render interpolation
|
||||
}
|
||||
|
||||
impl RenderJob {
|
||||
pub fn new(mesh: Mesh, material: Material, entity: Entity, transform: Option<Transform>, last_transform: Option<Transform>) -> Self {
|
||||
pub fn new(mesh: Mesh, material: Material, entity: Entity, transform: Transform, last_transform: Option<Transform>) -> Self {
|
||||
Self {
|
||||
mesh,
|
||||
material,
|
||||
|
@ -35,4 +35,20 @@ impl RenderJob {
|
|||
pub fn entity(&self)-> Entity {
|
||||
self.entity
|
||||
}
|
||||
|
||||
pub fn transform(&self)-> &Transform {
|
||||
&self.transform
|
||||
}
|
||||
|
||||
pub fn set_transform(&mut self, transform: Transform){
|
||||
self.transform = transform;
|
||||
}
|
||||
|
||||
pub fn last_transform(&self)-> Option<&Transform> {
|
||||
self.last_transform.as_ref()
|
||||
}
|
||||
|
||||
pub fn set_last_transform(&mut self, last_transform: Transform){
|
||||
self.last_transform = Some(last_transform);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::Arc;
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
@ -54,7 +54,7 @@ pub struct BasicRenderer {
|
|||
pub clear_color: wgpu::Color,
|
||||
|
||||
pub render_pipelines: HashMap<u32, Arc<FullRenderPipeline>>,
|
||||
pub render_jobs: HashMap<u32, Vec<RenderJob>>,
|
||||
pub render_jobs: VecDeque<RenderJob>,
|
||||
|
||||
buffer_storage: HashMap<Entity, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||
|
||||
|
@ -248,7 +248,7 @@ impl BasicRenderer {
|
|||
a: 1.0,
|
||||
},
|
||||
render_pipelines: pipelines,
|
||||
render_jobs: HashMap::new(),
|
||||
render_jobs: VecDeque::new(),
|
||||
buffer_storage: HashMap::new(),
|
||||
|
||||
transform_buffer,
|
||||
|
@ -348,22 +348,10 @@ impl BasicRenderer {
|
|||
#[async_trait]
|
||||
impl Renderer for BasicRenderer {
|
||||
async fn prepare(&mut self, main_world: &mut World) {
|
||||
for (entity, (model, transform)) in main_world.query::<(&MeshComponent, Option<&TransformComponent>)>().iter() {
|
||||
let transform = match transform {
|
||||
Some(transform) => {
|
||||
Some(transform.transform)
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform, None);
|
||||
|
||||
// Insert the new job into the queue
|
||||
if let Some(shader_jobs) = self.render_jobs.get_mut(&model.material.shader_id) {
|
||||
shader_jobs.push(job);
|
||||
} else {
|
||||
self.render_jobs.insert(model.material.shader_id, vec![job]);
|
||||
}
|
||||
for (entity, (model, transform)) in main_world.query::<(&MeshComponent, &TransformComponent)>().iter() {
|
||||
// Create the render job and push it to the queue
|
||||
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() {
|
||||
let buffers = self.create_model_buffers(model);
|
||||
|
@ -384,8 +372,6 @@ impl Renderer for BasicRenderer {
|
|||
}
|
||||
|
||||
async fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||
let jobs = &self.render_jobs;
|
||||
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
||||
|
@ -393,8 +379,9 @@ impl Renderer for BasicRenderer {
|
|||
label: Some("Basic Renderer's Encoder")
|
||||
});
|
||||
|
||||
// Loop through all the render pipelines and draw the buffers.
|
||||
for (shader_id, pipeline) in self.render_pipelines.iter() {
|
||||
// Create a new variable scope for the render pass
|
||||
{
|
||||
// There's only one render pass currently
|
||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||
|
@ -408,11 +395,11 @@ impl Renderer for BasicRenderer {
|
|||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
render_pass.set_pipeline(pipeline.get_wgpu_pipeline());
|
||||
// Pop off jobs from the queue as they're being processed
|
||||
while let Some(job) = self.render_jobs.pop_front() {
|
||||
if let Some(pipeline) = self.render_pipelines.get(&job.material().shader_id) {
|
||||
render_pass.set_pipeline(pipeline.get_wgpu_pipeline());
|
||||
|
||||
let pipeline_jobs = jobs.get(shader_id);
|
||||
if let Some(jobs) = pipeline_jobs {
|
||||
for job in jobs.iter() {
|
||||
let mesh = job.mesh();
|
||||
let buffers = self.buffer_storage.get(&job.entity()).unwrap();
|
||||
|
||||
|
@ -420,13 +407,9 @@ impl Renderer for BasicRenderer {
|
|||
render_pass.set_bind_group(0, &tex, &[]);
|
||||
}
|
||||
|
||||
// If the job has a transform, set the uniform to it
|
||||
if let Some(transform) = job.transform {
|
||||
//self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[transform]));
|
||||
render_pass.set_bind_group(1, &self.transform_bind_group, &[]);
|
||||
} else {
|
||||
debug!("//TODO: clear transform uniform if the RenderJob doesn't have a transform.");
|
||||
}
|
||||
// Update transform buffer, and bind to the bind group
|
||||
self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[job.transform().get_matrix()]));
|
||||
render_pass.set_bind_group(1, &self.transform_bind_group, &[]);
|
||||
|
||||
// There will always be a camera (hopefully)
|
||||
render_pass.set_bind_group(2, &self.camera_bind_group, &[]);
|
||||
|
@ -441,18 +424,15 @@ impl Renderer for BasicRenderer {
|
|||
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
|
||||
render_pass.draw(0..mesh.vertices.len() as u32, 0..1);
|
||||
}
|
||||
} else {
|
||||
warn!("Failure to find RenderPipeline with shader id of '{}'!", job.material().shader_id);
|
||||
}
|
||||
|
||||
//pipeline.render(&jobs, &mut render_pass, 0..VERTICES.len() as u32, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
// TODO: Use an actual queue instead of a hashmap
|
||||
self.render_jobs = HashMap::new();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue