pipeline builder

This commit is contained in:
Carter Anderson 2020-01-17 18:54:05 -08:00
parent 3a674394b9
commit d9bd2d4f15
3 changed files with 169 additions and 25 deletions

View file

@ -2,14 +2,15 @@ mod pipeline;
pub use pipeline::*;
use crate::prelude::*;
use crate::{asset::Texture, legion::{prelude::{Entity, World}, borrow::{Ref, RefMap}}, render::Albedo};
use std::{collections::{HashMap, HashSet}, ops::Deref};
use std::collections::HashMap;
pub enum ShaderValue<'a> {
Int(u32),
Float(f32),
Vec4(crate::math::Vec4),
Texture(&'a crate::asset::Handle<Texture>),
Vec4(Vec4),
Texture(&'a Handle<Texture>),
}
type ShaderMaterialSelector = fn(Entity, &World) -> Option<RefMap<&dyn ShaderMaterial>>;
@ -88,12 +89,20 @@ enum ResourceType {
// updates resources based on events like "resize" or "update"
// if there are no resources in use, dont run allocate resource provider resources on gpu
trait ResourceProvider {
fn get_resources() -> Vec<String>;
fn get_resources(&self) -> &[Resource];
}
// holds on to passes, pipeline descriptions, instances
// passes: shadow, forward
struct RenderGraph;
struct RenderGraph {
pipeline_definitions: HashMap<String, PipelineDefinition>,
pipeline_instances: HashMap<String, wgpu::RenderPipeline>,
}
struct RenderGraphBuilder {
}
/*
RenderGraph::build()
.AddPass("forward", Pass {
@ -127,20 +136,35 @@ RenderGraph::build()
)
*/
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
// Mesh target
trait DrawTarget {
fn draw(device: &wgpu::Device);
pub struct RenderPassColorAttachmentDescription {
/// The actual color attachment.
pub attachment: String,
/// The resolve target for this color attachment, if any.
pub resolve_target: Option<String>,
/// The beginning-of-pass load operation for this color attachment.
pub load_op: wgpu::LoadOp,
/// The end-of-pass store operation for this color attachment.
pub store_op: wgpu::StoreOp,
/// The color that will be assigned to every pixel of this attachment when cleared.
pub clear_color: wgpu::Color,
}
// a texture that is rendered to. TextureView or SwapChain
struct RenderTarget;
pub struct RenderPassDepthStencilAttachmentDescription {
pub attachment: String,
pub depth_load_op: wgpu::LoadOp,
pub depth_store_op: wgpu::StoreOp,
pub clear_depth: f32,
pub stencil_load_op: wgpu::LoadOp,
pub stencil_store_op: wgpu::StoreOp,
pub clear_stencil: u32,
}
// A set of pipeline bindings and draw calls with color and depth outputs
struct Pass;
// A pipeline description (original shaders)
struct PipelineDefinition;
// A specific instance of a pipeline definition
struct Pipeline;
struct Pass {
color_attachments: Vec<RenderPassColorAttachmentDescription>,
depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescription>,
}

View file

@ -1,4 +1,14 @@
use crate::render::shader::ShaderStages;
use crate::{
legion::prelude::World,
render::shader::{Shader, ShaderStages},
};
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
// Mesh target
// trait DrawTarget {
// fn draw(device: &wgpu::Device);
// }
type DrawTarget = fn(world: &World, device: &wgpu::Device);
pub struct VertexBufferDefinition {
pub stride: wgpu::BufferAddress,
@ -17,6 +27,7 @@ impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDefinition {
}
pub struct PipelineDefinition {
pub draw_targets: Vec<DrawTarget>,
pub shader_stages: ShaderStages,
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
@ -49,6 +60,30 @@ pub struct PipelineDefinition {
pub alpha_to_coverage_enabled: bool,
}
impl PipelineDefinition {
fn new(vertex_shader: Shader) -> Self {
PipelineDefinition {
color_states: Vec::new(),
depth_stencil_state: None,
draw_targets: Vec::new(),
shader_stages: ShaderStages::new(vertex_shader),
vertex_buffer_definitions: Vec::new(),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
index_format: wgpu::IndexFormat::Uint16,
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
}
}
}
impl PipelineDefinition {
pub fn create_render_pipeline(&self, device: &wgpu::Device) -> wgpu::RenderPipeline {
let vertex_shader_module = self.shader_stages.vertex.create_shader_module(device);
@ -57,11 +92,9 @@ impl PipelineDefinition {
None => None,
};
let pipeline_layout =
device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[],
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[],
});
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
@ -80,7 +113,11 @@ impl PipelineDefinition {
color_states: &self.color_states,
depth_stencil_state: self.depth_stencil_state.clone(),
index_format: self.index_format,
vertex_buffers: &self.vertex_buffer_definitions.iter().map(|v| v.into()).collect::<Vec<wgpu::VertexBufferDescriptor>>(),
vertex_buffers: &self
.vertex_buffer_definitions
.iter()
.map(|v| v.into())
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
sample_count: self.sample_count,
sample_mask: self.sample_mask,
alpha_to_coverage_enabled: self.alpha_to_coverage_enabled,
@ -88,4 +125,78 @@ impl PipelineDefinition {
device.create_render_pipeline(&render_pipeline_descriptor)
}
pub fn build(vertex_shader: Shader) -> PipelineBuilder {
PipelineBuilder::new(vertex_shader)
}
}
pub struct PipelineBuilder {
pipeline: PipelineDefinition,
}
impl PipelineBuilder {
pub fn new(vertex_shader: Shader) -> Self {
PipelineBuilder {
pipeline: PipelineDefinition::new(vertex_shader),
}
}
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
self.pipeline.shader_stages.fragment = Some(fragment_shader);
self
}
pub fn with_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self {
self.pipeline.color_states.push(color_state_descriptor);
self
}
pub fn with_depth_stencil_state(mut self, depth_stencil_state: wgpu::DepthStencilStateDescriptor) -> Self {
if let Some(_) = self.pipeline.depth_stencil_state {
panic!("Depth stencil state has already been set");
}
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
self
}
pub fn with_vertex_buffer_definition(mut self, vertex_buffer_definition: VertexBufferDefinition) -> Self {
self.pipeline.vertex_buffer_definitions.push(vertex_buffer_definition);
self
}
pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self {
self.pipeline.index_format = index_format;
self
}
pub fn with_draw_target(mut self, draw_target: DrawTarget) -> Self {
self.pipeline.draw_targets.push(draw_target);
self
}
pub fn with_rasterization_state(mut self, rasterization_state: wgpu::RasterizationStateDescriptor) -> Self {
self.pipeline.rasterization_state = Some(rasterization_state);
self
}
pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self {
self.pipeline.primitive_topology = primitive_topology;
self
}
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
self.pipeline.sample_count = sample_count;
self
}
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
self
}
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
self.pipeline.sample_mask = sample_mask;
self
}
}

View file

@ -65,4 +65,13 @@ impl Shader {
pub struct ShaderStages {
pub vertex: Shader,
pub fragment: Option<Shader>,
}
impl ShaderStages {
pub fn new(vertex_shader: Shader) -> Self {
ShaderStages {
vertex: vertex_shader,
fragment: None,
}
}
}