diff --git a/resources/shaders/simple.fragment b/resources/shaders/simple.fragment new file mode 100644 index 00000000..f40b64bc --- /dev/null +++ b/resources/shaders/simple.fragment @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 0) out vec4 f_color; + +void main() { + f_color = vec4(1.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/simple.vertex b/resources/shaders/simple.vertex new file mode 100644 index 00000000..eca24008 --- /dev/null +++ b/resources/shaders/simple.vertex @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 0) in vec2 position; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e99535a0..32bfd13a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,6 @@ #![allow(unused_variables)] #![allow(unused_mut)] - -/* extern crate cgmath; extern crate image; extern crate nalgebra as na; @@ -54,8 +52,8 @@ mod util; mod button; mod workpiece; -/* +/* What next? Second sprite for rendering paths at x10 or so resolution color bucketing @@ -205,32 +203,9 @@ fn main() { window.display(); } } -*/ - - - - - -//use vulkano::buffer::{BufferAccess, BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer, ImmutableBuffer}; -//use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; -//use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, PersistentDescriptorSetBuf, StdDescriptorPoolAlloc}; -//use vulkano::descriptor::pipeline_layout::PipelineLayout; -//use vulkano::device::{Device, DeviceExtensions, Queue, QueuesIter}; -//use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract, Subpass}; -//use vulkano::image::SwapchainImage; -//use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice, QueueFamily}; -//use vulkano::pipeline::{ComputePipeline, GraphicsPipeline}; -//use vulkano::pipeline::viewport::Viewport; -//use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError}; -//use vulkano::swapchain; -//use vulkano::sync::{FlushError, GpuFuture}; -//use vulkano::sync; -//use vulkano_win::VkSurfaceBuild; -//use winit::{Event, EventsLoop, Window, WindowBuilder, WindowEvent}; -//use shade_runner::{ComputeLayout, CompileError}; -//use shaderc::CompileOptions; +/* use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer, ImmutableBuffer, BufferAccess}; use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, StdDescriptorPoolAlloc}; @@ -258,6 +233,8 @@ use winit::{Event, EventsLoop, Window, WindowBuilder, WindowEvent}; use vulkano_win::VkSurfaceBuild; use vulkano::SafeDeref; + + fn main() { let instance = { let extensions = vulkano_win::required_extensions(); @@ -751,3 +728,4 @@ fn window_size_dependent_setup( }).collect::>() } +*/ \ No newline at end of file diff --git a/src/vkprocessor.rs b/src/vkprocessor.rs index 065459d4..c148d623 100644 --- a/src/vkprocessor.rs +++ b/src/vkprocessor.rs @@ -3,7 +3,7 @@ use vulkano::command_buffer::AutoCommandBufferBuilder; use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet, StdDescriptorPoolAlloc}; use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue}; use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice, QueueFamily}; -use vulkano::pipeline::ComputePipeline; +use vulkano::pipeline::{ComputePipeline, GraphicsPipeline}; use vulkano::sync::GpuFuture; use vulkano::sync; use std::time::SystemTime; @@ -15,14 +15,17 @@ use image::{DynamicImage, ImageBuffer}; use image::GenericImageView; use vulkano::descriptor::pipeline_layout::PipelineLayout; use image::GenericImage; -use shade_runner::{ComputeLayout, CompileError}; +use shade_runner::{ComputeLayout, CompileError, FragLayout}; use vulkano::descriptor::descriptor_set::PersistentDescriptorSetBuf; use shaderc::CompileOptions; +use vulkano::framebuffer::Subpass; +use vulkano::pipeline::shader::GraphicsShaderType; pub struct VkProcessor<'a> { pub instance: Arc, pub physical: PhysicalDevice<'a>, - pub pipeline: Option>>>, + pub pipeline: Option>>>, + pub compute_pipeline: (), pub device: Arc, pub queues: QueuesIter, pub queue: Arc, @@ -47,6 +50,7 @@ impl<'a> VkProcessor<'a> { instance: instance.clone(), physical: physical.clone(), pipeline: Option::None, + compute_pipeline: Option::None, device: device, queue: queues.next().unwrap(), queues: queues, @@ -88,6 +92,103 @@ impl<'a> VkProcessor<'a> { vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.compute) }.unwrap(); + let compute_pipeline = Arc::new({ + unsafe { + ComputePipeline::new(self.device.clone(), &x.compute_entry_point( + CStr::from_bytes_with_nul_unchecked(b"main\0"), + vulkano_entry.compute_layout), &(), + ).unwrap() + } + }); + + self.compute_pipeline = Some(compute_pipeline); + } + + pub fn compile_shaders(&mut self, filename: String) { + + let project_root = + std::env::current_dir() + .expect("failed to get root directory"); + + let mut shader_path = project_root.clone(); + shader_path.push(PathBuf::from("resources/shaders/")); + + let mut vertex_shader_path = project_root.clone() + .push(PathBuf::from("resources/shaders/")); + vertex_shader_path.push(PathBuf::from(filename.clone())); + vertex_shader_path.push(PathBuf::from(".vertex")); + + let mut fragment_shader_path = project_root.clone() + .push(PathBuf::from("resources/shaders/")); + vertex_shader_path.push(PathBuf::from(filename.clone())); + vertex_shader_path.push(PathBuf::from(".fragment")); + + let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); + options.add_macro_definition("SETTING_POS_X", Some("0")); + options.add_macro_definition("SETTING_POS_Y", Some("1")); + options.add_macro_definition("SETTING_BUCKETS_START", Some("2")); + options.add_macro_definition("SETTING_BUCKETS_LEN", Some("2")); + + let shader = + sr::load(vertex_shader_path, fragment_shader_path) + .expect("Failed to compile"); + + let vulkano_entry = + sr::parse(&shader) + .expect("failed to parse"); + + let x = unsafe { + vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.fragment) + }.unwrap(); + + + let frag_entry_point = unsafe { + &x.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 vert_entry_point = unsafe { + &x.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) + }; + + + // Before we draw we have to create what is called a pipeline. This is similar to an OpenGL + // program, but much more specific. + self.pipeline = Option::Some(Arc::new(GraphicsPipeline::start() + // We need to indicate the layout of the vertices. + // The type `SingleBufferDefinition` actually contains a template parameter corresponding + // to the type of each vertex. But in this code it is automatically inferred. + .vertex_input_single_buffer() + // A Vulkan shader can in theory contain multiple entry points, so we have to specify + // which one. The `main` word of `main_entry_point` actually corresponds to the name of + // the entry point. + .vertex_shader(vert_entry_point, ()) + // The content of the vertex buffer describes a list of triangles. + .triangle_list() + // Use a resizable viewport set to draw over the entire window + .viewports_dynamic_scissors_irrelevant(1) + // See `vertex_shader`. + .fragment_shader(frag_entry_point, ()) + // 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()) + // Now that our builder is filled, we call `build()` to obtain an actual pipeline. + .build(device.clone()) + .unwrap())); + + + + + + let x = unsafe { + vulkano::pipeline::shader::ShaderModule::from_words(self.device.clone(), &shader.fragment) + }.unwrap(); + let pipeline = Arc::new({ unsafe { ComputePipeline::new(self.device.clone(), &x.compute_entry_point( @@ -179,6 +280,37 @@ impl<'a> VkProcessor<'a> { self.settings_buffer = Some(settings_buffer); } + pub fn create_renderpass(&mut self) { + + let render_pass = Arc::new(vulkano::single_pass_renderpass!( + self.device.clone(), + attachments: { + // `color` is a custom name we give to the first and only attachment. + color: { + // `load: Clear` means that we ask the GPU to clear the content of this + // attachment at the start of the drawing. + load: Clear, + // `store: Store` means that we ask the GPU to store the output of the draw + // in the actual image. We could also ask it to discard the result. + store: Store, + // `format: ` indicates the type of the format of the image. This has to + // be one of the types of the `vulkano::format` module (or alternatively one + // of your structs that implements the `FormatDesc` trait). Here we use the + // same format as the swapchain. + format: swapchain.format(), + // TODO: + samples: 1, + } + }, + pass: { + // We use the attachment named `color` as the one and only color attachment. + color: [color], + // No depth-stencil attachment is indicated with empty brackets. + depth_stencil: {} + } + ).unwrap()); + } + pub fn run_kernel(&mut self) { println!("Running Kernel...");