mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 06:08:13 +08:00
Refactor to generalize pipeline drawing sequence
This commit is contained in:
+98
-31
@@ -1,4 +1,6 @@
|
||||
use std::mem;
|
||||
use crate::resource_cache::ResourceCache;
|
||||
use crate::shader_stage;
|
||||
|
||||
pub struct Pipeline {
|
||||
pub bind_group_layout: wgpu::BindGroupLayout,
|
||||
@@ -6,23 +8,107 @@ pub struct Pipeline {
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(device: &wgpu::Device, vertex_shader: &wgpu::ShaderModule, fragment_shader: &wgpu::ShaderModule, bind_group_layout_binding_types: Vec<wgpu::BindingType>) -> Self {
|
||||
let bind_group_layout_entries = bind_group_layout_binding_types.into_iter().enumerate().map(|(index, binding_type)|
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
pub fn new(device: &wgpu::Device, swap_chain_color_format: wgpu::TextureFormat, extra_layouts: Vec<&wgpu::BindGroupLayout>, shader_cache: &mut ResourceCache<wgpu::ShaderModule>, shader_pair_path: (&str, &str)) -> Self {
|
||||
// Load the vertex and fragment shaders
|
||||
let shader_pair = Pipeline::get_shader_pair(device, shader_cache, shader_pair_path);
|
||||
|
||||
// Prepare a bind group layout for the GUI element's texture and form factor data
|
||||
let bind_group_layout = Pipeline::build_bind_group_layout(device, &vec![
|
||||
wgpu::BindingType::UniformBuffer { dynamic: false },
|
||||
wgpu::BindingType::SampledTexture {
|
||||
dimension: wgpu::TextureViewDimension::D2,
|
||||
component_type: wgpu::TextureComponentType::Float,
|
||||
multisampled: false,
|
||||
},
|
||||
]);
|
||||
|
||||
// Combine all bind group layouts
|
||||
let mut bind_group_layouts = vec![&bind_group_layout];
|
||||
bind_group_layouts.append(&mut extra_layouts.clone());
|
||||
|
||||
// Construct the pipeline
|
||||
let render_pipeline = Pipeline::build_pipeline(device, swap_chain_color_format, bind_group_layouts, shader_pair);
|
||||
Self {
|
||||
bind_group_layout,
|
||||
render_pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_shader_pair<'a>(device: &wgpu::Device, shader_cache: &'a mut ResourceCache<wgpu::ShaderModule>, shader_pair_path: (&str, &str)) -> (&'a wgpu::ShaderModule, &'a wgpu::ShaderModule) {
|
||||
// If uncached, construct a vertex shader loaded from its source code file
|
||||
if shader_cache.get(shader_pair_path.0).is_none() {
|
||||
let vertex_shader_module = shader_stage::compile_from_glsl(device, shader_pair_path.0, glsl_to_spirv::ShaderType::Vertex).unwrap();
|
||||
shader_cache.set(shader_pair_path.0, vertex_shader_module);
|
||||
}
|
||||
|
||||
// If uncached, construct a fragment shader loaded from its source code file
|
||||
if shader_cache.get(shader_pair_path.1).is_none() {
|
||||
let fragment_shader_module = shader_stage::compile_from_glsl(&device, shader_pair_path.1, glsl_to_spirv::ShaderType::Fragment).unwrap();
|
||||
shader_cache.set(shader_pair_path.1, fragment_shader_module);
|
||||
}
|
||||
|
||||
// Get the shader pair
|
||||
let vertex_shader = shader_cache.get(shader_pair_path.0).unwrap();
|
||||
let fragment_shader = shader_cache.get(shader_pair_path.1).unwrap();
|
||||
|
||||
(vertex_shader, fragment_shader)
|
||||
}
|
||||
|
||||
pub fn build_bind_group_layouts(device: &wgpu::Device, bind_group_layouts: &Vec<Vec<wgpu::BindingType>>) -> Vec<wgpu::BindGroupLayout> {
|
||||
bind_group_layouts.into_iter().map(|layout_entry| Self::build_bind_group_layout(device, layout_entry)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn build_bind_group_layout(device: &wgpu::Device, bind_group_layout: &Vec<wgpu::BindingType>) -> wgpu::BindGroupLayout {
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
bindings: bind_group_layout.into_iter().enumerate().map(|(index, binding_type)|
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: index as u32,
|
||||
visibility: wgpu::ShaderStage::all(),
|
||||
ty: binding_type.clone(),
|
||||
}
|
||||
).collect::<Vec<_>>().as_slice(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_binding_staging_buffer<T: bytemuck::Pod>(device: &wgpu::Device, resource: T) -> wgpu::Buffer { // TODO: Turn this into a borrow
|
||||
// Construct a staging buffer with the binary uniform struct data
|
||||
device.create_buffer_with_data(
|
||||
bytemuck::cast_slice(&[resource]),
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn build_binding_resource(resource_buffer: &wgpu::Buffer) -> wgpu::BindingResource {
|
||||
// Return the buffer as a binding resource
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer: resource_buffer,
|
||||
range: 0..std::mem::size_of_val(resource_buffer) as wgpu::BufferAddress,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_bind_group(device: &wgpu::Device, bind_group_layout: &wgpu::BindGroupLayout, binding_resources: Vec<wgpu::BindingResource>) -> wgpu::BindGroup {
|
||||
let bindings = binding_resources.into_iter().enumerate().map(|(index, binding_resource)|
|
||||
wgpu::Binding {
|
||||
binding: index as u32,
|
||||
visibility: wgpu::ShaderStage::all(),
|
||||
ty: binding_type,
|
||||
resource: binding_resource,
|
||||
}
|
||||
).collect::<Vec<_>>();
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_entries.as_slice(),
|
||||
label: None,
|
||||
});
|
||||
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: bind_group_layout,
|
||||
bindings: bindings.as_slice(),
|
||||
label: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_pipeline(device: &wgpu::Device, swap_chain_color_format: wgpu::TextureFormat, bind_group_layouts: Vec<&wgpu::BindGroupLayout>, shader_pair: (&wgpu::ShaderModule, &wgpu::ShaderModule)) -> wgpu::RenderPipeline {
|
||||
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
|
||||
let (vertex_shader, fragment_shader) = shader_pair;
|
||||
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
layout: &render_pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: vertex_shader,
|
||||
@@ -41,7 +127,7 @@ impl Pipeline {
|
||||
}),
|
||||
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
color_states: &[wgpu::ColorStateDescriptor {
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb, // TODO: Make this match Application.swap_chain_descriptor
|
||||
format: swap_chain_color_format,
|
||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
@@ -62,25 +148,6 @@ impl Pipeline {
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
});
|
||||
|
||||
Self {
|
||||
bind_group_layout,
|
||||
render_pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_bind_group(&self, device: &wgpu::Device, binding_resources: Vec<wgpu::BindingResource>) -> wgpu::BindGroup {
|
||||
let bindings = binding_resources.into_iter().enumerate().map(|(index, binding_resource)|
|
||||
wgpu::Binding {
|
||||
binding: index as u32,
|
||||
resource: binding_resource,
|
||||
}
|
||||
).collect::<Vec<_>>();
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &self.bind_group_layout,
|
||||
bindings: bindings.as_slice(),
|
||||
label: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user