still working on getiting these shaders to a usable API
This commit is contained in:
@@ -16,6 +16,7 @@ use vulkano::pipeline::vertex::SingleBufferDefinition;
|
||||
use crate::util::vertex_3d::Vertex3D;
|
||||
use shade_runner as sr;
|
||||
use crate::canvas::shader::common::CompiledGraphicsPipelineResources;
|
||||
use vulkano::memory::pool::PotentialDedicatedAllocation::Generic;
|
||||
|
||||
/// CanvasShader holds the pipeline and render pass for the input shader source
|
||||
#[derive(Clone)]
|
||||
@@ -24,16 +25,92 @@ pub struct GenericShader {
|
||||
|
||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||
name: String,
|
||||
shader_types: HashSet<ShaderType>,
|
||||
|
||||
device: Arc<Device>,
|
||||
}
|
||||
|
||||
|
||||
impl GenericShader {}
|
||||
|
||||
/// Gives CanvasShader the resource functions
|
||||
impl CompiledGraphicsPipelineResources for GenericShader {}
|
||||
|
||||
/// Convenience interface so we don't have to juggle shader types
|
||||
impl CompiledGraphicsPipeline for GenericShader {
|
||||
|
||||
/// This will explode when the shader does not want to compile
|
||||
fn new(filename: String,
|
||||
device: Arc<Device>,
|
||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
|
||||
|
||||
let compiled_vertex = GenericShader::compile(
|
||||
GenericShader::get_path(filename.clone(), ShaderType::VERTEX),
|
||||
device.clone(), ShaderType::VERTEX
|
||||
);
|
||||
|
||||
let vertex_entry_point = unsafe {
|
||||
Some(compiled_vertex.1.graphics_entry_point(
|
||||
&CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
compiled_vertex.0.input.unwrap(),
|
||||
compiled_vertex.0.output.unwrap(),
|
||||
compiled_vertex.0.layout,
|
||||
GenericShader::convert_vk(ShaderType::VERTEX)
|
||||
)).unwrap()
|
||||
};
|
||||
|
||||
let compiled_fragment = GenericShader::compile(
|
||||
GenericShader::get_path(filename.clone(), ShaderType::FRAGMENT).into(),
|
||||
device.clone(), ShaderType::FRAGMENT
|
||||
);
|
||||
|
||||
let fragment_entry_point = unsafe {
|
||||
Some(compiled_fragment.1.graphics_entry_point(
|
||||
&CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
compiled_fragment.0.input.unwrap(),
|
||||
compiled_fragment.0.output.unwrap(),
|
||||
compiled_fragment.0.layout,
|
||||
GenericShader::convert_vk(ShaderType::FRAGMENT)
|
||||
)).unwrap()
|
||||
};
|
||||
|
||||
GenericShader {
|
||||
graphics_pipeline:
|
||||
Some(Arc::new(GraphicsPipeline::start()
|
||||
|
||||
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
|
||||
|
||||
.vertex_shader(vertex_entry_point.clone(), ShaderSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
|
||||
.triangle_list()
|
||||
// Use a resizable viewport set to draw over the entire window
|
||||
.viewports_dynamic_scissors_irrelevant(1)
|
||||
|
||||
.fragment_shader(fragment_entry_point.clone(), ShaderSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
|
||||
.depth_stencil(DepthStencil::default())
|
||||
|
||||
// We have to indicate which subpass of which render pass this pipeline is going to be used
|
||||
// in. The pipeline will only be usable from this particular subpass.
|
||||
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
||||
|
||||
.build(device.clone())
|
||||
.unwrap())),
|
||||
|
||||
device: device,
|
||||
handle: handle.clone(),
|
||||
name: filename.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
@@ -54,130 +131,3 @@ impl CompiledGraphicsPipeline for GenericShader {
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericShader {
|
||||
|
||||
/// This will explode when the shader does not want to compile
|
||||
pub fn new(filename: String,
|
||||
device: Arc<Device>,
|
||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
|
||||
|
||||
let mut shader_types : HashSet<ShaderType> = vec![
|
||||
ShaderType::VERTEX,
|
||||
ShaderType::FRAGMENT,
|
||||
].iter().cloned().collect();
|
||||
|
||||
let filenames = GenericShader::get_paths(filename.clone(), shader_types.clone());
|
||||
|
||||
// I guess this really herky intermediate store is going to be the most flexible way to
|
||||
// create these pipelines?
|
||||
|
||||
let mut modules: HashMap<ShaderType, (Entry, Arc<ShaderModule>)> = HashMap::default();
|
||||
|
||||
let mut entry_points: HashMap<ShaderType, GraphicsEntryPoint<ShaderSpecializationConstants,Input,Output,Layout>> = HashMap::default();
|
||||
|
||||
for shader in filenames {
|
||||
let compiled_shader = sr::load_vertex(shader.1)
|
||||
.expect("Shader didn't compile");
|
||||
|
||||
let vulkano_entry =
|
||||
sr::parse(&compiled_shader)
|
||||
.expect("failed to parse");
|
||||
|
||||
modules.insert(shader.0, (vulkano_entry, unsafe {
|
||||
ShaderModule::from_words(device.clone(), &compiled_shader.spriv.clone())
|
||||
}.unwrap()));
|
||||
}
|
||||
|
||||
for (shader_type, (entry, module)) in modules {
|
||||
|
||||
let graphics_shader_type = match shader_type {
|
||||
ShaderType::VERTEX => { GraphicsShaderType::Vertex }
|
||||
ShaderType::FRAGMENT => { GraphicsShaderType::Fragment }
|
||||
ShaderType::GEOMETRY => { GraphicsShaderType::Geometry(GeometryShaderExecutionMode::Triangles) }
|
||||
ShaderType::TESSELLATION_CONTROL => { GraphicsShaderType::TessellationControl }
|
||||
ShaderType::TESSELLATION_EVALUATION => { GraphicsShaderType::TessellationEvaluation }
|
||||
};
|
||||
|
||||
let entry_point: Option<GraphicsEntryPoint<
|
||||
ShaderSpecializationConstants,
|
||||
Input,
|
||||
Output,
|
||||
Layout>> = unsafe {
|
||||
Some(GraphicsEntryPoint {
|
||||
module: &module,
|
||||
name: &CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||
input: entry.input.unwrap(),
|
||||
layout: entry.layout,
|
||||
output: entry.output.unwrap(),
|
||||
ty: graphics_shader_type,
|
||||
marker: PhantomData::default(),
|
||||
})
|
||||
};
|
||||
|
||||
entry_points.insert(shader_type, entry_point.unwrap().to_owned());
|
||||
}
|
||||
|
||||
let stencil = DepthStencil {
|
||||
depth_compare: Compare::Less,
|
||||
depth_write: true,
|
||||
depth_bounds_test: DepthBounds::Disabled,
|
||||
stencil_front: Stencil {
|
||||
compare: Compare::Equal,
|
||||
pass_op: StencilOp::IncrementAndWrap,
|
||||
fail_op: StencilOp::DecrementAndClamp,
|
||||
depth_fail_op: StencilOp::Keep,
|
||||
compare_mask: None,
|
||||
write_mask: None,
|
||||
reference: None,
|
||||
},
|
||||
stencil_back: Stencil {
|
||||
compare: Compare::Equal,
|
||||
pass_op: StencilOp::Invert,
|
||||
fail_op: StencilOp::Zero,
|
||||
depth_fail_op: StencilOp::Zero,
|
||||
compare_mask: None,
|
||||
write_mask: None,
|
||||
reference: None,
|
||||
},
|
||||
};
|
||||
|
||||
GenericShader {
|
||||
graphics_pipeline:
|
||||
Some(Arc::new(GraphicsPipeline::start()
|
||||
|
||||
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
|
||||
|
||||
.vertex_shader(entry_points.get(&ShaderType::VERTEX).unwrap().clone(), ShaderSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
|
||||
.triangle_list()
|
||||
// Use a resizable viewport set to draw over the entire window
|
||||
.viewports_dynamic_scissors_irrelevant(1)
|
||||
|
||||
.fragment_shader(entry_points.get(&ShaderType::VERTEX).unwrap().clone(), ShaderSpecializationConstants {
|
||||
first_constant: 0,
|
||||
second_constant: 0,
|
||||
third_constant: 0.0,
|
||||
})
|
||||
|
||||
.depth_stencil(stencil)
|
||||
|
||||
|
||||
// We have to indicate which subpass of which render pass this pipeline is going to be used
|
||||
// in. The pipeline will only be usable from this particular subpass.
|
||||
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
||||
|
||||
.build(device.clone())
|
||||
.unwrap())),
|
||||
|
||||
device: device,
|
||||
handle: handle.clone(),
|
||||
name: filename.clone(),
|
||||
shader_types: shader_types.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user