aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/builders/pipeline.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:23 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:23 +0100
commit6ab13f2d0cb345795f761181a06777ade61ff09c (patch)
tree42007acef9846d5e79f1bf418a96647f34b530d1 /stockton-render/src/draw/builders/pipeline.rs
parentccf0074b08ce835cf22e7d46153d1cb3f3d06d32 (diff)
refactor(all): separate rendering from framework
stockton-passes is mostly just a stand-in until this is properly separated
Diffstat (limited to 'stockton-render/src/draw/builders/pipeline.rs')
-rw-r--r--stockton-render/src/draw/builders/pipeline.rs288
1 files changed, 0 insertions, 288 deletions
diff --git a/stockton-render/src/draw/builders/pipeline.rs b/stockton-render/src/draw/builders/pipeline.rs
deleted file mode 100644
index 0c06774..0000000
--- a/stockton-render/src/draw/builders/pipeline.rs
+++ /dev/null
@@ -1,288 +0,0 @@
-use super::{renderpass::RenderpassSpec, shader::ShaderDesc};
-use crate::{draw::target::SwapchainProperties, error::EnvironmentError, types::*};
-
-use std::{mem::ManuallyDrop, ops::Range};
-
-use anyhow::{Context, Result};
-use hal::{
- format::Format,
- pso::{
- AttributeDesc, BakedStates, BasePipeline, BlendDesc, BufferIndex, DepthStencilDesc,
- ElemStride, Element, GraphicsPipelineDesc, InputAssemblerDesc, PipelineCreationFlags,
- PrimitiveAssemblerDesc, Rasterizer, Rect, ShaderStageFlags, VertexBufferDesc,
- VertexInputRate, Viewport,
- },
-};
-use shaderc::Compiler;
-
-pub struct VertexBufferSpec {
- pub attributes: Vec<Format>,
- pub rate: VertexInputRate,
-}
-
-impl VertexBufferSpec {
- pub fn as_attribute_desc(&self, binding: BufferIndex) -> Vec<AttributeDesc> {
- let mut v = Vec::with_capacity(self.attributes.len());
- let mut offset = 0;
- for (idx, format) in self.attributes.iter().enumerate() {
- v.push(AttributeDesc {
- location: idx as u32,
- binding,
- element: Element {
- offset,
- format: *format,
- },
- });
- offset += get_size(*format);
- }
-
- v
- }
- pub fn stride(&self) -> ElemStride {
- self.attributes.iter().fold(0, |x, f| x + get_size(*f))
- }
-}
-
-fn get_size(f: Format) -> u32 {
- match f {
- Format::Rgb32Sfloat => 4 * 3,
- Format::R32Sint => 4,
- Format::Rg32Sfloat => 4 * 2,
- Format::Rgba32Sfloat => 4 * 4,
- _ => unimplemented!("dont know size of format {:?}", f),
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct VertexPrimitiveAssemblerSpec {
- buffers: Vec<VertexBufferDesc>,
- attributes: Vec<AttributeDesc>,
- input_assembler: InputAssemblerDesc,
-}
-
-impl VertexPrimitiveAssemblerSpec {
- pub fn with_buffer(&mut self, bd: VertexBufferSpec) -> &mut Self {
- let idx = self.buffers.len() as u32;
- self.buffers.push(VertexBufferDesc {
- binding: idx,
- stride: bd.stride(),
- rate: bd.rate,
- });
-
- self.attributes.extend(bd.as_attribute_desc(idx));
-
- self
- }
-
- pub fn with_buffers(iad: InputAssemblerDesc, mut bds: Vec<VertexBufferSpec>) -> Self {
- let mut this = VertexPrimitiveAssemblerSpec {
- buffers: vec![],
- attributes: vec![],
- input_assembler: iad,
- };
-
- for bd in bds.drain(..) {
- this.with_buffer(bd);
- }
-
- this
- }
-}
-
-#[derive(Builder, Debug)]
-#[builder(public)]
-pub struct PipelineSpec {
- rasterizer: Rasterizer,
- depth_stencil: DepthStencilDesc,
- blender: BlendDesc,
- primitive_assembler: VertexPrimitiveAssemblerSpec,
-
- shader_vertex: ShaderDesc,
- #[builder(setter(strip_option))]
- shader_fragment: Option<ShaderDesc>,
- #[builder(setter(strip_option), default)]
- shader_geom: Option<ShaderDesc>,
- #[builder(setter(strip_option), default)]
- shader_tesselation: Option<(ShaderDesc, ShaderDesc)>,
-
- push_constants: Vec<(ShaderStageFlags, Range<u32>)>,
-
- #[builder(default = "false")]
- dynamic_viewport: bool,
- #[builder(default = "false")]
- dynamic_scissor: bool,
-
- renderpass: RenderpassSpec,
-}
-
-impl PipelineSpec {
- pub fn build<'b, T: Iterator<Item = &'b DescriptorSetLayoutT> + std::fmt::Debug>(
- self,
- device: &mut DeviceT,
- extent: hal::image::Extent,
- _swapchain_properties: &SwapchainProperties,
- set_layouts: T,
- ) -> Result<CompletePipeline> {
- // Renderpass
- let renderpass = self.renderpass.build_renderpass(device)?;
-
- // Subpass
- let subpass = hal::pass::Subpass {
- index: 0,
- main_pass: &renderpass,
- };
-
- let mut compiler = Compiler::new().ok_or(EnvironmentError::NoShaderC)?;
- let (vs_module, fs_module, gm_module, ts_module) = {
- (
- self.shader_vertex.compile(&mut compiler, device)?,
- self.shader_fragment
- .as_ref()
- .map(|x| x.compile(&mut compiler, device))
- .transpose()?,
- self.shader_geom
- .as_ref()
- .map(|x| x.compile(&mut compiler, device))
- .transpose()?,
- self.shader_tesselation
- .as_ref()
- .map::<Result<_>, _>(|(a, b)| {
- Ok((
- a.compile(&mut compiler, device)?,
- b.compile(&mut compiler, device)?,
- ))
- })
- .transpose()?,
- )
- };
-
- // Safety: *_module is always populated when shader_* is, so this is safe
- let (vs_entry, fs_entry, gm_entry, ts_entry) = (
- self.shader_vertex.as_entry(&vs_module),
- self.shader_fragment
- .as_ref()
- .map(|x| x.as_entry(fs_module.as_ref().unwrap())),
- self.shader_geom
- .as_ref()
- .map(|x| x.as_entry(gm_module.as_ref().unwrap())),
- self.shader_tesselation.as_ref().map(|(a, b)| {
- (
- a.as_entry(&ts_module.as_ref().unwrap().0),
- b.as_entry(&ts_module.as_ref().unwrap().1),
- )
- }),
- );
-
- // Pipeline layout
- let layout = unsafe {
- device.create_pipeline_layout(set_layouts.into_iter(), self.push_constants.into_iter())
- }
- .context("Error creating pipeline layout")?;
-
- // Baked states
- let baked_states = BakedStates {
- viewport: match self.dynamic_viewport {
- true => None,
- false => Some(Viewport {
- rect: extent.rect(),
- depth: (0.0..1.0),
- }),
- },
- scissor: match self.dynamic_scissor {
- true => None,
- false => Some(extent.rect()),
- },
- blend_constants: None,
- depth_bounds: None,
- };
-
- // Primitive assembler
- let primitive_assembler = PrimitiveAssemblerDesc::Vertex {
- buffers: self.primitive_assembler.buffers.as_slice(),
- attributes: self.primitive_assembler.attributes.as_slice(),
- input_assembler: self.primitive_assembler.input_assembler,
- vertex: vs_entry,
- tessellation: ts_entry,
- geometry: gm_entry,
- };
-
- // Pipeline description
- let pipeline_desc = GraphicsPipelineDesc {
- label: Some("stockton"),
- rasterizer: self.rasterizer,
- fragment: fs_entry,
- blender: self.blender,
- depth_stencil: self.depth_stencil,
- multisampling: None,
- baked_states,
- layout: &layout,
- subpass,
- flags: PipelineCreationFlags::empty(),
- parent: BasePipeline::None,
- primitive_assembler,
- };
-
- // Pipeline
- let pipeline = unsafe { device.create_graphics_pipeline(&pipeline_desc, None) }
- .context("Error creating graphics pipeline")?;
-
- Ok(CompletePipeline {
- renderpass: ManuallyDrop::new(renderpass),
- pipeline_layout: ManuallyDrop::new(layout),
- pipeline: ManuallyDrop::new(pipeline),
- vs_module: ManuallyDrop::new(vs_module),
- fs_module,
- gm_module,
- ts_module,
- render_area: extent.rect(),
- })
- }
-}
-
-pub struct CompletePipeline {
- /// Our main render pass
- pub(crate) renderpass: ManuallyDrop<RenderPassT>,
-
- /// The layout of our main graphics pipeline
- pub(crate) pipeline_layout: ManuallyDrop<PipelineLayoutT>,
-
- /// Our main graphics pipeline
- pub(crate) pipeline: ManuallyDrop<GraphicsPipelineT>,
-
- /// The vertex shader module
- pub(crate) vs_module: ManuallyDrop<ShaderModuleT>,
-
- /// The fragment shader module
- pub(crate) fs_module: Option<ShaderModuleT>,
- pub(crate) gm_module: Option<ShaderModuleT>,
- pub(crate) ts_module: Option<(ShaderModuleT, ShaderModuleT)>,
-
- pub(crate) render_area: Rect,
-}
-
-impl CompletePipeline {
- /// Deactivate vulkan resources. Use before dropping
- pub fn deactivate(mut self, device: &mut DeviceT) {
- unsafe {
- use core::ptr::read;
-
- device.destroy_render_pass(ManuallyDrop::into_inner(read(&self.renderpass)));
-
- device.destroy_shader_module(ManuallyDrop::into_inner(read(&self.vs_module)));
- if let Some(x) = self.fs_module.take() {
- device.destroy_shader_module(x)
- }
- if let Some(x) = self.gm_module.take() {
- device.destroy_shader_module(x)
- }
- self.ts_module.take().map(|(a, b)| {
- device.destroy_shader_module(a);
- device.destroy_shader_module(b);
- });
-
- device.destroy_graphics_pipeline(ManuallyDrop::into_inner(read(&self.pipeline)));
-
- device.destroy_pipeline_layout(ManuallyDrop::into_inner(read(&self.pipeline_layout)));
- }
- }
-}