still working on getiting these shaders to a usable API
This commit is contained in:
21
resources/shaders/simple_texture.frag
Normal file
21
resources/shaders/simple_texture.frag
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#version 450
|
||||||
|
// SIMPLE TEXTURE : FRAGMENT SHADER
|
||||||
|
|
||||||
|
// These come in from the previous shader (vertex)
|
||||||
|
layout(location = 0) in vec2 texture_position;
|
||||||
|
|
||||||
|
// This goes out to the bound image in window_size_dependent setup
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
// This is bound by the descriptor set
|
||||||
|
// Currently handled by the individual buffer and are 1:1
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
ivec2 pixel_pos = ivec2(gl_FragCoord.x, gl_FragCoord.y);
|
||||||
|
|
||||||
|
f_color = texture(tex, texture_position);
|
||||||
|
float gamma = 0.5;
|
||||||
|
f_color.rgb = pow(f_color.rgb, vec3(1.0/gamma));
|
||||||
|
}
|
||||||
21
resources/shaders/simple_texture.vert
Normal file
21
resources/shaders/simple_texture.vert
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#version 450
|
||||||
|
// SIMPLE TEXTURE : VERTEX SHADER
|
||||||
|
|
||||||
|
// These come in from the vertex definition
|
||||||
|
// TODO : Need to add texture coordinate attribute so I can single VBO all these sumbitches
|
||||||
|
layout(location = 0) in vec3 v_position;
|
||||||
|
layout(location = 1) in vec4 color;
|
||||||
|
layout(location = 2) in vec2 ti_position;
|
||||||
|
|
||||||
|
// These are made up in the shader themselves
|
||||||
|
layout(location = 0) out vec2 tex_coords;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
gl_Position = vec4(v_position, 1.0);
|
||||||
|
tex_coords = ti_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ use crate::util::vertex_3d::Vertex3D;
|
|||||||
use vulkano::pipeline::depth_stencil::{StencilFaceFlags, DynamicStencilValue};
|
use vulkano::pipeline::depth_stencil::{StencilFaceFlags, DynamicStencilValue};
|
||||||
use crate::canvas::shader::common::{CompiledGraphicsPipeline, CompiledGraphicsPipelineHandle};
|
use crate::canvas::shader::common::{CompiledGraphicsPipeline, CompiledGraphicsPipelineHandle};
|
||||||
use crate::canvas::shader::generic_shader::GenericShader;
|
use crate::canvas::shader::generic_shader::GenericShader;
|
||||||
|
use vulkano::memory::pool::PotentialDedicatedAllocation::Generic;
|
||||||
|
|
||||||
/// A drawable object can be passed into a CanvasFrame to be rendered
|
/// A drawable object can be passed into a CanvasFrame to be rendered
|
||||||
/// Very generic implementation. (N % 2 == 0) vertices, ditto for texture coords, and rgba color
|
/// Very generic implementation. (N % 2 == 0) vertices, ditto for texture coords, and rgba color
|
||||||
@@ -336,17 +337,17 @@ impl CanvasState {
|
|||||||
|
|
||||||
/// Load and Compile a shader with the filename at resources/shaders
|
/// Load and Compile a shader with the filename at resources/shaders
|
||||||
/// Takes physical and capabilities as we don't store that in Canvas
|
/// Takes physical and capabilities as we don't store that in Canvas
|
||||||
pub fn load_shader(&mut self,
|
pub fn load_shader<T: 'static>(&mut self,
|
||||||
filename: String,
|
filename: String,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
capabilities: Capabilities) -> Option<Arc<CompiledGraphicsPipelineHandle>> {
|
capabilities: Capabilities) -> Option<Arc<CompiledGraphicsPipelineHandle>>
|
||||||
|
where T: CompiledGraphicsPipeline {
|
||||||
|
|
||||||
let handle = Arc::new(CompiledGraphicsPipelineHandle {
|
let handle = Arc::new(CompiledGraphicsPipelineHandle {
|
||||||
handle: self.shader_buffers.len() as u32
|
handle: self.shader_buffers.len() as u32
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let shader : Box<dyn CompiledGraphicsPipeline> = Box::new(T::new(
|
||||||
let shader : Box<dyn CompiledGraphicsPipeline> = Box::new(GenericShader::new(
|
|
||||||
filename.clone(),
|
filename.clone(),
|
||||||
self.device.clone(),
|
self.device.clone(),
|
||||||
handle.clone(),
|
handle.clone(),
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
use vulkano::device::{Device, Queue};
|
|
||||||
use vulkano::instance::{PhysicalDevice, QueueFamily, LayerProperties};
|
|
||||||
use vulkano::pipeline::{GraphicsPipeline, GraphicsPipelineAbstract, GraphicsPipelineBuilder};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::ffi::CStr;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use shade_runner as sr;
|
|
||||||
use vulkano::framebuffer::{Subpass, RenderPassAbstract, Framebuffer, FramebufferAbstract};
|
|
||||||
use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, SpecializationConstants, SpecializationMapEntry, GeometryShaderExecutionMode, GraphicsEntryPointAbstract, GraphicsEntryPoint, EmptyEntryPointDummy};
|
|
||||||
use vulkano::swapchain::Capabilities;
|
|
||||||
use vulkano::pipeline::vertex::SingleBufferDefinition;
|
|
||||||
use crate::util::vertex_3d::Vertex3D;
|
|
||||||
use vulkano::pipeline::depth_stencil::{DepthStencil, Stencil, StencilOp, Compare, DepthBounds};
|
|
||||||
use std::collections::{HashSet, HashMap};
|
|
||||||
use shade_runner::{Layout, Output, Input, Entry};
|
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use vulkano::pipeline::input_assembly::PrimitiveTopology;
|
|
||||||
use vulkano::pipeline::blend::{Blend, AttachmentsBlend};
|
|
||||||
use vulkano::pipeline::vertex::BufferlessDefinition;
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ use std::path::PathBuf;
|
|||||||
use vulkano::pipeline::GraphicsPipelineAbstract;
|
use vulkano::pipeline::GraphicsPipelineAbstract;
|
||||||
use vulkano::framebuffer::RenderPassAbstract;
|
use vulkano::framebuffer::RenderPassAbstract;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use vulkano::pipeline::shader::{ShaderModule, GraphicsShaderType, GeometryShaderExecutionMode};
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use shade_runner::Entry;
|
||||||
|
use shaderc::ShaderKind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -24,7 +28,8 @@ This best works I think if I allow users to
|
|||||||
|
|
||||||
/// Inheriting this gives private functions to grab resources
|
/// Inheriting this gives private functions to grab resources
|
||||||
pub(super) trait CompiledGraphicsPipelineResources {
|
pub(super) trait CompiledGraphicsPipelineResources {
|
||||||
fn get_paths(filename: String, types: HashSet<ShaderType>) -> Vec<(ShaderType, PathBuf)> {
|
|
||||||
|
fn get_path(filename: String, shader_type: ShaderType) -> PathBuf {
|
||||||
let project_root =
|
let project_root =
|
||||||
std::env::current_dir()
|
std::env::current_dir()
|
||||||
.expect("failed to get root directory");
|
.expect("failed to get root directory");
|
||||||
@@ -32,39 +37,62 @@ pub(super) trait CompiledGraphicsPipelineResources {
|
|||||||
let mut shader_path = project_root.clone();
|
let mut shader_path = project_root.clone();
|
||||||
shader_path.push(PathBuf::from("resources/shaders/"));
|
shader_path.push(PathBuf::from("resources/shaders/"));
|
||||||
|
|
||||||
let mut paths = Vec::new();
|
|
||||||
|
|
||||||
for shader_type in types {
|
let mut shader_path = shader_path.clone();
|
||||||
match shader_type {
|
|
||||||
ShaderType::VERTEX => {
|
match shader_type {
|
||||||
let mut shader_path = shader_path.clone();
|
ShaderType::VERTEX => {
|
||||||
shader_path.push(PathBuf::from(filename.clone() + ".vert"));
|
shader_path.push(PathBuf::from(filename.clone() + ".vert"));
|
||||||
paths.push((shader_type, shader_path));
|
}
|
||||||
}
|
ShaderType::FRAGMENT => {
|
||||||
ShaderType::FRAGMENT => {
|
shader_path.push(PathBuf::from(filename.clone() + ".frag"));
|
||||||
let mut shader_path = shader_path.clone();
|
}
|
||||||
shader_path.push(PathBuf::from(filename.clone() + ".frag"));
|
ShaderType::GEOMETRY => {
|
||||||
paths.push((shader_type, shader_path));
|
shader_path.push(PathBuf::from(filename.clone() + ".geom"));
|
||||||
}
|
}
|
||||||
ShaderType::GEOMETRY => {
|
ShaderType::TESSELLATION_CONTROL => {
|
||||||
let mut shader_path = shader_path.clone();
|
shader_path.push(PathBuf::from(filename.clone() + ".tesscont"));
|
||||||
shader_path.push(PathBuf::from(filename.clone() + ".geom"));
|
}
|
||||||
paths.push((shader_type, shader_path));
|
ShaderType::TESSELLATION_EVALUATION => {
|
||||||
}
|
shader_path.push(PathBuf::from(filename.clone() + ".tesseval"));
|
||||||
ShaderType::TESSELLATION_CONTROL => {
|
|
||||||
let mut shader_path = shader_path.clone();
|
|
||||||
shader_path.push(PathBuf::from(filename.clone() + ".tesscont"));
|
|
||||||
paths.push((shader_type, shader_path));
|
|
||||||
}
|
|
||||||
ShaderType::TESSELLATION_EVALUATION => {
|
|
||||||
let mut shader_path = shader_path.clone();
|
|
||||||
shader_path.push(PathBuf::from(filename.clone() + ".tesseval"));
|
|
||||||
paths.push((shader_type, shader_path));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paths
|
shader_path
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn compile(filepath: PathBuf, device: Arc<Device>, shader_type: ShaderType) -> (Entry, Arc<ShaderModule>) {
|
||||||
|
let compiled_shader = shade_runner::load(filepath, Self::convert_sr(shader_type))
|
||||||
|
.expect("Shader didn't compile");
|
||||||
|
|
||||||
|
let vulkano_entry =
|
||||||
|
shade_runner::parse(&compiled_shader)
|
||||||
|
.expect("failed to parse");
|
||||||
|
|
||||||
|
(vulkano_entry, unsafe {
|
||||||
|
ShaderModule::from_words(device.clone(), &compiled_shader.spriv.clone())
|
||||||
|
}.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_vk(shader_type: ShaderType) -> GraphicsShaderType {
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_sr(shader_type: ShaderType) -> ShaderKind {
|
||||||
|
match shader_type {
|
||||||
|
ShaderType::VERTEX => { ShaderKind::Vertex }
|
||||||
|
ShaderType::FRAGMENT => { ShaderKind::Fragment }
|
||||||
|
ShaderType::GEOMETRY => { ShaderKind::Geometry }
|
||||||
|
ShaderType::TESSELLATION_CONTROL => { ShaderKind::TessControl }
|
||||||
|
ShaderType::TESSELLATION_EVALUATION => { ShaderKind::TessEvaluation }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +103,10 @@ pub struct CompiledGraphicsPipelineHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait CompiledGraphicsPipeline {
|
pub trait CompiledGraphicsPipeline {
|
||||||
|
fn new(filename: String,
|
||||||
|
device: Arc<Device>,
|
||||||
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||||
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> Self where Self: Sized;
|
||||||
fn get_name(&self) -> String;
|
fn get_name(&self) -> String;
|
||||||
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle>;
|
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle>;
|
||||||
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send>;
|
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send>;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use vulkano::pipeline::vertex::SingleBufferDefinition;
|
|||||||
use crate::util::vertex_3d::Vertex3D;
|
use crate::util::vertex_3d::Vertex3D;
|
||||||
use shade_runner as sr;
|
use shade_runner as sr;
|
||||||
use crate::canvas::shader::common::CompiledGraphicsPipelineResources;
|
use crate::canvas::shader::common::CompiledGraphicsPipelineResources;
|
||||||
|
use vulkano::memory::pool::PotentialDedicatedAllocation::Generic;
|
||||||
|
|
||||||
/// CanvasShader holds the pipeline and render pass for the input shader source
|
/// CanvasShader holds the pipeline and render pass for the input shader source
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -24,16 +25,92 @@ pub struct GenericShader {
|
|||||||
|
|
||||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||||
name: String,
|
name: String,
|
||||||
shader_types: HashSet<ShaderType>,
|
|
||||||
|
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl GenericShader {}
|
||||||
|
|
||||||
/// Gives CanvasShader the resource functions
|
/// Gives CanvasShader the resource functions
|
||||||
impl CompiledGraphicsPipelineResources for GenericShader {}
|
impl CompiledGraphicsPipelineResources for GenericShader {}
|
||||||
|
|
||||||
/// Convenience interface so we don't have to juggle shader types
|
/// Convenience interface so we don't have to juggle shader types
|
||||||
impl CompiledGraphicsPipeline for GenericShader {
|
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 {
|
fn get_name(&self) -> String {
|
||||||
self.name.clone()
|
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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,97 +23,53 @@ pub struct TextShader {
|
|||||||
|
|
||||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||||
name: String,
|
name: String,
|
||||||
shader_types: HashSet<ShaderType>,
|
|
||||||
|
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TextShader {}
|
||||||
|
|
||||||
/// Gives CanvasShader the resource functions
|
/// Gives CanvasShader the resource functions
|
||||||
impl CompiledGraphicsPipelineResources for TextShader {}
|
impl CompiledGraphicsPipelineResources for TextShader {}
|
||||||
|
|
||||||
/// Convenience interface so we don't have to juggle shader types
|
/// Convenience interface so we don't have to juggle shader types
|
||||||
impl CompiledGraphicsPipeline for TextShader {
|
impl CompiledGraphicsPipeline for TextShader {
|
||||||
fn get_name(&self) -> String {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle> {
|
|
||||||
self.handle.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
|
|
||||||
self.graphics_pipeline.clone().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recompile(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> TextShader {
|
|
||||||
TextShader::new(self.name,
|
|
||||||
self.device,
|
|
||||||
self.handle,
|
|
||||||
render_pass.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TextShader {
|
|
||||||
|
|
||||||
/// This will explode when the shader does not want to compile
|
/// This will explode when the shader does not want to compile
|
||||||
pub fn new(filename: String,
|
fn new(filename: String,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
handle: Arc<CompiledGraphicsPipelineHandle>,
|
handle: Arc<CompiledGraphicsPipelineHandle>,
|
||||||
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> TextShader {
|
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> TextShader {
|
||||||
let mut shader_types: HashSet<ShaderType> = vec![
|
|
||||||
ShaderType::VERTEX,
|
|
||||||
ShaderType::FRAGMENT,
|
|
||||||
].iter().cloned().collect();
|
|
||||||
|
|
||||||
let filenames = GenericShader::get_paths(filename.clone(), shader_types.clone());
|
let compiled_vertex = GenericShader::compile(
|
||||||
|
GenericShader::get_path(filename.clone(), ShaderType::VERTEX).into(),
|
||||||
|
device.clone(), ShaderType::VERTEX
|
||||||
|
);
|
||||||
|
|
||||||
// I guess this really herky intermediate store is going to be the most flexible way to
|
let vertex_entry_point = unsafe {
|
||||||
// create these pipelines?
|
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 mut modules: HashMap<ShaderType, (Entry, Arc<ShaderModule>)> = HashMap::default();
|
let compiled_fragment = GenericShader::compile(
|
||||||
|
GenericShader::get_path(filename.clone(), ShaderType::FRAGMENT).into(),
|
||||||
|
device.clone(), ShaderType::FRAGMENT
|
||||||
|
);
|
||||||
|
|
||||||
let mut entry_points: HashMap<ShaderType, GraphicsEntryPoint<ShaderSpecializationConstants, Input, Output, Layout>> = HashMap::default();
|
let fragment_entry_point = unsafe {
|
||||||
|
Some(compiled_fragment.1.graphics_entry_point(
|
||||||
for shader in filenames {
|
&CStr::from_bytes_with_nul_unchecked(b"main\0"),
|
||||||
let compiled_shader = sr::load_vertex(shader.1)
|
compiled_fragment.0.input.unwrap(),
|
||||||
.expect("Shader didn't compile");
|
compiled_fragment.0.output.unwrap(),
|
||||||
|
compiled_fragment.0.layout,
|
||||||
let vulkano_entry =
|
GenericShader::convert_vk(ShaderType::FRAGMENT),
|
||||||
sr::parse(&compiled_shader)
|
)).unwrap()
|
||||||
.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().clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
let stencil = DepthStencil {
|
let stencil = DepthStencil {
|
||||||
depth_compare: Compare::Less,
|
depth_compare: Compare::Less,
|
||||||
@@ -145,7 +101,7 @@ impl TextShader {
|
|||||||
|
|
||||||
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
|
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
|
||||||
|
|
||||||
.vertex_shader(entry_points.get(&ShaderType::VERTEX).unwrap().clone(), ShaderSpecializationConstants {
|
.vertex_shader(vertex_entry_point.clone(), ShaderSpecializationConstants {
|
||||||
first_constant: 0,
|
first_constant: 0,
|
||||||
second_constant: 0,
|
second_constant: 0,
|
||||||
third_constant: 0.0,
|
third_constant: 0.0,
|
||||||
@@ -155,7 +111,7 @@ impl TextShader {
|
|||||||
// Use a resizable viewport set to draw over the entire window
|
// Use a resizable viewport set to draw over the entire window
|
||||||
.viewports_dynamic_scissors_irrelevant(1)
|
.viewports_dynamic_scissors_irrelevant(1)
|
||||||
|
|
||||||
.fragment_shader(entry_points.get(&ShaderType::VERTEX).unwrap().clone(), ShaderSpecializationConstants {
|
.fragment_shader(fragment_entry_point.clone(), ShaderSpecializationConstants {
|
||||||
first_constant: 0,
|
first_constant: 0,
|
||||||
second_constant: 0,
|
second_constant: 0,
|
||||||
third_constant: 0.0,
|
third_constant: 0.0,
|
||||||
@@ -163,7 +119,6 @@ impl TextShader {
|
|||||||
|
|
||||||
.depth_stencil(stencil)
|
.depth_stencil(stencil)
|
||||||
|
|
||||||
|
|
||||||
// We have to indicate which subpass of which render pass this pipeline is going to be used
|
// 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.
|
// in. The pipeline will only be usable from this particular subpass.
|
||||||
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
||||||
@@ -174,7 +129,37 @@ impl TextShader {
|
|||||||
device: device,
|
device: device,
|
||||||
handle: handle.clone(),
|
handle: handle.clone(),
|
||||||
name: filename.clone(),
|
name: filename.clone(),
|
||||||
shader_types: shader_types.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_handle(&self) -> Arc<CompiledGraphicsPipelineHandle> {
|
||||||
|
self.handle.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
|
||||||
|
self.graphics_pipeline.clone().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recompile(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> TextShader {
|
||||||
|
TextShader::new(self.name,
|
||||||
|
self.device,
|
||||||
|
self.handle,
|
||||||
|
render_pass.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ pub fn main() {
|
|||||||
let mut accumulator_time: f32 = 0.0;
|
let mut accumulator_time: f32 = 0.0;
|
||||||
let mut current_time: f32 = timer.elap_time();
|
let mut current_time: f32 = timer.elap_time();
|
||||||
|
|
||||||
|
|
||||||
let image_data = load_raw(String::from("funky-bird.jpg"));
|
let image_data = load_raw(String::from("funky-bird.jpg"));
|
||||||
let image_dimensions_f = ((image_data.1).0 as f32, (image_data.1).1 as f32);
|
let image_dimensions_f = ((image_data.1).0 as f32, (image_data.1).1 as f32);
|
||||||
let image_dimensions_u = image_data.1;
|
let image_dimensions_u = image_data.1;
|
||||||
@@ -163,9 +162,11 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut canvas = CanvasFrame::new();
|
let mut canvas = CanvasFrame::new();
|
||||||
|
|
||||||
canvas.draw(&funky_sprite);
|
canvas.draw(&funky_sprite);
|
||||||
canvas.draw(&sfml_sprite);
|
|
||||||
canvas.draw(&compu_sprite1);
|
// canvas.draw(&sfml_sprite);
|
||||||
|
// canvas.draw(&compu_sprite1);
|
||||||
|
|
||||||
canvas.draw(&test_polygon);
|
canvas.draw(&test_polygon);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ use crate::compute::compu_buffer::{CompuBuffers, CompuBufferHandle};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vulkano::pipeline::depth_stencil::{DynamicStencilValue, StencilFaceFlags};
|
use vulkano::pipeline::depth_stencil::{DynamicStencilValue, StencilFaceFlags};
|
||||||
use crate::canvas::shader::common::CompiledGraphicsPipelineHandle;
|
use crate::canvas::shader::common::CompiledGraphicsPipelineHandle;
|
||||||
|
use crate::canvas::shader::generic_shader::GenericShader;
|
||||||
|
use crate::canvas::shader::text_shader::TextShader;
|
||||||
|
|
||||||
/// VKProcessor holds the vulkan instance information, the swapchain, and the compute and canvas states
|
/// VKProcessor holds the vulkan instance information, the swapchain, and the compute and canvas states
|
||||||
///
|
///
|
||||||
@@ -155,9 +157,10 @@ impl<'a> VkProcessor<'a> {
|
|||||||
|
|
||||||
/// A hardcoded list of shaders which can be proloaded from this function
|
/// A hardcoded list of shaders which can be proloaded from this function
|
||||||
pub fn preload_shaders(&mut self) {
|
pub fn preload_shaders(&mut self) {
|
||||||
self.canvas.load_shader(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
|
self.canvas.load_shader::<GenericShader>(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
|
||||||
self.canvas.load_shader(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
|
self.canvas.load_shader::<GenericShader>(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
|
||||||
self.canvas.load_shader(String::from("simple_image"), self.physical.clone(), self.capabilities.clone());
|
self.canvas.load_shader::<GenericShader>(String::from("simple_image"), self.physical.clone(), self.capabilities.clone());
|
||||||
|
self.canvas.load_shader::<TextShader>(String::from("simple_text"), self.physical.clone(), self.capabilities.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// O(n) Lookup for the matching texture string
|
/// O(n) Lookup for the matching texture string
|
||||||
@@ -256,6 +259,7 @@ impl<'a> VkProcessor<'a> {
|
|||||||
drop(g);
|
drop(g);
|
||||||
|
|
||||||
let g = hprof::enter("Push draw commands to command buffer");
|
let g = hprof::enter("Push draw commands to command buffer");
|
||||||
|
|
||||||
// Add the draw commands
|
// Add the draw commands
|
||||||
let mut command_buffer = self.canvas.draw_commands(command_buffer, framebuffers, image_num);
|
let mut command_buffer = self.canvas.draw_commands(command_buffer, framebuffers, image_num);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user