|
|
|
|
|
|
|
#![allow(dead_code)]
|
|
|
|
#![allow(unused_variables)]
|
|
|
|
#![allow(unused_mut)]
|
|
|
|
|
|
|
|
extern crate cgmath;
|
|
|
|
extern crate image;
|
|
|
|
extern crate nalgebra as na;
|
|
|
|
extern crate rand;
|
|
|
|
extern crate sfml;
|
|
|
|
extern crate time;
|
|
|
|
|
|
|
|
use sfml::system::*;
|
|
|
|
use vulkano::sync;
|
|
|
|
use crate::timer::Timer;
|
|
|
|
use vulkano::instance::{Instance};
|
|
|
|
use vulkano::sync::GpuFuture;
|
|
|
|
use winit::{EventsLoop, WindowBuilder, WindowEvent, Event, DeviceEvent, VirtualKeyCode, ElementState};
|
|
|
|
use winit::dpi::LogicalSize;
|
|
|
|
use vulkano_win::VkSurfaceBuild;
|
|
|
|
use sprite::Sprite;
|
|
|
|
use crate::canvas::CanvasFrame;
|
|
|
|
|
|
|
|
|
|
|
|
mod util;
|
|
|
|
mod slider;
|
|
|
|
mod timer;
|
|
|
|
mod input;
|
|
|
|
mod vkprocessor;
|
|
|
|
mod button;
|
|
|
|
mod vertex_2d;
|
|
|
|
mod vertex_3d;
|
|
|
|
mod sprite;
|
|
|
|
mod canvas;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Alright, what the hell do I do next...
|
|
|
|
|
|
|
|
Canvas works, but I want to use CPU accessible buffer instead of immutable buffer
|
|
|
|
I think it would be faster if we reuse fewer oversized buffers than vis versa
|
|
|
|
|
|
|
|
Texturing is broken
|
|
|
|
|
|
|
|
Compute is running in the background, but don't have a way to draw it.
|
|
|
|
Would like to draw it to a sprite???
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8/13 :
|
|
|
|
Okay. So I've decided to keep compute image and compute kernel in their own 'canvas'
|
|
|
|
Canvas still needs to be cleaned up. I would like a contract type of thing going on
|
|
|
|
with the loaded textures. Where you need to request a texture_handle from vkprocessor
|
|
|
|
to attach to a Sprite. The problem is kinda what I do with the swap image. I only need
|
|
|
|
a reference to it and the general buffer coming back from the compute kernel. I could
|
|
|
|
continue to hold the image in the Canvas, and just give out an ID when a Sprite wants it.
|
|
|
|
|
|
|
|
The issue here is that kinda muddles the API a bit. I would need to do something like
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8/27 :
|
|
|
|
|
|
|
|
But I dont always want to draw a computable...
|
|
|
|
Which I guess is fine. I could have another datatype implement computable
|
|
|
|
|
|
|
|
CompuSprite
|
|
|
|
-> Drawable, Computable
|
|
|
|
TxturSprite
|
|
|
|
-> Drawable
|
|
|
|
ColorSprite
|
|
|
|
-> Drawable
|
|
|
|
|
|
|
|
Computable
|
|
|
|
-> get pipeline id (need to assoc. compiled kernel)
|
|
|
|
->
|
|
|
|
|
|
|
|
Drawable
|
|
|
|
-> get texture id
|
|
|
|
-> get image id
|
|
|
|
-> get color
|
|
|
|
-> get vertices
|
|
|
|
|
|
|
|
Computable
|
|
|
|
get data
|
|
|
|
set data?
|
|
|
|
set settings?
|
|
|
|
get swap image id
|
|
|
|
|
|
|
|
Drawable:
|
|
|
|
get vertices
|
|
|
|
get color
|
|
|
|
get texture id
|
|
|
|
|
|
|
|
get descriptor set
|
|
|
|
|
|
|
|
need some sort of computable interface for the Sprite. It already has drawable
|
|
|
|
so why not computable
|
|
|
|
|
|
|
|
|
|
|
|
Pipeline is the compiled kernel/shader
|
|
|
|
in the shaders case, it has the vertex definition, constants, and the compiled code
|
|
|
|
in kernel, its just constants and compiled code
|
|
|
|
|
|
|
|
Descriptor set holds the buffers which we will pass to the pipeline
|
|
|
|
rw and settings buffers for the compu
|
|
|
|
texture buffer for the textured
|
|
|
|
image buffer for the image (swap)
|
|
|
|
|
|
|
|
|
|
|
|
Need to have certain stages in the building of the command buffer.
|
|
|
|
(Z level????)
|
|
|
|
|
|
|
|
1.) computes
|
|
|
|
2.) compute swaps
|
|
|
|
3.) render images
|
|
|
|
4.) render textures
|
|
|
|
5.) render solids
|
|
|
|
|
|
|
|
So to start with we need to know the compute data which we want to run and the kernel we want to run it on. We combine the buffers along with the pipeline generated from the compiled kernel and get
|
|
|
|
the descriptor set. We also need the XY for the compute run
|
|
|
|
|
|
|
|
|
|
|
|
I think I need to keep these kernels in their own Canvas type of structure
|
|
|
|
I want to modify their constants and recompile
|
|
|
|
|
|
|
|
|
|
|
|
let comp = Computable::new(device, data, kernel_id)
|
|
|
|
|
|
|
|
I have canvas frame. Perhaps I should do something similar for compute
|
|
|
|
|
|
|
|
ComputeFrame.add(device, data, kernel_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Not sure if I can do this... but inside it could be like
|
|
|
|
CompuSprite::new(&mut canvas, kernel);
|
|
|
|
|
|
|
|
new(&mut canvas) -> CompuSprite {
|
|
|
|
let img_id = canvas.new_image();
|
|
|
|
|
|
|
|
Canvas {
|
|
|
|
img_id.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
I want to be able to chain computes using the same data
|
|
|
|
So that would be a different pipeline using the same or similar descriptor set
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sprite = Sprite::with_texture(Canvas.get_texture_from_file())
|
|
|
|
|
|
|
|
(compute, sprite2) = Compute::with_swap_image(Canvas.get_new_image())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compute load shader -> shader object
|
|
|
|
|
|
|
|
compute load buffers -> buffer object
|
|
|
|
|
|
|
|
shader object + buffer object + maybe the swap buffer
|
|
|
|
-> command queue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut canvas = CanvasFrame::new();
|
|
|
|
canvas.draw(&sprite);
|
|
|
|
canvas.draw(&sprite2);
|
|
|
|
|
|
|
|
|
|
|
|
(frame_future) = processor.run(&surface, frame_future, canvas);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
|
|
|
let instance = {
|
|
|
|
let extensions = vulkano_win::required_extensions();
|
|
|
|
Instance::new(None, &extensions, None).unwrap()
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut events_loop = EventsLoop::new();
|
|
|
|
let mut surface = WindowBuilder::new()
|
|
|
|
.with_dimensions(LogicalSize::from((800, 800)))
|
|
|
|
.build_vk_surface(&events_loop, instance.clone()).unwrap();
|
|
|
|
let mut window = surface.window();
|
|
|
|
|
|
|
|
let mut processor = vkprocessor::VkProcessor::new(&instance, &surface);
|
|
|
|
processor.compile_kernel(String::from("simple-edge.compute"));
|
|
|
|
processor.load_compute_image(String::from("background.jpg"));
|
|
|
|
processor.load_textures(String::from("funky-bird.jpg"));
|
|
|
|
processor.create_swapchain(&surface);
|
|
|
|
|
|
|
|
let mut timer = Timer::new();
|
|
|
|
let mut frame_future = Box::new(sync::now(processor.device.clone())) as Box<dyn GpuFuture>;
|
|
|
|
|
|
|
|
let step_size: f32 = 0.005;
|
|
|
|
let mut elapsed_time: f32;
|
|
|
|
let mut delta_time: f32;
|
|
|
|
let mut accumulator_time: f32 = 0.0;
|
|
|
|
let mut current_time: f32 = timer.elap_time();
|
|
|
|
|
|
|
|
let mut mouse_xy = Vector2i::new(0,0);
|
|
|
|
|
|
|
|
let sprite = Sprite::new_with_color((0.,0.), (0.1,0.1), (1.,0.,0.,1.));
|
|
|
|
let sprite2 = Sprite::new_with_color((-1.,-0.5), (0.1,0.1), (0.,1.,0.,1.));
|
|
|
|
|
|
|
|
while let Some(p) = window.get_position() {
|
|
|
|
|
|
|
|
elapsed_time = timer.elap_time();
|
|
|
|
delta_time = elapsed_time - current_time;
|
|
|
|
current_time = elapsed_time;
|
|
|
|
if delta_time > 0.02 {
|
|
|
|
delta_time = 0.02;
|
|
|
|
}
|
|
|
|
accumulator_time += delta_time;
|
|
|
|
|
|
|
|
while (accumulator_time - step_size) >= step_size {
|
|
|
|
accumulator_time -= step_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("{}", delta_time);
|
|
|
|
|
|
|
|
let mut exit = false;
|
|
|
|
events_loop.poll_events(|event| {
|
|
|
|
match event {
|
|
|
|
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
|
|
|
|
{
|
|
|
|
exit = true;
|
|
|
|
},
|
|
|
|
Event::WindowEvent { event: WindowEvent::Resized(_), .. } => {
|
|
|
|
processor.recreate_swapchain(&surface);
|
|
|
|
},
|
|
|
|
Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => {
|
|
|
|
|
|
|
|
match keyboard_input.virtual_keycode.unwrap() {
|
|
|
|
VirtualKeyCode::A => {
|
|
|
|
if keyboard_input.state == ElementState::Pressed {
|
|
|
|
processor.save_edges_image();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// Event::DeviceEvent { event: DeviceEvent::Button(mouse_input), .. } => {
|
|
|
|
// mouse_xy.x
|
|
|
|
// },
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if exit {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
let mut canvas = CanvasFrame::new();
|
|
|
|
canvas.draw(&sprite);
|
|
|
|
canvas.draw(&sprite2);
|
|
|
|
|
|
|
|
|
|
|
|
(frame_future) = processor.run(&surface, frame_future, canvas);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|