diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
commit | 6ab13f2d0cb345795f761181a06777ade61ff09c (patch) | |
tree | 42007acef9846d5e79f1bf418a96647f34b530d1 /stockton-render/src/draw/builders | |
parent | ccf0074b08ce835cf22e7d46153d1cb3f3d06d32 (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')
-rw-r--r-- | stockton-render/src/draw/builders/mod.rs | 3 | ||||
-rw-r--r-- | stockton-render/src/draw/builders/pipeline.rs | 288 | ||||
-rw-r--r-- | stockton-render/src/draw/builders/renderpass.rs | 75 | ||||
-rw-r--r-- | stockton-render/src/draw/builders/shader.rs | 35 |
4 files changed, 0 insertions, 401 deletions
diff --git a/stockton-render/src/draw/builders/mod.rs b/stockton-render/src/draw/builders/mod.rs deleted file mode 100644 index 002c09f..0000000 --- a/stockton-render/src/draw/builders/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod pipeline; -pub mod renderpass; -pub mod shader; 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))); - } - } -} diff --git a/stockton-render/src/draw/builders/renderpass.rs b/stockton-render/src/draw/builders/renderpass.rs deleted file mode 100644 index 43f0eb2..0000000 --- a/stockton-render/src/draw/builders/renderpass.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::types::*; - -use std::iter::{empty, once}; - -use anyhow::Result; -use hal::pass::{Attachment, AttachmentRef, SubpassDesc}; - -#[derive(Debug, Clone)] -pub struct RenderpassSpec { - pub colors: Vec<Attachment>, - pub depth: Option<Attachment>, - pub inputs: Vec<Attachment>, - pub resolves: Vec<Attachment>, - pub preserves: Vec<Attachment>, -} - -impl RenderpassSpec { - pub fn build_renderpass(self, device: &mut DeviceT) -> Result<RenderPassT> { - let mut next_offset = 0; - - let colors: Vec<AttachmentRef> = self - .colors - .iter() - .enumerate() - .map(|(i, a)| (next_offset + i, a.layouts.end)) - .collect(); - next_offset = colors.len(); - - let depth_stencil = self.depth.as_ref().map(|x| (next_offset, x.layouts.end)); - if depth_stencil.is_some() { - next_offset += 1; - } - - let inputs: Vec<AttachmentRef> = self - .inputs - .iter() - .enumerate() - .map(|(i, a)| (next_offset + i, a.layouts.end)) - .collect(); - next_offset += inputs.len(); - - let resolves: Vec<AttachmentRef> = self - .resolves - .iter() - .enumerate() - .map(|(i, a)| (next_offset + i, a.layouts.end)) - .collect(); - next_offset += resolves.len(); - - let preserves: Vec<usize> = self - .preserves - .iter() - .enumerate() - .map(|(i, _a)| next_offset + i) - .collect(); - - let sp_desc = SubpassDesc { - colors: colors.as_slice(), - depth_stencil: depth_stencil.as_ref(), - inputs: inputs.as_slice(), - resolves: resolves.as_slice(), - preserves: preserves.as_slice(), - }; - - let all_attachments = self - .colors - .into_iter() - .chain(self.depth.into_iter()) - .chain(self.inputs.into_iter()) - .chain(self.resolves.into_iter()) - .chain(self.preserves.into_iter()); - - Ok(unsafe { device.create_render_pass(all_attachments, once(sp_desc), empty())? }) - } -} diff --git a/stockton-render/src/draw/builders/shader.rs b/stockton-render/src/draw/builders/shader.rs deleted file mode 100644 index fde185d..0000000 --- a/stockton-render/src/draw/builders/shader.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::types::*; - -use anyhow::{Context, Result}; -use hal::pso::Specialization; -use shaderc::{Compiler, ShaderKind}; - -#[derive(Debug, Clone)] -pub struct ShaderDesc { - pub source: String, - pub entry: String, - pub kind: ShaderKind, -} - -impl ShaderDesc { - pub fn compile(&self, compiler: &mut Compiler, device: &mut DeviceT) -> Result<ShaderModuleT> { - let artifact = compiler - .compile_into_spirv(&self.source, self.kind, "shader", &self.entry, None) - .context("Shader compilation failed")?; - - // Make into shader module - Ok(unsafe { - device - .create_shader_module(artifact.as_binary()) - .context("Shader module creation failed")? - }) - } - - pub fn as_entry<'a>(&'a self, module: &'a ShaderModuleT) -> EntryPoint<'a> { - EntryPoint { - entry: &self.entry, - module, - specialization: Specialization::default(), - } - } -} |