Skip to main content

mraphics_core/render/
pipeline_manager.rs

1use crate::{RenderInstance, constants::PrimitiveTopology};
2use std::collections::HashMap;
3
4pub struct PipelineManager {
5    pub pipeline_pool: HashMap<String, wgpu::RenderPipeline>,
6}
7
8impl PipelineManager {
9    pub fn new() -> Self {
10        Self {
11            pipeline_pool: HashMap::new(),
12        }
13    }
14
15    pub fn acquire_pipeline(
16        &mut self,
17        device: &wgpu::Device,
18        texture_format: wgpu::TextureFormat,
19        instance: &RenderInstance,
20        bind_groups: &[&wgpu::BindGroupLayout],
21        force_update: bool,
22    ) -> &wgpu::RenderPipeline {
23        let pipeline_identifier = format!(
24            "{}{}",
25            &instance.material.identifier,
26            instance.topology.to_str()
27        );
28
29        if !self.pipeline_pool.contains_key(&pipeline_identifier) || force_update {
30            self.insert_pipeline(
31                device,
32                texture_format,
33                instance,
34                bind_groups,
35                &pipeline_identifier,
36            );
37        }
38
39        // SAFETY: Checked upon
40        &self.pipeline_pool.get(&pipeline_identifier).unwrap()
41    }
42
43    pub fn insert_pipeline(
44        &mut self,
45        device: &wgpu::Device,
46        texture_format: wgpu::TextureFormat,
47        instance: &RenderInstance,
48        bind_groups: &[&wgpu::BindGroupLayout],
49        pipeline_identifier: &String,
50    ) {
51        self.pipeline_pool.insert(
52            String::from(pipeline_identifier),
53            PipelineManager::build_pipeline(
54                device,
55                texture_format,
56                instance,
57                bind_groups,
58                instance.topology,
59            ),
60        );
61    }
62
63    pub fn build_pipeline(
64        device: &wgpu::Device,
65        texture_format: wgpu::TextureFormat,
66        instance: &RenderInstance,
67        bind_groups: &[&wgpu::BindGroupLayout],
68        topology: PrimitiveTopology,
69    ) -> wgpu::RenderPipeline {
70        let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
71            label: Some("Mraphics Shader"),
72            source: wgpu::ShaderSource::Wgsl((&instance.material.shader_code).into()),
73        });
74
75        let render_pipeline_layout =
76            device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
77                label: Some("Mraphics Render Pipeline Layout"),
78                bind_group_layouts: bind_groups,
79                push_constant_ranges: &[],
80            });
81
82        let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
83            label: Some("Mraphics Render Pipeline"),
84            layout: Some(&render_pipeline_layout),
85            vertex: wgpu::VertexState {
86                module: &shader_module,
87                entry_point: Some("vs"),
88                buffers: &[],
89                compilation_options: wgpu::PipelineCompilationOptions::default(),
90            },
91            fragment: Some(wgpu::FragmentState {
92                module: &shader_module,
93                entry_point: Some("fs"),
94                targets: &[Some(wgpu::ColorTargetState {
95                    format: texture_format,
96                    blend: Some(wgpu::BlendState::REPLACE),
97                    write_mask: wgpu::ColorWrites::ALL,
98                })],
99                compilation_options: wgpu::PipelineCompilationOptions::default(),
100            }),
101            primitive: wgpu::PrimitiveState {
102                topology: topology.to_wgpu(),
103                strip_index_format: None,
104                front_face: wgpu::FrontFace::Ccw,
105                cull_mode: None,
106                polygon_mode: wgpu::PolygonMode::Fill,
107                unclipped_depth: false,
108                conservative: false,
109            },
110            depth_stencil: None,
111            multisample: wgpu::MultisampleState::default(),
112            multiview: None,
113            cache: None,
114        });
115
116        render_pipeline
117    }
118}