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}; 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, OneVertexOneInstanceDefinition, Vertex}; use shade_runner as sr; use crate::canvas::managed::shader::shader_common::{ShaderType, CompiledGraphicsPipelineResources, CompiledGraphicsPipeline}; use crate::canvas::managed::handles::CompiledShaderHandle; use crate::canvas::managed::shader::generic_shader::GenericShader; use crate::canvas::managed::shader::dynamic_vertex::RuntimeVertexDef; use crate::canvas::managed::ShaderSpecializationConstants; use crate::util::vertex::ColorVertex2D; /// CanvasShader holds the pipeline and render pass for the input shader source #[derive(Clone)] pub struct TextShader { graphics_pipeline: Option>, handle: Arc, name: String, device: Arc, renderpass: Arc, } impl TextShader {} /// Gives CanvasShader the resource functions impl CompiledGraphicsPipelineResources for TextShader {} /// Convenience interface so we don't have to juggle shader types impl CompiledGraphicsPipeline for TextShader { /// This will explode when the shader does not want to compile fn new(filename: String, device: Arc, handle: Arc, render_pass: Arc) -> TextShader { let compiled_vertex = GenericShader::compile( GenericShader::get_path(filename.clone(), ShaderType::VERTEX).into(), 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 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, }, }; let vertex_definition = RuntimeVertexDef::from_primitive(0); TextShader { graphics_pipeline: Some(Arc::new(GraphicsPipeline::start() .vertex_input(SingleBufferDefinition::::new()) //.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(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(), 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) -> TextShader { TextShader::new::(self.name, self.device, self.handle, self.renderpass.clone()) } }