use crate::errors::AleaticoResult;
use crate::renderer::surface::Surface;
use crate::renderer::vertex::Vertex;
use std::borrow::Cow;
use std::fs;
use std::path::{Path, PathBuf};
use wgpu::util::DeviceExt;
use wgpu::{ShaderModuleDescriptor, ShaderSource};
pub struct Pipeline {
pub render_pipeline: wgpu::RenderPipeline,
pub vertex_buffer: wgpu::Buffer,
}
impl Pipeline {
pub fn from_shader_desc(
surface: &mut Surface,
vertices: &[Vertex],
shader: ShaderModuleDescriptor,
) -> AleaticoResult<Self> {
let shader = surface.device.create_shader_module(shader);
let vertex_buffer = surface
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: &*bytemuck::cast_slice(vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let render_pipeline_layout =
surface
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"),
bind_group_layouts: &[],
immediate_size: 0,
});
let render_pipeline =
surface
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Render Pipeline"),
layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: Some("vs_main"),
buffers: &[Vertex::desc()],
compilation_options: wgpu::PipelineCompilationOptions::default(),
},
primitive: 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,
},
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: Some("fs_main"),
targets: &[Some(wgpu::ColorTargetState {
format: surface.config.format,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
compilation_options: wgpu::PipelineCompilationOptions::default(),
}),
multiview_mask: None,
cache: None,
});
Ok(Self {
render_pipeline,
vertex_buffer,
})
}
pub fn from_shader_file(
surface: &mut Surface,
vertices: &[Vertex],
shader: impl Into<PathBuf> + Clone + AsRef<Path>,
) -> AleaticoResult<Self> {
let data = Cow::Owned(fs::read_to_string(shader.clone())?);
let shader_desc = ShaderModuleDescriptor {
label: Some("Shader"),
source: ShaderSource::Wgsl(data),
};
let render_pipeline = Pipeline::from_shader_desc(surface, vertices, shader_desc)?;
Ok(render_pipeline)
}
pub fn from_shader_string(
surface: &mut Surface,
vertices: &[Vertex],
shader: &str,
) -> AleaticoResult<Self> {
let shader_desc = ShaderModuleDescriptor {
label: Some("Shader"),
source: ShaderSource::Wgsl(Cow::Owned(shader.to_string())),
};
let render_pipeline = Pipeline::from_shader_desc(surface, vertices, shader_desc)?;
Ok(render_pipeline)
}
}