librashader/librashader-runtime-wgpu/src/graphics_pipeline.rs

162 lines
5.7 KiB
Rust
Raw Normal View History

2023-11-30 17:49:22 +11:00
use std::borrow::Cow;
2023-12-13 11:02:49 +11:00
use std::num::NonZeroU32;
2023-11-30 17:49:22 +11:00
use std::sync::Arc;
use wgpu::{BindGroup, BindGroupDescriptor, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, Device, PipelineLayout, PushConstantRange, SamplerBindingType, ShaderModule, ShaderSource, ShaderStages, TextureFormat, TextureSampleType, TextureViewDimension};
2023-11-30 17:49:22 +11:00
use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::back::wgsl::NagaWgslContext;
use librashader_reflect::reflect::semantics::BufferReflection;
2023-11-30 17:49:22 +11:00
use librashader_reflect::reflect::ShaderReflection;
2023-12-13 11:02:49 +11:00
use crate::util;
2023-11-30 17:49:22 +11:00
pub struct WgpuGraphicsPipeline {
vertex: ShaderModule,
fragment: ShaderModule
}
2023-12-13 11:02:49 +11:00
pub struct PipelineLayoutObjects {
pub layout: PipelineLayout,
pub bind_group_layouts: Vec<BindGroupLayout>
}
//
// pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
//
// }
// pub fn add_texture_bindings<'a>(&mut self, textures: impl Iterator<Item = &'a TextureBinding>) {
// let texture_mask = vk::ShaderStageFlags::FRAGMENT;
// for texture in textures {
// self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
// binding: texture.binding,
// descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: 1,
// stage_flags: texture_mask,
// p_immutable_samplers: std::ptr::null(),
// });
//
// self.pool_sizes.push(vk::DescriptorPoolSize {
// ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
// descriptor_count: self.replicas,
// })
// }
// }
2023-12-13 11:02:49 +11:00
impl PipelineLayoutObjects {
pub fn new(
reflection: &ShaderReflection,
device: &Device
) -> Self {
let mut bind_group_layouts = Vec::new();
let mut main_bindings = Vec::new();
let mut sampler_bindings = Vec::new();
let mut push_constant_range = Vec::new();
2023-12-13 11:02:49 +11:00
if let Some(push_meta) = reflection.push_constant.as_ref() && !push_meta.stage_mask.is_empty() {
let push_mask = util::binding_stage_to_wgpu_stage(push_meta.stage_mask);
if let Some(binding) = push_meta.binding {
main_bindings.push(BindGroupLayoutEntry {
binding,
visibility: push_mask,
2023-12-13 11:02:49 +11:00
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: BufferSize::new(push_meta.size as u64),
2023-12-13 11:02:49 +11:00
},
count: None,
});
} else {
push_constant_range.push(PushConstantRange {
stages: push_mask,
range: 0..push_meta.size,
})
}
}
if let Some(ubo_meta) = reflection.ubo.as_ref() && !ubo_meta.stage_mask.is_empty() {
let ubo_mask = util::binding_stage_to_wgpu_stage(ubo_meta.stage_mask);
main_bindings.push(BindGroupLayoutEntry {
binding: ubo_meta.binding,
visibility: ubo_mask,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: BufferSize::new(ubo_meta.size as u64),
},
count: None,
});
}
for texture in reflection.meta.texture_meta.values() {
main_bindings.push(BindGroupLayoutEntry {
binding: texture.binding,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
sample_type: TextureSampleType::Float { filterable: true },
view_dimension: TextureViewDimension::D2,
multisampled: false,
},
count: None,
2023-12-13 11:02:49 +11:00
});
sampler_bindings.push(BindGroupLayoutEntry {
binding: texture.binding,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler(SamplerBindingType::Filtering),
count: None,
})
2023-12-13 11:02:49 +11:00
}
let main_bind_group = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("bind group 0"),
entries: &main_bindings,
});
let sampler_bind_group = device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("bind group 1"),
entries: &sampler_bindings,
});
bind_group_layouts.push(main_bind_group);
bind_group_layouts.push(sampler_bind_group);
2023-12-13 11:02:49 +11:00
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("shader pipeline layout"),
bind_group_layouts: &bind_group_layouts.as_ref(),
push_constant_ranges: &push_constant_range.as_ref(),
2023-12-13 11:02:49 +11:00
});
Self {
layout,
bind_group_layouts
}
}
}
2023-11-30 17:49:22 +11:00
impl WgpuGraphicsPipeline {
pub fn new(
device: &Device,
shader_assembly: &ShaderCompilerOutput<String, NagaWgslContext>,
2023-11-30 17:49:22 +11:00
reflection: &ShaderReflection,
render_pass_format: TextureFormat,
) -> Self {
let vertex = device.create_shader_module(wgpu::ShaderModuleDescriptor {
2023-11-30 17:49:22 +11:00
label: Some("vertex"),
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.vertex))
});
2023-12-13 11:02:49 +11:00
let fragment = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("fragment"),
source: ShaderSource::Wgsl(Cow::from(&shader_assembly.fragment))
});
2023-12-13 11:02:49 +11:00
2023-11-30 17:49:22 +11:00
Self {
vertex,
fragment
}
}
}