diff --git a/Cargo.toml b/Cargo.toml index 7f158ddf..df50f314 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,13 +11,13 @@ simple-stopwatch="0.1.4" nalgebra = "0.18.0" image = "0.21.2" rand = "0.6.5" -#vulkano = "0.12.0" -vulkano = {path = "../vulkano/vulkano"} -#vulkano-shaders = "0.12.0" -#vulkano-win = "0.13.0" +vulkano = "0.13.0" +#vulkano = {path = "../vulkano/vulkano"} +vulkano-shaders = "0.13.0" +vulkano-win = "0.13.0" time = "0.1.38" shaderc = "0.5.0" -#shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"} -shade_runner = {path = "../shade_runner"} +shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"} +#shade_runner = {path = "../shade_runner"} winit = "0.19.1" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c7ea55a6..e99535a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ #![allow(unused_variables)] #![allow(unused_mut)] + +/* extern crate cgmath; extern crate image; extern crate nalgebra as na; @@ -58,7 +60,6 @@ What next? Second sprite for rendering paths at x10 or so resolution color bucketing - Textures and Sprites cannot live in the same struct as there is no way for a sprite to own its texture and become a single object (rust self-referencing structs) @@ -81,8 +82,6 @@ frequent updates to the screen... Let's take a look at how easy it would be to replace SFML... */ - - fn main() { let font = Font::from_file("resources/fonts/sansation.ttf").unwrap(); @@ -206,13 +205,12 @@ 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}; @@ -553,7 +551,7 @@ void main() { vulkano::pipeline::shader::ShaderModule::from_words(device.clone(), &shader.compute) }.unwrap(); - let pipeline = Arc::new({ + let c_pipeline = Arc::new({ unsafe { ComputePipeline::new(device.clone(), &x.compute_entry_point( CStr::from_bytes_with_nul_unchecked(b"main\0"), @@ -561,7 +559,82 @@ void main() { ).unwrap() } }); - } + + let project_root = + std::env::current_dir() + .expect("failed to get root directory"); + + let mut compute_path = project_root.clone(); + compute_path.push(PathBuf::from("resources/images/")); + compute_path.push(PathBuf::from("funky-bird.jpg")); + + let img = image::open(compute_path).expect("Couldn't find image"); + + let xy = img.dimensions(); + + let data_length = xy.0 * xy.1 * 4; + let pixel_count = img.raw_pixels().len(); + println!("Pixel count {}", pixel_count); + + let mut image_buffer = Vec::new(); + if pixel_count != data_length as usize { + println!("Creating apha channel..."); + for i in img.raw_pixels().iter() { + if (image_buffer.len() + 1) % 4 == 0 { + image_buffer.push(255); + } + image_buffer.push(*i); + } + image_buffer.push(255); + } else { + image_buffer = img.raw_pixels(); + } + + println!("Buffer length {}", image_buffer.len()); + println!("Size {:?}", xy); + + println!("Allocating Buffers..."); + + // Pull out the image data and place it in a buffer for the kernel to write to and for us to read from + let write_buffer = { + let mut buff = image_buffer.iter(); + let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() + }; + + + // Pull out the image data and place it in a buffer for the kernel to read from + let read_buffer = { + let mut buff = image_buffer.iter(); + let data_iter = (0..data_length).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() + }; + + + // A buffer to hold many i32 values to use as settings + let settings_buffer = { + let vec = vec![xy.0, xy.1]; + let mut buff = vec.iter(); + let data_iter = + (0..2).map(|n| *(buff.next().unwrap())); + CpuAccessibleBuffer::from_iter(device.clone(), + BufferUsage::all(), + data_iter).unwrap() + }; + + println!("Done"); + + // Create the data descriptor set for our previously created shader pipeline + let mut set = + PersistentDescriptorSet::start(c_pipeline.clone(), 0) + .add_buffer(write_buffer.clone()).unwrap() + .add_buffer(read_buffer.clone()).unwrap() + .add_buffer(settings_buffer.clone()).unwrap(); + + let mut set = Arc::new(set.build().unwrap()); + + + // In order to draw, we have to build a *command buffer*. The command buffer object holds // the list of commands that are going to be executed. @@ -572,7 +645,13 @@ void main() { // // Note that we have to pass a queue family when we create the command buffer. The command // buffer will only be executable on that given queue family. - let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap() + let command_buffer = + AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) + .unwrap() + + .dispatch([xy.0, xy.1, 1], + c_pipeline.clone(), + set.clone(), ()).unwrap() // Before we can draw, we have to *enter a render pass*. There are two methods to do // this: `draw_inline` and `draw_secondary`. The latter is a bit more advanced and is // not covered here. @@ -583,6 +662,7 @@ void main() { .begin_render_pass(framebuffers[image_num].clone(), false, clear_values) .unwrap() + // We are now inside the first subpass of the render pass. We add a draw command. // // The last two parameters contain the list of resources to pass to the shaders. @@ -624,7 +704,7 @@ void main() { previous_frame_end = Box::new(sync::now(device.clone())) as Box<_>; } } - + } // Note that in more complex programs it is likely that one of `acquire_next_image`, // `command_buffer::submit`, or `present` will block for some time. This happens when the // GPU's queue is full and the driver has to wait until the GPU finished some work. @@ -671,5 +751,3 @@ fn window_size_dependent_setup( }).collect::>() } - -*/ \ No newline at end of file