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;
|
|
|
|
}
|
|
|
|
}
|