use vulkano::pipeline::GraphicsPipelineAbstract; use std::sync::Arc; use std::collections::{HashSet, HashMap}; use vulkano::device::Device; use vulkano::framebuffer::{RenderPassAbstract, Subpass}; use vulkano::pipeline::GraphicsPipeline; use vulkano::pipeline::shader::{GraphicsEntryPoint, ShaderModule, GraphicsShaderType, GeometryShaderExecutionMode, ShaderInterfaceDef}; use shade_runner::{Input, Output, Layout, Entry}; use std::ffi::CStr; use std::marker::PhantomData; use vulkano::pipeline::depth_stencil::{DepthStencil, Compare, DepthBounds, Stencil, StencilOp}; use vulkano::pipeline::vertex::{SingleBufferDefinition, VertexDefinition}; use crate::util::vertex_3d::Vertex3D; use shade_runner as sr; use vulkano::memory::pool::PotentialDedicatedAllocation::Generic; use vulkano::SafeDeref; use crate::canvas::managed::shader::shader_common::{ShaderType, CompiledGraphicsPipelineResources, CompiledGraphicsPipeline}; use crate::canvas::managed::handles::CompiledGraphicsPipelineHandle; use crate::canvas::managed::shader::dynamic_vertex::RuntimeVertexDef; use crate::canvas::managed::ShaderSpecializationConstants; /// CanvasShader holds the pipeline and render pass for the input shader source #[derive(Clone)] pub struct GenericShader { graphics_pipeline: Option>, handle: Arc, name: String, device: Arc, renderpass: Arc, } 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, handle: Arc, render_pass: Arc) -> 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() }; let vertex_definition = RuntimeVertexDef::from_primitive(0); GenericShader { graphics_pipeline: Some(Arc::new(GraphicsPipeline::start() //SingleBufferDefinition:: .vertex_input(vertex_definition) .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_simple_depth() // 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(), renderpass: render_pass.clone(), } } fn get_name(&self) -> String { self.name.clone() } fn get_handle(&self) -> Arc { self.handle.clone() } fn get_pipeline(&self) -> Arc { self.graphics_pipeline.clone().unwrap() } fn get_renderpass(&self) -> Arc { self.renderpass.clone() } fn recompile(self, render_pass: Arc) -> GenericShader { GenericShader::new(self.name, self.device, self.handle, render_pass.clone()) } }