hitting this damn shader module again. Very unergonomic interface with the fact that the entry point doesn't just own the shadermodule

master
mitchellhansen 5 years ago
parent 3db8eaf006
commit 5a888a4163

@ -1,17 +1,23 @@
use vulkano::device::{Device, Queue};
use vulkano::instance::{PhysicalDevice, QueueFamily};
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};
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;
use std::collections::{HashSet, HashMap};
use shade_runner::{Layout, Output, Input};
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;
/// Inheriting this gives private functions to grab resources
trait CompiledGraphicsPipelineResources {
@ -42,9 +48,14 @@ trait CompiledGraphicsPipelineResources {
shader_path.push(PathBuf::from(filename.clone() + ".geom"));
paths.push((shader_type, shader_path));
}
ShaderType::TESSELLATION => {
ShaderType::TESSELLATION_CONTROL => {
let mut shader_path = shader_path.clone();
shader_path.push(PathBuf::from(filename.clone() + ".tess"));
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));
}
}
@ -116,84 +127,136 @@ impl CompiledGraphicsPipeline for GenericShader {
fn recompile(self, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
GenericShader::new(self.name,
self.shader_types,
self.device,
self.handle,
render_pass.clone())
}
}
impl GenericShader {
/*
/// This will explode when the shader does not want to compile
pub fn new(filename: String,
shader_types: HashSet<ShaderType>,
device: Arc<Device>,
handle: Arc<CompiledGraphicsPipelineHandle>,
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>) -> GenericShader {
Realistically, what should the API for this thing look like...
let filenames = GenericShader::get_paths(filename.clone(), shader_types.clone());
It's going to just generate a pipeline. But that consists of loading and compiling various shaders,
and generating a pipeline for those shaders and other customer behaviour.
This best works I think if I allow users to
A.) impl from a base trait which allows resource lookup
B.) Generate 1 of each of the types of shaders
C.) Modify specilization constants, whatever that might mean
D.) impl from a base trait which defines it's interface
// TODO: better compile message, run til successful compile
*/
impl GenericShader {
pub fn ret(&self) -> Option<GraphicsEntryPoint<
ShaderSpecializationConstants,
Input,
Output,
Layout>> {
for shader in filenames {
match shader.0 {
ShaderType::VERTEX => {
let shader = sr::load(filenames.0, filenames.1)
let compiled_shader = sr::load_vertex("dfqwefqwef")
.expect("Shader didn't compile");
let vulkano_entry =
sr::parse(&shader)
sr::parse(&compiled_shader)
.expect("failed to parse");
}
ShaderType::FRAGMENT => {
}
ShaderType::GEOMETRY => {
let shader_module: Arc<ShaderModule> = unsafe {
ShaderModule::from_words(self.device.clone(), &compiled_shader.spriv.clone())
}.unwrap();
}
ShaderType::TESSELLATION => {
let s = ShaderType::VERTEX;
let shader_type = match s {
ShaderType::VERTEX => { GraphicsShaderType::Vertex }
ShaderType::FRAGMENT => { GraphicsShaderType::Fragment }
ShaderType::GEOMETRY => { GraphicsShaderType::Geometry(GeometryShaderExecutionMode::Triangles) }
ShaderType::TESSELLATION_CONTROL => { GraphicsShaderType::TessellationControl }
ShaderType::TESSELLATION_EVALUATION => { GraphicsShaderType::TessellationEvaluation }
};
unsafe {
Some(GraphicsEntryPoint {
module: &shader_module,
name: &CStr::from_bytes_with_nul_unchecked(b"main\0"),
input: vulkano_entry.input.unwrap(),
layout: vulkano_entry.layout,
output: vulkano_entry.output.unwrap(),
ty: shader_type,
marker: PhantomData::default(),
})
}
}
}
/// 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());
let fragment_shader_module: Arc<ShaderModule> = unsafe {
let filenames1 = GenericShader::get_path(filename.clone());
let shader1 = sr::load(filenames1.0, filenames1.1)
.expect("Shader didn't compile");
ShaderModule::from_words(device.clone(), &shader1.fragment.clone())
}.unwrap();
// let mut c = Vec::new();
let vertex_shader_module: Arc<ShaderModule> = unsafe {
let mut vertex_entry_point : Option<GraphicsEntryPoint<ShaderSpecializationConstants,Input,Output,Layout>>
= None;
let mut fragment_entry_point : Option<GraphicsEntryPoint<ShaderSpecializationConstants,Input,Output,Layout>>
= None;
let filenames1 = GenericShader::get_path(filename.clone());
let shader1 = sr::load(filenames1.0, filenames1.1)
for shader in filenames {
let compiled_shader = sr::load_vertex(shader.1)
.expect("Shader didn't compile");
ShaderModule::from_words(device.clone(), &shader1.vertex.clone())
let vulkano_entry =
sr::parse(&compiled_shader)
.expect("failed to parse");
let shader_module: Arc<ShaderModule> = unsafe {
ShaderModule::from_words(device.clone(), &compiled_shader.spriv.clone())
}.unwrap();
let shader_type = match shader.0 {
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 frag_entry_point = unsafe {
Some(fragment_shader_module.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"),
vulkano_entry.frag_input,
vulkano_entry.frag_output,
vulkano_entry.frag_layout,
GraphicsShaderType::Fragment))
let entry_point: Option<GraphicsEntryPoint<
ShaderSpecializationConstants,
Input,
Output,
Layout>> = unsafe {
Some(GraphicsEntryPoint {
module: &shader_module,
name: &CStr::from_bytes_with_nul_unchecked(b"main\0"),
input: vulkano_entry.input.unwrap(),
layout: vulkano_entry.layout,
output: vulkano_entry.output.unwrap(),
ty: shader_type,
marker: PhantomData::default(),
})
};
let vertex_entry_point = unsafe {
Some(vertex_shader_module.graphics_entry_point(CStr::from_bytes_with_nul_unchecked(b"main\0"),
vulkano_entry.vert_input,
vulkano_entry.vert_output,
vulkano_entry.vert_layout,
GraphicsShaderType::Vertex))
let shader_type = match shader.0 {
ShaderType::VERTEX => { vertex_entry_point = Some(entry_point.clone().unwrap()) }
ShaderType::FRAGMENT => { fragment_entry_point = Some(entry_point.clone().unwrap()) }
_ => {}
};
// c.push((entry_point.unwrap().clone(), shader_module.clone()));
}
let stencil = DepthStencil {
depth_compare: Compare::Less,
depth_write: true,
@ -218,13 +281,13 @@ impl GenericShader {
},
};
GenericShader {
graphics_pipeline: Some(Arc::new(GraphicsPipeline::start()
graphics_pipeline:
Some(Arc::new(GraphicsPipeline::start()
.vertex_input(SingleBufferDefinition::<Vertex3D>::new())
.vertex_shader(vertex_entry_point.clone().unwrap(), ShaderSpecializationConstants {
.vertex_shader(vertex_entry_point.unwrap(), ShaderSpecializationConstants {
first_constant: 0,
second_constant: 0,
third_constant: 0.0,
@ -234,7 +297,7 @@ impl GenericShader {
// Use a resizable viewport set to draw over the entire window
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(frag_entry_point.clone().unwrap(), ShaderSpecializationConstants {
.fragment_shader(fragment_entry_point.unwrap(), ShaderSpecializationConstants {
first_constant: 0,
second_constant: 0,
third_constant: 0.0,
@ -242,6 +305,7 @@ impl GenericShader {
.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())

@ -1,5 +1,5 @@
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use vulkano::buffer::{BufferAccess, BufferUsage, ImmutableBuffer, CpuAccessibleBuffer};
use std::sync::Arc;
use vulkano::format::{ClearValue, Format, R8Unorm};
@ -21,7 +21,7 @@ use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
use crate::canvas::canvas_frame::CanvasFrame;
use std::hash::Hash;
use crate::canvas::canvas_text::{CanvasText, CanvasTextHandle};
use crate::canvas::canvas_shader::{GenericShader, CanvasShaderHandle, CompiledGraphicsPipelineHandle, CompiledGraphicsPipeline};
use crate::canvas::canvas_shader::{GenericShader, CanvasShaderHandle, CompiledGraphicsPipelineHandle, CompiledGraphicsPipeline, ShaderType};
use crate::canvas::canvas_buffer::{CanvasImage, CanvasTexture, CanvasTextCache};
use crate::util::vertex_3d::Vertex3D;
use vulkano::pipeline::depth_stencil::{StencilFaceFlags, DynamicStencilValue};
@ -51,14 +51,6 @@ pub trait Drawable {
}
}
/// Legacy ShaderType enum for single type shaders.
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum ShaderType {
SOLID = 0,
TEXTURED = 1,
IMAGE = 2,
}
/// Typed wrapper for a u32 texture handle (index id)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct CanvasTextureHandle {
@ -344,7 +336,6 @@ impl CanvasState {
/// Takes physical and capabilities as we don't store that in Canvas
pub fn load_shader(&mut self,
filename: String,
shader_type: ShaderType,
physical: PhysicalDevice,
capabilities: Capabilities) -> Option<Arc<CompiledGraphicsPipelineHandle>> {

@ -6,6 +6,7 @@ use vulkano::descriptor::pipeline_layout::PipelineLayout;
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, PersistentDescriptorSetBuf};
use image::ImageBuffer;
use image::Rgba;
use shade_runner::Layout;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct CompuBufferHandle {
@ -68,8 +69,8 @@ impl CompuBuffers {
self.dimensions
}
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>)
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((),
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<Layout>>>)
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<Layout>>>, ((((),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> {

@ -5,7 +5,7 @@ use std::ffi::CStr;
use std::path::PathBuf;
use shade_runner as sr;
use vulkano::descriptor::pipeline_layout::PipelineLayout;
use shade_runner::{CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry};
use shade_runner::{CompileError, Layout, Input, Output, CompiledShaders, Entry, CompiledShader};
use shaderc::CompileOptions;
use vulkano::pipeline::shader::{ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry};
use crate::compute::compu_buffer::{CompuBuffers, CompuBufferHandle};
@ -20,12 +20,12 @@ pub struct CompuKernel {
handle: Arc<CompuKernelHandle>,
compute_pipeline: Option<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>>,
compute_pipeline: Option<std::sync::Arc<ComputePipeline<PipelineLayout<Layout>>>>,
compute_kernel_path: PathBuf,
name: String,
shader: CompiledShaders,
shader: CompiledShader,
entry: Entry,
shader_module: Arc<ShaderModule>,
device: Arc<Device>,
@ -61,7 +61,7 @@ impl CompuKernel {
.expect("Failed to parse");
let shader_module = unsafe {
vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader.compute)
vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader.spriv)
}.unwrap();
@ -82,7 +82,7 @@ impl CompuKernel {
}
}
pub fn get_pipeline(&mut self) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
pub fn get_pipeline(&mut self) -> std::sync::Arc<ComputePipeline<PipelineLayout<Layout>>> {
match self.compute_pipeline.clone() {
Some(t) => t,
@ -91,7 +91,7 @@ impl CompuKernel {
unsafe {
ComputePipeline::new(self.device.clone(), &self.shader_module.compute_entry_point(
CStr::from_bytes_with_nul_unchecked(b"main\0"),
self.entry.compute_layout.clone()), &self.specialization_constants,
self.entry.layout.clone()), &self.specialization_constants,
).unwrap()
}
}));
@ -100,11 +100,11 @@ impl CompuKernel {
}
}
pub fn recompile_kernel(&mut self) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
pub fn recompile_kernel(&mut self) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::Layout>>> {
self.compile_kernel(String::from(self.compute_kernel_path.clone().to_str().unwrap()))
}
pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc<ComputePipeline<PipelineLayout<Layout>>> {
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
self.compute_kernel_path = CompuKernel::get_path(filename);
@ -118,7 +118,7 @@ impl CompuKernel {
.expect("Failed to parse");
self.shader_module = unsafe {
vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &self.shader.compute)
vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &self.shader.spriv)
}.unwrap();
self.get_pipeline()

@ -11,12 +11,12 @@ use winit::Window;
use crate::compute::compu_state::CompuState;
use vulkano::image::ImageUsage;
use crate::compute::compu_frame::CompuFrame;
use crate::canvas::canvas_state::{CanvasState, CanvasTextureHandle, CanvasImageHandle, ShaderType};
use crate::canvas::canvas_state::{CanvasState, CanvasTextureHandle, CanvasImageHandle};
use crate::canvas::canvas_frame::CanvasFrame;
use crate::compute::compu_kernel::{CompuKernel, CompuKernelHandle};
use crate::compute::compu_buffer::{CompuBuffers, CompuBufferHandle};
use std::time::Duration;
use crate::canvas::canvas_shader::{CanvasShaderHandle, CompiledGraphicsPipeline, CompiledGraphicsPipelineHandle};
use crate::canvas::canvas_shader::{CanvasShaderHandle, CompiledGraphicsPipeline, CompiledGraphicsPipelineHandle, ShaderType};
use vulkano::pipeline::depth_stencil::{DynamicStencilValue, StencilFaceFlags};
/// VKProcessor holds the vulkan instance information, the swapchain, and the compute and canvas states
@ -155,9 +155,9 @@ impl<'a> VkProcessor<'a> {
/// A hardcoded list of shaders which can be proloaded from this function
pub fn preload_shaders(&mut self) {
self.canvas.load_shader(String::from("color-passthrough"), ShaderType::SOLID, self.physical.clone(), self.capabilities.clone());
self.canvas.load_shader(String::from("simple_texture"), ShaderType::TEXTURED, self.physical.clone(), self.capabilities.clone());
self.canvas.load_shader(String::from("simple_image"), ShaderType::IMAGE, self.physical.clone(), self.capabilities.clone());
self.canvas.load_shader(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(String::from("simple_image"), self.physical.clone(), self.capabilities.clone());
}
/// O(n) Lookup for the matching texture string

Loading…
Cancel
Save