Galactica/crates/render/src/pipeline.rs

139 lines
3.3 KiB
Rust
Raw Normal View History

2023-12-23 12:52:36 -08:00
use std::rc::Rc;
2023-12-23 11:01:27 -08:00
use wgpu;
2023-12-31 18:48:35 -08:00
use crate::vertexbuffer::VertexBuffer;
2024-01-01 10:44:55 -08:00
use crate::{SHADER_MAIN_FRAGMENT, SHADER_MAIN_VERTEX};
2023-12-23 12:52:36 -08:00
2023-12-23 11:01:27 -08:00
pub struct PipelineBuilder<'a> {
// These are provided with new()
label: &'a str,
device: &'a wgpu::Device,
// These have empty defaults
triangle: bool,
bind_group_layouts: &'a [&'a wgpu::BindGroupLayout],
// These must be provided
shader: Option<&'a str>,
format: Option<wgpu::TextureFormat>,
2023-12-23 12:52:36 -08:00
vertex_buffer: Option<&'a Rc<VertexBuffer>>,
2023-12-23 11:01:27 -08:00
}
impl<'a> PipelineBuilder<'a> {
pub fn new(label: &'a str, device: &'a wgpu::Device) -> Self {
Self {
label,
device,
triangle: true,
2023-12-23 12:52:36 -08:00
vertex_buffer: None,
2023-12-23 11:01:27 -08:00
bind_group_layouts: &[],
shader: None,
format: None,
}
}
pub fn set_shader(mut self, shader: &'a str) -> Self {
self.shader = Some(shader);
self
}
pub fn set_format(mut self, format: wgpu::TextureFormat) -> Self {
self.format = Some(format);
self
}
pub fn set_triangle(mut self, triangle: bool) -> Self {
self.triangle = triangle;
self
}
2023-12-23 12:52:36 -08:00
pub fn set_vertex_buffer(mut self, vertex_buffer: &'a Rc<VertexBuffer>) -> Self {
self.vertex_buffer = Some(vertex_buffer);
2023-12-23 11:01:27 -08:00
self
}
pub fn set_bind_group_layouts(
mut self,
bind_group_layouts: &'a [&'a wgpu::BindGroupLayout],
) -> Self {
self.bind_group_layouts = bind_group_layouts;
self
}
pub fn build(self) -> wgpu::RenderPipeline {
// All fields should be set.
// Nones are not checked, they will panic.
let shader = self
.device
.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some(&format!("pipeline [{}] shader", self.label)),
source: wgpu::ShaderSource::Wgsl(self.shader.unwrap().into()),
});
let pipeline_layout = self
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some(&format!("pipeline [{}] layout", self.label)),
bind_group_layouts: self.bind_group_layouts,
push_constant_ranges: &[],
});
let pipeline = self
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some(&format!("pipeline [{}]", self.label)),
layout: Some(&pipeline_layout),
depth_stencil: None,
multiview: None,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
vertex: wgpu::VertexState {
module: &shader,
2023-12-25 11:17:08 -08:00
entry_point: SHADER_MAIN_VERTEX,
2023-12-23 12:52:36 -08:00
buffers: &self.vertex_buffer.unwrap().layout,
2023-12-23 11:01:27 -08:00
},
fragment: Some(wgpu::FragmentState {
module: &shader,
2023-12-25 11:17:08 -08:00
entry_point: SHADER_MAIN_FRAGMENT,
2023-12-23 11:01:27 -08:00
targets: &[Some(wgpu::ColorTargetState {
format: self.format.unwrap(),
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
primitive: if self.triangle {
wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: Some(wgpu::Face::Back),
polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false,
conservative: false,
}
} else {
wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::PointList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false,
conservative: false,
}
},
});
return pipeline;
}
}