diff --git a/dynamic_entities.txt b/dynamic_entities.txt deleted file mode 100644 index 8bb1381d..00000000 --- a/dynamic_entities.txt +++ /dev/null @@ -1,4 +0,0 @@ -player 200 200 -enemy 100 100 -enemy 150 100 -enemy 200 100 \ No newline at end of file diff --git a/resources/sansation.ttf b/resources/fonts/sansation.ttf similarity index 100% rename from resources/sansation.ttf rename to resources/fonts/sansation.ttf diff --git a/resources/background.jpg b/resources/images/background.jpg similarity index 100% rename from resources/background.jpg rename to resources/images/background.jpg diff --git a/resources/devices.png b/resources/images/devices.png similarity index 100% rename from resources/devices.png rename to resources/images/devices.png diff --git a/resources/images/funky-bird.jpg b/resources/images/funky-bird.jpg new file mode 100755 index 00000000..d4d1dc14 Binary files /dev/null and b/resources/images/funky-bird.jpg differ diff --git a/resources/sfml.png b/resources/images/sfml.png similarity index 100% rename from resources/sfml.png rename to resources/images/sfml.png diff --git a/test.jpg b/resources/images/test.jpg similarity index 100% rename from test.jpg rename to resources/images/test.jpg diff --git a/resources/text-background.png b/resources/images/text-background.png similarity index 100% rename from resources/text-background.png rename to resources/images/text-background.png diff --git a/resources/edge.frag b/resources/shaders/edge.frag similarity index 100% rename from resources/edge.frag rename to resources/shaders/edge.frag diff --git a/spritesheet_complete.png b/spritesheet_complete.png deleted file mode 100755 index 98b999fc..00000000 Binary files a/spritesheet_complete.png and /dev/null differ diff --git a/spritesheet_complete.xml b/spritesheet_complete.xml deleted file mode 100755 index de636b60..00000000 --- a/spritesheet_complete.xml +++ /dev/null @@ -1,366 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/basic-compute-shader.rs b/src/basic-compute-shader.rs new file mode 100644 index 00000000..5aab015a --- /dev/null +++ b/src/basic-compute-shader.rs @@ -0,0 +1,160 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +// This example demonstrates how to use the compute capabilities of Vulkan. +// +// While graphics cards have traditionally been used for graphical operations, over time they have +// been more or more used for general-purpose operations as well. This is called "General-Purpose +// GPU", or *GPGPU*. This is what this example demonstrates. + +use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer}; +use vulkano::command_buffer::AutoCommandBufferBuilder; +use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; +use vulkano::device::{Device, DeviceExtensions}; +use vulkano::instance::{Instance, InstanceExtensions, PhysicalDevice}; +use vulkano::pipeline::ComputePipeline; +use vulkano::sync::GpuFuture; +use vulkano::sync; + +use std::sync::Arc; + +fn main() { + // As with other examples, the first step is to create an instance. + let instance = Instance::new(None, &InstanceExtensions::none(), None).unwrap(); + + // Choose which physical device to use. + let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); + + // Choose the queue of the physical device which is going to run our compute operation. + // + // The Vulkan specs guarantee that a compliant implementation must provide at least one queue + // that supports compute operations. + let queue_family = physical.queue_families().find(|&q| q.supports_compute()).unwrap(); + + // Now initializing the device. + let (device, mut queues) = Device::new(physical, + physical.supported_features(), + &DeviceExtensions::none(), + [(queue_family, 0.5)].iter().cloned()).unwrap(); + + // Since we can request multiple queues, the `queues` variable is in fact an iterator. In this + // example we use only one queue, so we just retrieve the first and only element of the + // iterator and throw it away. + let queue = queues.next().unwrap(); + + println!("Device initialized"); + + // Now let's get to the actual example. + // + // What we are going to do is very basic: we are going to fill a buffer with 64k integers + // and ask the GPU to multiply each of them by 12. + // + // GPUs are very good at parallel computations (SIMD-like operations), and thus will do this + // much more quickly than a CPU would do. While a CPU would typically multiply them one by one + // or four by four, a GPU will do it by groups of 32 or 64. + // + // Note however that in a real-life situation for such a simple operation the cost of + // accessing memory usually outweighs the benefits of a faster calculation. Since both the CPU + // and the GPU will need to access data, there is no other choice but to transfer the data + // through the slow PCI express bus. + + // We need to create the compute pipeline that describes our operation. + // + // If you are familiar with graphics pipeline, the principle is the same except that compute + // pipelines are much simpler to create. + let pipeline = Arc::new({ + mod cs { + vulkano_shaders::shader!{ + ty: "compute", + src: " +#version 450 + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(set = 0, binding = 0) buffer Data { + uint data[]; +} data; + +void main() { + uint idx = gl_GlobalInvocationID.x; + data.data[idx] *= 12; +}" + } + } + let shader = cs::Shader::load(device.clone()).unwrap(); + ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()).unwrap() + }); + + // We start by creating the buffer that will store the data. + let data_buffer = { + // Iterator that produces the data. + let data_iter = (0 .. 65536u32).map(|n| n); + // Builds the buffer and fills it with this iterator. + CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap() + }; + + // In order to let the shader access the buffer, we need to build a *descriptor set* that + // contains the buffer. + // + // The resources that we bind to the descriptor set must match the resources expected by the + // pipeline which we pass as the first parameter. + // + // If you want to run the pipeline on multiple different buffers, you need to create multiple + // descriptor sets that each contain the buffer you want to run the shader on. + let set = Arc::new(PersistentDescriptorSet::start(pipeline.clone(), 0) + .add_buffer(data_buffer.clone()).unwrap() + .build().unwrap() + ); + + // In order to execute our operation, we have to build a command buffer. + let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap() + // The command buffer only does one thing: execute the compute pipeline. + // This is called a *dispatch* operation. + // + // Note that we clone the pipeline and the set. Since they are both wrapped around an + // `Arc`, this only clones the `Arc` and not the whole pipeline or set (which aren't + // cloneable anyway). In this example we would avoid cloning them since this is the last + // time we use them, but in a real code you would probably need to clone them. + .dispatch([1024, 1, 1], pipeline.clone(), set.clone(), ()).unwrap() + // Finish building the command buffer by calling `build`. + .build().unwrap(); + + // Let's execute this command buffer now. + // To do so, we TODO: this is a bit clumsy, probably needs a shortcut + let future = sync::now(device.clone()) + .then_execute(queue.clone(), command_buffer).unwrap() + + // This line instructs the GPU to signal a *fence* once the command buffer has finished + // execution. A fence is a Vulkan object that allows the CPU to know when the GPU has + // reached a certain point. + // We need to signal a fence here because below we want to block the CPU until the GPU has + // reached that point in the execution. + .then_signal_fence_and_flush().unwrap(); + + // Blocks execution until the GPU has finished the operation. This method only exists on the + // future that corresponds to a signalled fence. In other words, this method wouldn't be + // available if we didn't call `.then_signal_fence_and_flush()` earlier. + // The `None` parameter is an optional timeout. + // + // Note however that dropping the `future` variable (with `drop(future)` for example) would + // block execution as well, and this would be the case even if we didn't call + // `.then_signal_fence_and_flush()`. + // Therefore the actual point of calling `.then_signal_fence_and_flush()` and `.wait()` is to + // make things more explicit. In the future, if the Rust language gets linear types vulkano may + // get modified so that only fence-signalled futures can get destroyed like this. + future.wait(None).unwrap(); + + // Now that the GPU is done, the content of the buffer should have been modified. Let's + // check it out. + // The call to `read()` would return an error if the buffer was still in use by the GPU. + let data_buffer_content = data_buffer.read().unwrap(); + for n in 0 .. 65536u32 { + assert_eq!(data_buffer_content[n as usize], n * 12); + } +} diff --git a/src/main.rs b/src/main.rs index 28dd4f95..b7e63fde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,34 +2,31 @@ #![allow(unused_variables)] #![allow(unused_mut)] -extern crate quick_xml; -extern crate sfml; extern crate cgmath; extern crate image; +extern crate nalgebra as na; +extern crate quick_xml; extern crate rand; +extern crate sfml; - -mod slider; -mod timer; -mod input; -mod util; - +use image::{DynamicImage, GenericImage, GenericImageView, Pixel, SubImage}; use sfml::graphics::*; +use sfml::graphics::{ + Color, RenderTarget, RenderWindow, +}; use sfml::system::*; +use sfml::system::Vector2 as sfVec2; use sfml::window::*; -use crate::timer::Timer; +use sfml::window::{Event, Key, Style}; + use crate::input::Input; use crate::slider::Slider; +use crate::timer::Timer; -extern crate nalgebra as na; - -use image::{GenericImageView, GenericImage, DynamicImage, Pixel, SubImage}; - -use sfml::graphics::{ - Color, RenderTarget, RenderWindow, -}; -use sfml::window::{ Event, Key, Style}; -use sfml::system::Vector2 as sfVec2; +mod slider; +mod timer; +mod input; +mod util; // The container trait for all the shaders trait Effect: Drawable { @@ -138,39 +135,18 @@ fn surrounding_pixels(x: u32, y: u32, img: &DynamicImage) -> Vec fn main() { - let mut img = image::open("test.jpg").unwrap(); + let mut img = image::open("resources/funky-bird.jpg").unwrap(); let xy = img.dimensions(); println!("Starting"); - for x in 0..xy.0 { - for y in 0..xy.1 { - let mut pixel = img.get_pixel(x, y); - - let v = surrounding_pixels(x, y, &img); - - let mut avg = v.first().unwrap().clone(); - - for p in v { - let r: u16 = (avg.data[0] as u16 + p.data[0] as u16); - let g: u16 = (avg.data[1] as u16 + p.data[1] as u16); - let b: u16 = (avg.data[2] as u16 + p.data[2] as u16); - let a: u16 = (avg.data[3] as u16 + p.data[3] as u16); - avg.data[0] = (r/2) as u8; - avg.data[1] = (g/2) as u8; - avg.data[2] = (b/2) as u8; - avg.data[3] = (a/2) as u8; - } - - pixel.data[0] = avg.data[0]; - pixel.data[1] = avg.data[1]; - pixel.data[2] = avg.data[2]; - pixel.data[3] = avg.data[3]; - - img.put_pixel(x, y, pixel); - } - } - println!("Ending"); - img.save("fractal.png").unwrap(); +// for x in 0..xy.0 { +// for y in 0..xy.1 { +// let mut pixel = img.get_pixel(x, y); +// img.put_pixel(x, y, pixel); +// } +// } + // println!("Ending"); + // img.save("fractal.png").unwrap(); let mut window = RenderWindow::new( (512, 512), @@ -202,7 +178,6 @@ fn main() { text_bg.set_color(&Color::rgba(255, 255, 255, 200)); //========================================== - let mut slider = Slider::new(40.0, None); let step_size: f32 = 0.005; @@ -249,7 +224,7 @@ fn main() { let x = window.mouse_position().x as f32 / window.size().x as f32; let y = window.mouse_position().y as f32 / window.size().y as f32; - effects[current].update(elapsed_time*1000.0, x, y); + effects[current].update(elapsed_time*1.0, x, y); window.clear(&Color::BLACK); @@ -259,5 +234,4 @@ fn main() { window.display(); } - } diff --git a/static_entities.txt b/static_entities.txt deleted file mode 100644 index fd9b1e2b..00000000 --- a/static_entities.txt +++ /dev/null @@ -1,9 +0,0 @@ -64 64 -0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 -1 1 1 0 0 0 0 0 -0 0 1 0 0 0 0 0 -0 0 1 0 0 0 0 0 -0 0 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 \ No newline at end of file