|
|
|
@ -20,7 +20,7 @@ use sfml::system::Vector2 as sfVec2;
|
|
|
|
|
use sfml::window::*;
|
|
|
|
|
use sfml::window::{Event, Key, Style};
|
|
|
|
|
|
|
|
|
|
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
|
|
|
|
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer, ImmutableBuffer, BufferAccess};
|
|
|
|
|
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
|
|
|
|
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
|
|
|
|
use vulkano::device::{Device, DeviceExtensions};
|
|
|
|
@ -31,6 +31,7 @@ use vulkano::sync;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
use std::result;
|
|
|
|
|
|
|
|
|
|
use crate::input::Input;
|
|
|
|
|
use crate::slider::Slider;
|
|
|
|
@ -127,30 +128,6 @@ impl<'t> Effect for Edge<'t> {
|
|
|
|
|
}
|
|
|
|
|
// =================================================
|
|
|
|
|
|
|
|
|
|
fn surrounding_pixels(x: u32, y: u32, img: &DynamicImage) -> Vec<image::Rgba<u8>> {
|
|
|
|
|
|
|
|
|
|
let mut pixels: Vec<image::Rgba<u8>> = Vec::new();
|
|
|
|
|
|
|
|
|
|
if img.in_bounds(x+1, y+1) {pixels.push(img.get_pixel(x+1, y+1))}
|
|
|
|
|
if img.in_bounds(x+1, y) {pixels.push(img.get_pixel(x+1, y))}
|
|
|
|
|
if img.in_bounds(x, y+1) {pixels.push(img.get_pixel(x, y+1))}
|
|
|
|
|
|
|
|
|
|
if x > 0 {
|
|
|
|
|
if img.in_bounds(x-1, y+1) {pixels.push(img.get_pixel(x-1, y+1))}
|
|
|
|
|
if img.in_bounds(x-1, y) {pixels.push(img.get_pixel(x-1, y))}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if y > 0 {
|
|
|
|
|
if img.in_bounds(x+1, y-1) {pixels.push(img.get_pixel(x+1, y-1))}
|
|
|
|
|
if img.in_bounds(x, y-1) {pixels.push(img.get_pixel(x, y-1))}
|
|
|
|
|
if x > 0 {
|
|
|
|
|
if img.in_bounds(x - 1, y - 1) { pixels.push(img.get_pixel(x - 1, y - 1)) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pixels
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
|
|
|
|
|
// Create the vulkan instance, device, and device queue
|
|
|
|
@ -162,6 +139,7 @@ fn main() {
|
|
|
|
|
&DeviceExtensions::none(),
|
|
|
|
|
[(queue_family, 0.5)].iter().cloned()).unwrap();
|
|
|
|
|
let queue = queues.next().unwrap();
|
|
|
|
|
|
|
|
|
|
println!("Device initialized");
|
|
|
|
|
|
|
|
|
|
let project_root = std::env::current_dir().expect("failed to get root directory");
|
|
|
|
@ -187,39 +165,47 @@ fn main() {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Load up the input image, determine some details
|
|
|
|
|
let mut img = image::open("resources/images/funky-bird.jpg").unwrap();
|
|
|
|
|
let mut img = image::open("resources/images/test.png").unwrap();
|
|
|
|
|
let xy = img.dimensions();
|
|
|
|
|
let data_length = xy.0*xy.1*4;
|
|
|
|
|
|
|
|
|
|
let mut image_buffer = Vec::new();
|
|
|
|
|
let pixel_count = img.raw_pixels().len();
|
|
|
|
|
println!("Pixel count {}", pixel_count);
|
|
|
|
|
|
|
|
|
|
for i in img.raw_pixels().iter() {
|
|
|
|
|
if (image_buffer.len() + 1) % 4 == 0 {
|
|
|
|
|
image_buffer.push(255);
|
|
|
|
|
let mut image_buffer = Vec::new();
|
|
|
|
|
if pixel_count != data_length as usize {
|
|
|
|
|
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(*i);
|
|
|
|
|
image_buffer.push(255);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
image_buffer = img.raw_pixels();
|
|
|
|
|
}
|
|
|
|
|
image_buffer.push(255);
|
|
|
|
|
|
|
|
|
|
println!("Buffer length {}", data_length);
|
|
|
|
|
println!("Buffer length {}", image_buffer.len());
|
|
|
|
|
println!("Size {:?}", xy);
|
|
|
|
|
|
|
|
|
|
println!("Allocating Buffers...");
|
|
|
|
|
{
|
|
|
|
|
// Pull out the image data and place it in a sync'd CPU<->GPU buffer
|
|
|
|
|
let data_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 q = ImmutableBuffer::from_data(image_buffer.clone(), BufferUsage::all(), queue.clone()).unwrap();
|
|
|
|
|
q.1.flush();
|
|
|
|
|
q.0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let out_buffer = {
|
|
|
|
|
// 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()
|
|
|
|
|
CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), image_buffer.clone()).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();
|
|
|
|
@ -227,14 +213,16 @@ fn main() {
|
|
|
|
|
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 = Arc::new(PersistentDescriptorSet::start(pipeline.clone(), 0)
|
|
|
|
|
.add_buffer(data_buffer.clone()).unwrap()
|
|
|
|
|
.add_buffer(out_buffer.clone()).unwrap()
|
|
|
|
|
.add_buffer(read_buffer).unwrap()
|
|
|
|
|
.add_buffer(write_buffer.clone()).unwrap()
|
|
|
|
|
.add_buffer(settings_buffer.clone()).unwrap()
|
|
|
|
|
.build().unwrap()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
println!("Running Kernel...");
|
|
|
|
|
// The command buffer I think pretty much serves to define what runs where for how many times
|
|
|
|
|
let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap()
|
|
|
|
|
.dispatch([xy.0, xy.1, 1], pipeline.clone(), set.clone(), ()).unwrap()
|
|
|
|
@ -248,9 +236,13 @@ fn main() {
|
|
|
|
|
// I think this is redundant and returns immediately
|
|
|
|
|
future.wait(None).unwrap();
|
|
|
|
|
|
|
|
|
|
println!("Done running kernel");
|
|
|
|
|
// The buffer is sync'd so we can just read straight from the handle
|
|
|
|
|
let data_buffer_content = data_buffer.read().unwrap();
|
|
|
|
|
let data_buffer_content = write_buffer.read().unwrap();
|
|
|
|
|
|
|
|
|
|
let p = image::load_from_memory(data_buffer_content.as_slice()).unwrap();
|
|
|
|
|
|
|
|
|
|
println!("done2");
|
|
|
|
|
for y in 0 .. xy.1 {
|
|
|
|
|
for x in 0 .. xy.0 {
|
|
|
|
|
|
|
|
|
@ -269,6 +261,7 @@ fn main() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("done3");
|
|
|
|
|
img.save(format!("output/{}.png", SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()));
|
|
|
|
|
|
|
|
|
|
println!("Stdddwafasddfqwefaarting");
|
|
|
|
|