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