lots of refactoring
This commit is contained in:
@@ -19,5 +19,4 @@ time = "0.1.38"
|
|||||||
shaderc = "0.5.0"
|
shaderc = "0.5.0"
|
||||||
#shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"}
|
#shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"}
|
||||||
shade_runner = {path = "../shade_runner"}
|
shade_runner = {path = "../shade_runner"}
|
||||||
|
|
||||||
winit = "0.19.1"
|
winit = "0.19.1"
|
||||||
284
src/canvas.rs
284
src/canvas.rs
@@ -15,11 +15,12 @@ use vulkano::descriptor::DescriptorSet;
|
|||||||
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
use crate::util::compute_image::ComputeImage;
|
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use vulkano::swapchain::Capabilities;
|
use vulkano::swapchain::Capabilities;
|
||||||
use winit::Window;
|
use winit::Window;
|
||||||
use vulkano::pipeline::viewport::Viewport;
|
use vulkano::pipeline::viewport::Viewport;
|
||||||
|
use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
|
||||||
|
use crate::canvas_frame::CanvasFrame;
|
||||||
|
|
||||||
// Canvas is the accumulator of Sprites for drawing
|
// Canvas is the accumulator of Sprites for drawing
|
||||||
|
|
||||||
@@ -85,87 +86,73 @@ pub enum ShaderType {
|
|||||||
IMAGE = 2,
|
IMAGE = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CanvasFrame {
|
|
||||||
colored_drawables: Vec<ColoredVertex2D>,
|
|
||||||
textured_drawables: HashMap<Arc<u32>, Vec<Vec<Vertex2D>>>,
|
|
||||||
image_drawables: HashMap<Arc<u32>, Vec<Vec<Vertex2D>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CanvasFrame {
|
|
||||||
|
|
||||||
pub fn new() -> CanvasFrame {
|
|
||||||
CanvasFrame {
|
|
||||||
colored_drawables: vec![],
|
|
||||||
textured_drawables: Default::default(),
|
|
||||||
image_drawables: Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulates the drawables vertices and colors
|
|
||||||
pub fn draw(&mut self, drawable: &dyn Drawable) {
|
|
||||||
|
|
||||||
match drawable.get_texture_handle() {
|
|
||||||
Some(handle) => {
|
|
||||||
self.textured_drawables
|
|
||||||
.entry(handle.clone())
|
|
||||||
.or_insert(Vec::new())
|
|
||||||
.push(drawable.get_vertices().iter().map(|n|
|
|
||||||
Vertex2D {
|
|
||||||
position: [n.0, n.1],
|
|
||||||
}
|
|
||||||
).collect::<Vec<Vertex2D>>());
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
|
|
||||||
match drawable.get_image_handle() {
|
|
||||||
|
|
||||||
Some(handle) => {
|
|
||||||
self.image_drawables
|
|
||||||
.entry(handle.clone())
|
|
||||||
.or_insert(Vec::new())
|
|
||||||
.push(drawable.get_vertices().iter().map(|n|
|
|
||||||
Vertex2D {
|
|
||||||
position: [n.0, n.1],
|
|
||||||
}
|
|
||||||
).collect());
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let colors = drawable.get_color();
|
|
||||||
|
|
||||||
self.colored_drawables.extend(
|
|
||||||
drawable.get_vertices().iter().map(|n|
|
|
||||||
ColoredVertex2D {
|
|
||||||
position: [n.0, n.1],
|
|
||||||
color: [colors.0, colors.1, colors.2, colors.3],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Canvas {
|
pub struct TextureHandle {
|
||||||
shader_kernels: HashMap<ShaderType, ShaderKernels>,
|
handle: u32
|
||||||
|
}
|
||||||
|
|
||||||
texture_store: HashMap<String, Arc<ImmutableImage<Format>>>,
|
#[derive(Clone)]
|
||||||
|
pub struct ImageHandle {
|
||||||
|
handle: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ShaderHandle {
|
||||||
|
handle: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CanvasTexture {
|
||||||
|
handle: Arc<TextureHandle>,
|
||||||
|
buffer: Arc<ImmutableImage<Format>>,
|
||||||
|
name: String,
|
||||||
|
size: (u32, u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanvasTexture {
|
||||||
|
fn get_descriptor_set(&mut self,
|
||||||
|
shader: Arc<ShaderKernels>,
|
||||||
|
sampler: Arc<Sampler>) -> Box<dyn DescriptorSet + Send + Sync> {
|
||||||
|
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
||||||
|
PersistentDescriptorSet::start(
|
||||||
|
shader.clone().get_pipeline().clone(), 0,
|
||||||
|
)
|
||||||
|
.add_sampled_image(self.buffer.clone(), sampler.clone()).unwrap()
|
||||||
|
.build().unwrap());
|
||||||
|
o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CanvasImage {
|
||||||
|
handle: Arc<ImageHandle>,
|
||||||
|
buffer: Arc<AttachmentImage>,
|
||||||
|
size: (u32, u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanvasImage {
|
||||||
|
fn get_descriptor_set(&mut self, shader: Arc<ShaderKernels>)
|
||||||
|
-> Box<dyn DescriptorSet + Send + Sync> {
|
||||||
|
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
||||||
|
PersistentDescriptorSet::start(
|
||||||
|
shader.clone().get_pipeline().clone(), 0,
|
||||||
|
)
|
||||||
|
.add_image(self.buffer.clone()).unwrap()
|
||||||
|
.build().unwrap());
|
||||||
|
o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CanvasState {
|
||||||
dynamic_state: DynamicState,
|
dynamic_state: DynamicState,
|
||||||
sampler: Arc<Sampler>,
|
sampler: Arc<Sampler>,
|
||||||
|
|
||||||
// hold the image, texture, and shader buffers the same was as we do CompuState
|
// hold the image, texture, and shader buffers the same was as we do CompuState
|
||||||
image_buffers: Vec<std::sync::Arc<vulkano::image::attachment::AttachmentImage>>,
|
image_buffers: Vec<Arc<CanvasImage>>,
|
||||||
image_buffer_handles: Vec<Arc<u32>>,
|
texture_buffers: Vec<Arc<CanvasTexture>>,
|
||||||
|
shader_buffers: HashMap<String, ShaderKernels>,
|
||||||
texture_buffers: Vec<Arc<ImmutableImage<Format>>>,
|
|
||||||
texture_buffer_handles: Vec<Arc<u32>>,
|
|
||||||
|
|
||||||
shader_buffers: HashMap<ShaderType, ShaderKernels>,
|
|
||||||
shader_buffer_handles: Vec<Arc<u32>>,
|
|
||||||
|
|
||||||
// Hold onto the vertices we get from the Compu and Canvas Frames
|
// Hold onto the vertices we get from the Compu and Canvas Frames
|
||||||
// When the run comes around, push the vertices to the GPU
|
// When the run comes around, push the vertices to the GPU
|
||||||
@@ -184,11 +171,10 @@ pub struct Canvas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Canvas {
|
impl CanvasState {
|
||||||
|
|
||||||
// This method is called once during initialization, then again whenever the window is resized
|
// This method is called once during initialization, then again whenever the window is resized
|
||||||
pub fn window_size_dependent_setup(&mut self, images: &[Arc<SwapchainImage<Window>>])
|
pub fn window_size_dependent_setup(&mut self, images: &[Arc<SwapchainImage<Window>>])
|
||||||
-> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
|
-> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
|
||||||
let dimensions = images[0].dimensions();
|
let dimensions = images[0].dimensions();
|
||||||
|
|
||||||
self.dynamic_state.viewports =
|
self.dynamic_state.viewports =
|
||||||
@@ -200,7 +186,7 @@ impl Canvas {
|
|||||||
|
|
||||||
images.iter().map(|image| {
|
images.iter().map(|image| {
|
||||||
Arc::new(
|
Arc::new(
|
||||||
Framebuffer::start(self.shader_kernels.get(&ShaderType::SOLID).unwrap().render_pass.clone())
|
Framebuffer::start(self.shader_kernels.get(String::from("color-passthrough")).unwrap().render_pass.clone())
|
||||||
.add(image.clone()).unwrap()
|
.add(image.clone()).unwrap()
|
||||||
.build().unwrap()
|
.build().unwrap()
|
||||||
) as Arc<dyn FramebufferAbstract + Send + Sync>
|
) as Arc<dyn FramebufferAbstract + Send + Sync>
|
||||||
@@ -211,31 +197,24 @@ impl Canvas {
|
|||||||
pub fn new(queue: Arc<Queue>,
|
pub fn new(queue: Arc<Queue>,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
physical: PhysicalDevice,
|
physical: PhysicalDevice,
|
||||||
capabilities: Capabilities) -> Canvas {
|
capabilities: Capabilities) -> CanvasState {
|
||||||
|
|
||||||
let solid_color_kernel = String::from("color-passthrough");
|
let solid_color_kernel = String::from("color-passthrough");
|
||||||
let texture_kernel = String::from("simple_texture");
|
let texture_kernel = String::from("simple_texture");
|
||||||
|
|
||||||
let shader_kernels : HashMap<ShaderType, ShaderKernels> = HashMap::from_iter(vec![
|
let shader_kernels: HashMap<ShaderType, ShaderKernels> = HashMap::from_iter(vec![
|
||||||
(ShaderType::SOLID, ShaderKernels::new(solid_color_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone())),
|
(ShaderType::SOLID, ShaderKernels::new(solid_color_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone())),
|
||||||
(ShaderType::TEXTURED, ShaderKernels::new(texture_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone()))
|
(ShaderType::TEXTURED, ShaderKernels::new(texture_kernel, capabilities.clone(), queue.clone(), physical.clone(), device.clone()))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
Canvas {
|
CanvasState {
|
||||||
shader_kernels: Default::default(),
|
|
||||||
texture_store: Default::default(),
|
|
||||||
|
|
||||||
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
|
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
|
||||||
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
|
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
|
||||||
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
|
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
|
||||||
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(),
|
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(),
|
||||||
image_buffers: vec![],
|
image_buffers: vec![],
|
||||||
image_buffer_handles: vec![],
|
|
||||||
texture_buffers: vec![],
|
texture_buffers: vec![],
|
||||||
texture_buffer_handles: vec![],
|
|
||||||
shader_buffers: Default::default(),
|
shader_buffers: Default::default(),
|
||||||
shader_buffer_handles: vec![],
|
|
||||||
|
|
||||||
colored_drawables: vec![],
|
colored_drawables: vec![],
|
||||||
colored_vertex_buffer: vec![],
|
colored_vertex_buffer: vec![],
|
||||||
@@ -249,20 +228,24 @@ impl Canvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<u32> {
|
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<ImageHandle> {
|
||||||
self.image_buffers.push(
|
let image = CanvasImage {
|
||||||
AttachmentImage::with_usage(
|
handle: Arc::new(ImageHandle { handle: self.image_buffers.len() as u32 + 1 }),
|
||||||
|
buffer: AttachmentImage::with_usage(
|
||||||
self.device.clone(),
|
self.device.clone(),
|
||||||
[dimensions.0, dimensions.1],
|
[dimensions.0, dimensions.1],
|
||||||
Format::R8G8B8A8Uint,
|
Format::R8G8B8A8Uint,
|
||||||
usage).unwrap());
|
usage).unwrap(),
|
||||||
let id = Arc::new(self.image_buffers.len() as u32);
|
size: dimensions,
|
||||||
self.image_buffer_handles.push(id.clone());
|
};
|
||||||
id
|
let handle = image.handle.clone();
|
||||||
|
self.image_buffers.push(Arc::new(image));
|
||||||
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image(&self, image_handle: Arc<u32>) -> std::sync::Arc<vulkano::image::attachment::AttachmentImage> {
|
pub fn get_image(&self, image_handle: Arc<ImageHandle>) -> Arc<AttachmentImage> {
|
||||||
self.image_buffers.get((*image_handle).clone() as usize).unwrap().clone()
|
self.image_buffers.get((*image_handle).clone() as usize).unwrap()
|
||||||
|
.clone().buffer.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Handle file not found gracefully
|
// TODO Handle file not found gracefully
|
||||||
@@ -307,25 +290,24 @@ impl Canvas {
|
|||||||
texture
|
texture
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_texture_from_filename(&mut self, filename: String) -> Arc<ImmutableImage<Format>> {
|
pub fn load_texture(&mut self, filename: String) -> Option<Arc<TextureHandle>> {
|
||||||
if self.texture_store.contains_key(&filename.clone()) {
|
|
||||||
println!("{} Already exists, not going to replace it.", filename.clone());
|
|
||||||
self.texture_store.get(&filename.clone()).unwrap().clone()
|
|
||||||
} else {
|
|
||||||
let texture = self.get_texture_from_file(filename.clone());
|
|
||||||
self.texture_store.insert(filename, texture.clone());
|
|
||||||
texture
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_texture(&mut self, filename: String) -> Option<Arc<u32>> {
|
|
||||||
let texture_buffer = self.get_texture_from_file(filename.clone());
|
let texture_buffer = self.get_texture_from_file(filename.clone());
|
||||||
self.texture_buffers.push(texture_buffer.clone());
|
|
||||||
let id = Arc::new(self.texture_buffers.len() as u32);
|
|
||||||
self.texture_buffer_handles.push(id.clone());
|
|
||||||
Some(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let handle = Arc::new(TextureHandle {
|
||||||
|
handle: self.texture_buffers.len() as u32 + 1
|
||||||
|
});
|
||||||
|
|
||||||
|
let texture = Arc::new(CanvasTexture {
|
||||||
|
handle: handle.clone(),
|
||||||
|
buffer: self.get_texture_from_file(filename.clone()),
|
||||||
|
name: "".to_string(),
|
||||||
|
size: (0, 0),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.texture_buffers.push(texture);
|
||||||
|
|
||||||
|
Some(handle)
|
||||||
|
}
|
||||||
|
|
||||||
// After done using this, need to call allocated vertex buffers
|
// After done using this, need to call allocated vertex buffers
|
||||||
pub fn draw(&mut self, canvas_frame: CanvasFrame) {
|
pub fn draw(&mut self, canvas_frame: CanvasFrame) {
|
||||||
@@ -336,26 +318,20 @@ impl Canvas {
|
|||||||
self.allocate_vertex_buffers(self.device.clone());
|
self.allocate_vertex_buffers(self.device.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_texture(&self, texture_id: String) -> Arc<ImmutableImage<Format>> {
|
fn allocate_vertex_buffers(&mut self, device: Arc<Device>) {
|
||||||
if let Some(i) = self.texture_store.get(&texture_id) {
|
|
||||||
return i.clone();
|
|
||||||
} else {
|
|
||||||
panic!("{} : Texture not loaded", texture_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocate_vertex_buffers(&mut self, device: Arc<Device>) {
|
|
||||||
self.colored_vertex_buffer.clear();
|
self.colored_vertex_buffer.clear();
|
||||||
self.textured_vertex_buffer.clear();
|
self.textured_vertex_buffer.clear();
|
||||||
self.image_vertex_buffer.clear();
|
self.image_vertex_buffer.clear();
|
||||||
|
|
||||||
|
|
||||||
//TODO should probably use cpu accessible buffer instead of recreating immutes each frame
|
//TODO should probably use cpu accessible buffer instead of recreating immutes each frame
|
||||||
// CpuAccessibleBuffer::from_iter(
|
/*
|
||||||
// device.clone(),
|
CpuAccessibleBuffer::from_iter(
|
||||||
// BufferUsage::vertex_buffer(),
|
|
||||||
// self.colored_drawables.iter().cloned(),
|
device.clone(),
|
||||||
// ).unwrap().0;
|
BufferUsage::vertex_buffer(),
|
||||||
|
self.colored_drawables.iter().cloned(),
|
||||||
|
).unwrap().0;
|
||||||
|
*/
|
||||||
|
|
||||||
self.colored_vertex_buffer.push(
|
self.colored_vertex_buffer.push(
|
||||||
ImmutableBuffer::from_iter(
|
ImmutableBuffer::from_iter(
|
||||||
@@ -377,46 +353,24 @@ impl Canvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_solid_color_descriptor_set(&self) -> Box<dyn DescriptorSet + Send + Sync> {
|
fn get_texture(&self, texture_id: String) -> Arc<ImmutableImage<Format>> {
|
||||||
println!("{}", self.shader_kernels.get(&ShaderType::SOLID).unwrap().clone().get_pipeline().clone().num_sets());
|
if let Some(i) = self.texture_store.get(&texture_id) {
|
||||||
|
return i.clone();
|
||||||
|
} else {
|
||||||
|
panic!("{} : Texture not loaded", texture_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn get_solid_color_descriptor_set(&self, kernel: Arc<ShaderKernels>) -> Box<dyn DescriptorSet + Send + Sync> {
|
||||||
|
|
||||||
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
||||||
PersistentDescriptorSet::start(
|
PersistentDescriptorSet::start(
|
||||||
self.shader_kernels.get(&ShaderType::SOLID).unwrap().clone().get_pipeline().clone(), 0,
|
kernel.clone().get_pipeline().clone(), 0,
|
||||||
).build().unwrap());
|
).build().unwrap());
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_textured_descriptor_set(&self, texture_id: String)
|
|
||||||
-> Box<dyn DescriptorSet + Send + Sync> {
|
|
||||||
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
|
||||||
PersistentDescriptorSet::start(
|
|
||||||
self.shader_kernels.get(&ShaderType::TEXTURED).unwrap().clone().get_pipeline().clone(), 0,
|
|
||||||
)
|
|
||||||
.add_sampled_image(self.get_texture(texture_id), self.sampler.clone()).unwrap()
|
|
||||||
.build().unwrap());
|
|
||||||
o
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the image which is written to by the write compute buffer
|
|
||||||
// I suppose I could just have a general image set maker instead of compue... they are
|
|
||||||
// somewhat similar
|
|
||||||
fn get_compute_swap_descriptor_set(&mut self,
|
|
||||||
device: Arc<Device>,
|
|
||||||
compute_image: &ComputeImage) -> Box<dyn DescriptorSet + Send + Sync> {
|
|
||||||
let sampler = Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
|
|
||||||
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
|
|
||||||
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap();
|
|
||||||
|
|
||||||
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
|
|
||||||
PersistentDescriptorSet::start(
|
|
||||||
self.shader_kernels.get(&ShaderType::IMAGE).clone().unwrap().clone().get_pipeline(), 0,
|
|
||||||
)
|
|
||||||
.add_image(compute_image.clone().get_swap_buffer().clone()).unwrap()
|
|
||||||
.build().unwrap());
|
|
||||||
o
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw_commands(&self,
|
pub fn draw_commands(&self,
|
||||||
mut command_buffer: AutoCommandBufferBuilder,
|
mut command_buffer: AutoCommandBufferBuilder,
|
||||||
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
|
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
|
||||||
@@ -447,9 +401,7 @@ impl Canvas {
|
|||||||
// vec![self.get_textured_descriptor_set(String::from("funky-bird.jpg"))], ()
|
// vec![self.get_textured_descriptor_set(String::from("funky-bird.jpg"))], ()
|
||||||
// ).unwrap();
|
// ).unwrap();
|
||||||
}
|
}
|
||||||
ShaderType::IMAGE => {
|
ShaderType::IMAGE => {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,8 +409,6 @@ impl Canvas {
|
|||||||
.end_render_pass()
|
.end_render_pass()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
62
src/canvas_frame.rs
Normal file
62
src/canvas_frame.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use crate::canvas::Drawable;
|
||||||
|
|
||||||
|
pub struct CanvasFrame {
|
||||||
|
pub colored_drawables: Vec<ColoredVertex2D>,
|
||||||
|
pub textured_drawables: HashMap<Arc<u32>, Vec<Vec<Vertex2D>>>,
|
||||||
|
pub image_drawables: HashMap<Arc<u32>, Vec<Vec<Vertex2D>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanvasFrame {
|
||||||
|
pub fn new() -> CanvasFrame {
|
||||||
|
CanvasFrame {
|
||||||
|
colored_drawables: vec![],
|
||||||
|
textured_drawables: Default::default(),
|
||||||
|
image_drawables: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulates the drawables vertices and colors
|
||||||
|
pub fn draw(&mut self, drawable: &dyn Drawable) {
|
||||||
|
match drawable.get_texture_handle() {
|
||||||
|
Some(handle) => {
|
||||||
|
self.textured_drawables
|
||||||
|
.entry(handle.clone())
|
||||||
|
.or_insert(Vec::new())
|
||||||
|
.push(drawable.get_vertices().iter().map(|n|
|
||||||
|
Vertex2D {
|
||||||
|
position: [n.0, n.1],
|
||||||
|
}
|
||||||
|
).collect::<Vec<Vertex2D>>());
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
match drawable.get_image_handle() {
|
||||||
|
Some(handle) => {
|
||||||
|
self.image_drawables
|
||||||
|
.entry(handle.clone())
|
||||||
|
.or_insert(Vec::new())
|
||||||
|
.push(drawable.get_vertices().iter().map(|n|
|
||||||
|
Vertex2D {
|
||||||
|
position: [n.0, n.1],
|
||||||
|
}
|
||||||
|
).collect());
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let colors = drawable.get_color();
|
||||||
|
|
||||||
|
self.colored_drawables.extend(
|
||||||
|
drawable.get_vertices().iter().map(|n|
|
||||||
|
ColoredVertex2D {
|
||||||
|
position: [n.0, n.1],
|
||||||
|
color: [colors.0, colors.1, colors.2, colors.3],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/compu_buffer.rs
Normal file
99
src/compu_buffer.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage};
|
||||||
|
use vulkano::pipeline::ComputePipeline;
|
||||||
|
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
||||||
|
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
|
||||||
|
use image::ImageBuffer;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CompuBuffers {
|
||||||
|
dimensions: (u32, u32),
|
||||||
|
device: Arc<Device>,
|
||||||
|
handle: Arc<CompuBufferHandle>,
|
||||||
|
|
||||||
|
io_buffers: Vec<Arc<CpuAccessibleBuffer<[u8]>>>,
|
||||||
|
settings_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompuBuffers {
|
||||||
|
pub fn new(device: Arc<Device>, data: Vec<u8>,
|
||||||
|
dimensions: (u32, u32), stride: u32,
|
||||||
|
handle: Arc<CompuBufferHandle>) -> CompuBuffers {
|
||||||
|
|
||||||
|
let data_length = dimensions.0 * dimensions.1 * stride;
|
||||||
|
|
||||||
|
let input_buffer = {
|
||||||
|
let mut buff = data.iter();
|
||||||
|
let data_iter = (0..data_length).map(|n| *(buff.next().unwrap()));
|
||||||
|
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let output_buffer = {
|
||||||
|
let mut buff = data.iter();
|
||||||
|
let data_iter = (0..data_length).map(|n| *(buff.next().unwrap()));
|
||||||
|
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Settings buffer which holds i32's
|
||||||
|
// Compile macros into the kernel eventually to index them
|
||||||
|
let settings_buffer = {
|
||||||
|
let vec = vec![dimensions.0, dimensions.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()
|
||||||
|
};
|
||||||
|
|
||||||
|
CompuBuffers {
|
||||||
|
dimensions: dimensions,
|
||||||
|
device: device.clone(),
|
||||||
|
|
||||||
|
handle: handle,
|
||||||
|
io_buffers: vec![input_buffer, output_buffer],
|
||||||
|
settings_buffer: settings_buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_size(&self) -> (u32, u32) {
|
||||||
|
self.dimensions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>)
|
||||||
|
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((),
|
||||||
|
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
||||||
|
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
||||||
|
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> {
|
||||||
|
Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0)
|
||||||
|
.add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap()
|
||||||
|
.add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap()
|
||||||
|
.add_buffer(self.settings_buffer.clone()).unwrap()
|
||||||
|
.build().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_output_buffer(&self) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
|
||||||
|
let xy = self.get_size();
|
||||||
|
|
||||||
|
self.io_buffers.get(1).unwrap().write().unwrap().map(|x| x);
|
||||||
|
let data_buffer_content = self.io_buffers.get(1).unwrap().read().unwrap();
|
||||||
|
ImageBuffer::from_fn(xy.0, xy.1, |x, y| {
|
||||||
|
let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8;
|
||||||
|
let g = data_buffer_content[((xy.0 * y + x) * 4 + 1) as usize] as u8;
|
||||||
|
let b = data_buffer_content[((xy.0 * y + x) * 4 + 2) as usize] as u8;
|
||||||
|
let a = data_buffer_content[((xy.0 * y + x) * 4 + 3) as usize] as u8;
|
||||||
|
|
||||||
|
image::Rgba([r, g, b, a])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CompuBufferHandle {
|
||||||
|
handle: u32,
|
||||||
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct CompuKernelHandle {
|
||||||
|
handle: u32,
|
||||||
|
}
|
||||||
56
src/compu_frame.rs
Normal file
56
src/compu_frame.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
use crate::canvas::ImageHandle;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::compu_sprite::CompuSprite;
|
||||||
|
use crate::compu_buffer::{CompuBufferHandle, CompuKernelHandle};
|
||||||
|
|
||||||
|
pub struct CompuFrame {
|
||||||
|
// Vec<(Buffer, Kernel)>
|
||||||
|
pure_compute: Vec<(
|
||||||
|
Arc<CompuBufferHandle>,
|
||||||
|
Arc<CompuKernelHandle>)>,
|
||||||
|
|
||||||
|
// Vec<(Buffer, Image, Kernel)>
|
||||||
|
swapped_to_image: Vec<(
|
||||||
|
Arc<CompuBufferHandle>,
|
||||||
|
Arc<ImageHandle>,
|
||||||
|
Arc<CompuKernelHandle>)>,
|
||||||
|
|
||||||
|
// Vec<(Input Buffer, Output Buffer, Kernel)>
|
||||||
|
swapped_to_buffer: Vec<(
|
||||||
|
Arc<CompuBufferHandle>,
|
||||||
|
Arc<CompuBufferHandle>,
|
||||||
|
Arc<CompuKernelHandle>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompuFrame {
|
||||||
|
pub fn new() -> CompuFrame {
|
||||||
|
CompuFrame {
|
||||||
|
pure_compute: vec![],
|
||||||
|
swapped_to_image: vec![],
|
||||||
|
swapped_to_buffer: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, buffer: Arc<CompuBufferHandle>, kernel: Arc<CompuKernelHandle>) {
|
||||||
|
self.pure_compute.push((buffer, kernel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
INPUT_BUFFER -> input -> kernel -> output
|
||||||
|
v------------------^
|
||||||
|
OUTPUT_BUFFER -> input X kernel X output
|
||||||
|
*/
|
||||||
|
pub fn add_chained(&mut self,
|
||||||
|
input_buffer: Arc<CompuBufferHandle>,
|
||||||
|
output_buffer: Arc<CompuBufferHandle>,
|
||||||
|
kernel: Arc<CompuKernelHandle>) {
|
||||||
|
self.swapped_to_buffer.push((input_buffer, output_buffer, kernel));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_with_image_swap(&mut self,
|
||||||
|
buffer: Arc<CompuBufferHandle>,
|
||||||
|
kernel: Arc<CompuKernelHandle>,
|
||||||
|
sprite: &CompuSprite) {
|
||||||
|
self.swapped_to_image.push((buffer, sprite.get_image_handle().clone(), kernel))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,13 @@ use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
|||||||
use shade_runner::{CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry};
|
use shade_runner::{CompileError, FragLayout, FragInput, FragOutput, VertInput, VertOutput, VertLayout, CompiledShaders, Entry};
|
||||||
use shaderc::CompileOptions;
|
use shaderc::CompileOptions;
|
||||||
use vulkano::pipeline::shader::{ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry};
|
use vulkano::pipeline::shader::{ShaderModule, GraphicsEntryPoint, SpecializationConstants, SpecializationMapEntry};
|
||||||
|
use crate::compu_buffer::CompuKernelHandle;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ComputeKernel {
|
pub struct CompuKernel {
|
||||||
|
|
||||||
|
handle: Arc<CompuKernelHandle>,
|
||||||
|
|
||||||
compute_pipeline: Option<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>>,
|
compute_pipeline: Option<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>>,
|
||||||
compute_kernel_path: PathBuf,
|
compute_kernel_path: PathBuf,
|
||||||
@@ -22,7 +26,7 @@ pub struct ComputeKernel {
|
|||||||
specialization_constants: ComputeSpecializationConstants,
|
specialization_constants: ComputeSpecializationConstants,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputeKernel {
|
impl CompuKernel {
|
||||||
|
|
||||||
fn get_path(filename: String) -> PathBuf {
|
fn get_path(filename: String) -> PathBuf {
|
||||||
|
|
||||||
@@ -37,9 +41,10 @@ impl ComputeKernel {
|
|||||||
compute_path
|
compute_path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(filename: String, device: Arc<Device>) -> ComputeKernel {
|
pub fn new(filename: String, device: Arc<Device>,
|
||||||
|
handle: Arc<CompuKernelHandle>) -> CompuKernel {
|
||||||
|
|
||||||
let compute_path = ComputeKernel::get_path(filename);
|
let compute_path = CompuKernel::get_path(filename);
|
||||||
|
|
||||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||||
|
|
||||||
@@ -54,7 +59,8 @@ impl ComputeKernel {
|
|||||||
}.unwrap();
|
}.unwrap();
|
||||||
|
|
||||||
|
|
||||||
ComputeKernel {
|
CompuKernel {
|
||||||
|
handle: handle,
|
||||||
device: device,
|
device: device,
|
||||||
shader: shader,
|
shader: shader,
|
||||||
compute_pipeline: Option::None,
|
compute_pipeline: Option::None,
|
||||||
@@ -94,7 +100,7 @@ impl ComputeKernel {
|
|||||||
pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
|
pub fn compile_kernel(&mut self, filename: String) -> std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>> {
|
||||||
|
|
||||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||||
self.compute_kernel_path = ComputeKernel::get_path(filename);
|
self.compute_kernel_path = CompuKernel::get_path(filename);
|
||||||
|
|
||||||
self.shader =
|
self.shader =
|
||||||
sr::load_compute_with_options(self.compute_kernel_path.clone(), options)
|
sr::load_compute_with_options(self.compute_kernel_path.clone(), options)
|
||||||
@@ -112,10 +118,9 @@ impl ComputeKernel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
struct ComputeSpecializationConstants {
|
pub struct ComputeSpecializationConstants {
|
||||||
first_constant: i32,
|
first_constant: i32,
|
||||||
second_constant: u32,
|
second_constant: u32,
|
||||||
third_constant: f32,
|
third_constant: f32,
|
||||||
64
src/compu_sprite.rs
Normal file
64
src/compu_sprite.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
use crate::canvas::{ImageHandle, Drawable, TextureHandle};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct CompuSprite {
|
||||||
|
vertices: [(f32, f32); 6],
|
||||||
|
position: (f32, f32),
|
||||||
|
size: (f32, f32),
|
||||||
|
color: (f32, f32, f32, f32),
|
||||||
|
image_handle: Arc<ImageHandle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drawable for CompuSprite {
|
||||||
|
fn get_vertices(&self) -> Vec<(f32, f32)> {
|
||||||
|
self.vertices.to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_color(&self) -> (f32, f32, f32, f32) {
|
||||||
|
self.color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_texture_handle(&self) -> Option<Arc<TextureHandle>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_image_handle(&self) -> Option<Arc<ImageHandle>> {
|
||||||
|
Some(self.image_handle.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompuSprite {
|
||||||
|
pub fn new(position: (f32, f32),
|
||||||
|
size: (f32, f32),
|
||||||
|
image_handle: Arc<ImageHandle>) -> CompuSprite {
|
||||||
|
let fsize = (size.0 as f32, size.1 as f32);
|
||||||
|
|
||||||
|
CompuSprite {
|
||||||
|
vertices: [
|
||||||
|
(position.0, position.1), // top left
|
||||||
|
(position.0, position.1 + fsize.1), // bottom left
|
||||||
|
(position.0 + fsize.0, position.1 + fsize.1), // bottom right
|
||||||
|
(position.0, position.1), // top left
|
||||||
|
(position.0 + fsize.0, position.1 + fsize.1), // bottom right
|
||||||
|
(position.0 + fsize.0, position.1), // top right
|
||||||
|
],
|
||||||
|
|
||||||
|
position: position,
|
||||||
|
size: size,
|
||||||
|
color: (0.0, 0.0, 0.0, 0.0),
|
||||||
|
image_handle: image_handle.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_vertices(&self) -> Vec<(f32, f32)> {
|
||||||
|
self.vertices.to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_color(&self) -> (f32, f32, f32, f32) {
|
||||||
|
self.color.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_image_handle(&self) -> Arc<ImageHandle> {
|
||||||
|
self.image_handle.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
141
src/compu_state.rs
Normal file
141
src/compu_state.rs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
use std::ffi::CStr;
|
||||||
|
use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::canvas::{Drawable, CanvasState, ImageHandle, CanvasImage, TextureHandle};
|
||||||
|
use vulkano::framebuffer::RenderPassAbstract;
|
||||||
|
use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use image::ImageBuffer;
|
||||||
|
use image::GenericImageView;
|
||||||
|
use vulkano::image::{ImageUsage, AttachmentImage};
|
||||||
|
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet};
|
||||||
|
use vulkano::format::Format;
|
||||||
|
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use image::Rgba;
|
||||||
|
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use shade_runner::{CompiledShaders, Entry, CompileError};
|
||||||
|
use vulkano::pipeline::shader::ShaderModule;
|
||||||
|
use shaderc::CompileOptions;
|
||||||
|
use crate::compu_kernel::CompuKernel;
|
||||||
|
use crate::compu_buffer::{CompuBuffers, CompuBufferHandle, CompuKernelHandle};
|
||||||
|
use crate::compu_frame::CompuFrame;
|
||||||
|
|
||||||
|
|
||||||
|
// Canvas analog
|
||||||
|
pub struct CompuState {
|
||||||
|
compute_buffers: Vec<CompuBuffers>,
|
||||||
|
kernels: Vec<CompuKernel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompuState {
|
||||||
|
pub fn new() -> CompuState {
|
||||||
|
CompuState {
|
||||||
|
compute_buffers: vec![],
|
||||||
|
kernels: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_compute_buffer(&mut self,
|
||||||
|
data: Vec<u8>,
|
||||||
|
dimensions: (u32, u32),
|
||||||
|
stride: u32,
|
||||||
|
device: Arc<Device>) -> Arc<CompuBufferHandle> {
|
||||||
|
|
||||||
|
let handle = Arc::new(CompuBufferHandle {
|
||||||
|
handle: self.compute_buffers.len() as u32 + 1
|
||||||
|
});
|
||||||
|
|
||||||
|
self.compute_buffers.push(
|
||||||
|
CompuBuffers::new(device.clone(), data, dimensions, stride, handle.clone()));
|
||||||
|
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_compute_buffer(&mut self, handle: Arc<CompuBufferHandle>) -> Vec<u8> {
|
||||||
|
// This is way more difficult than it should be
|
||||||
|
//let compute_buffer : CompuBuffers = self.compute_buffers.get(handle.into()).unwrap();
|
||||||
|
//compute_buffer.read_output_buffer().to_vec()
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
pub fn write_compute_buffer(&self, handle: Arc<CompuBufferHandle>, data: Vec<u8>) {}
|
||||||
|
|
||||||
|
pub fn new_kernel(&mut self,
|
||||||
|
filename: String,
|
||||||
|
device: &Arc<Device>) -> Arc<CompuKernelHandle> {
|
||||||
|
|
||||||
|
let handle = Arc::new(CompuKernelHandle {
|
||||||
|
handle: self.kernels.len() as u32 + 1
|
||||||
|
});
|
||||||
|
|
||||||
|
self.kernels.push(CompuKernel::new(filename, device.clone(), handle.clone()));
|
||||||
|
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_commands(&mut self,
|
||||||
|
compute_frame: CompuFrame,
|
||||||
|
mut command_buffer: AutoCommandBufferBuilder,
|
||||||
|
canvas: &CanvasState)
|
||||||
|
-> AutoCommandBufferBuilder {
|
||||||
|
|
||||||
|
// i = (Buffer, Kernel)
|
||||||
|
for i in compute_frame.pure_compute {
|
||||||
|
let buffer_id = (*i.0).clone() as usize;
|
||||||
|
let kernel_id = (*i.1).clone() as usize;
|
||||||
|
|
||||||
|
let buffer = self.compute_buffers.get(buffer_id).unwrap();
|
||||||
|
let kernel = self.kernels.get(buffer_id).unwrap();
|
||||||
|
|
||||||
|
let p = kernel.clone().get_pipeline();
|
||||||
|
let d = buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
||||||
|
|
||||||
|
command_buffer = command_buffer
|
||||||
|
.dispatch([100,100,1], p, d, ()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// i = (Buffer, Image, Kernel)
|
||||||
|
for i in compute_frame.swapped_to_image {
|
||||||
|
let buffer_id = (*i.0).clone() as usize;
|
||||||
|
let image_id = i.1.clone();
|
||||||
|
let kernel_id = (*i.2).clone() as usize;
|
||||||
|
|
||||||
|
let buffer = self.compute_buffers.get(buffer_id).unwrap();
|
||||||
|
let image = canvas.get_image(image_id);
|
||||||
|
let kernel = self.kernels.get(buffer_id).unwrap();
|
||||||
|
|
||||||
|
let p = kernel.clone().get_pipeline();
|
||||||
|
let d = buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
||||||
|
|
||||||
|
command_buffer = command_buffer
|
||||||
|
.dispatch([100,100,1], p, d, ()).unwrap()
|
||||||
|
.copy_buffer_to_image(buffer.io_buffers.get(0).unwrap().clone(), image).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// i = (Input Buffer, Output Buffer, Kernel)
|
||||||
|
// Input buffer -> Kernel -> Output buffer
|
||||||
|
for i in compute_frame.swapped_to_buffer {
|
||||||
|
let input_buffer_id = (*i.0).clone() as usize;
|
||||||
|
let output_buffer_id = (*i.1).clone() as usize;
|
||||||
|
let kernel_id = (*i.2).clone() as usize;
|
||||||
|
|
||||||
|
let input_buffer = self.compute_buffers.get(input_buffer_id).unwrap();
|
||||||
|
let output_buffer = self.compute_buffers.get(output_buffer_id).unwrap();
|
||||||
|
let kernel = self.kernels.get(kernel_id).unwrap();
|
||||||
|
|
||||||
|
let pipeline = kernel.clone().get_pipeline();
|
||||||
|
let descriptor_set = input_buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
||||||
|
|
||||||
|
command_buffer = command_buffer
|
||||||
|
.dispatch([100,100,1], pipeline, descriptor_set, ()).unwrap()
|
||||||
|
.copy_buffer(
|
||||||
|
input_buffer.io_buffers.get(1).unwrap().clone(),
|
||||||
|
output_buffer.io_buffers.get(0).unwrap().clone()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
command_buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
315
src/compu_wip.rs
315
src/compu_wip.rs
@@ -1,315 +0,0 @@
|
|||||||
use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use crate::canvas::{Drawable, Canvas};
|
|
||||||
use vulkano::framebuffer::RenderPassAbstract;
|
|
||||||
use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
|
|
||||||
use vulkano::device::Device;
|
|
||||||
use crate::util::compute_kernel::ComputeKernel;
|
|
||||||
use image::ImageBuffer;
|
|
||||||
use image::GenericImageView;
|
|
||||||
use crate::util::compute_image::ComputeImage;
|
|
||||||
use vulkano::image::{ImageUsage, AttachmentImage};
|
|
||||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf, PersistentDescriptorSet};
|
|
||||||
use vulkano::format::Format;
|
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
|
||||||
use std::borrow::Borrow;
|
|
||||||
use image::Rgba;
|
|
||||||
use vulkano::command_buffer::AutoCommandBufferBuilder;
|
|
||||||
|
|
||||||
pub struct CompuSprite {
|
|
||||||
vertices: [(f32, f32); 6],
|
|
||||||
position: (f32, f32),
|
|
||||||
size: (f32, f32),
|
|
||||||
color: (f32, f32, f32, f32),
|
|
||||||
image_handle: Arc<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drawable for CompuSprite {
|
|
||||||
fn get_vertices(&self) -> Vec<(f32, f32)> {
|
|
||||||
self.vertices.to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_color(&self) -> (f32, f32, f32, f32) {
|
|
||||||
self.color
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_texture_handle(&self) -> Option<Arc<u32>> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_image_handle(&self) -> Option<Arc<u32>> {
|
|
||||||
Some(self.image_handle.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompuSprite {
|
|
||||||
pub fn new(position: (f32, f32),
|
|
||||||
size: (f32, f32),
|
|
||||||
image_handle: Arc<u32>) -> CompuSprite {
|
|
||||||
let fsize = (size.0 as f32, size.1 as f32);
|
|
||||||
|
|
||||||
CompuSprite {
|
|
||||||
vertices: [
|
|
||||||
(position.0, position.1), // top left
|
|
||||||
(position.0, position.1 + fsize.1), // bottom left
|
|
||||||
(position.0 + fsize.0, position.1 + fsize.1), // bottom right
|
|
||||||
(position.0, position.1), // top left
|
|
||||||
(position.0 + fsize.0, position.1 + fsize.1), // bottom right
|
|
||||||
(position.0 + fsize.0, position.1), // top right
|
|
||||||
],
|
|
||||||
|
|
||||||
position: position,
|
|
||||||
size: size,
|
|
||||||
color: (0.0, 0.0, 0.0, 0.0),
|
|
||||||
image_handle: image_handle.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_vertices(&self) -> Vec<(f32, f32)> {
|
|
||||||
self.vertices.to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_color(&self) -> (f32, f32, f32, f32) {
|
|
||||||
self.color.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_image_handle(&self) -> Arc<u32> {
|
|
||||||
self.image_handle.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct CompuBuffers {
|
|
||||||
dimensions: (u32, u32),
|
|
||||||
device: Arc<Device>,
|
|
||||||
|
|
||||||
io_buffers: Vec<Arc<CpuAccessibleBuffer<[u8]>>>,
|
|
||||||
settings_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompuBuffers {
|
|
||||||
pub fn new(device: Arc<Device>, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> CompuBuffers {
|
|
||||||
let data_length = dimensions.0 * dimensions.1 * stride;
|
|
||||||
|
|
||||||
let input_buffer = {
|
|
||||||
let mut buff = data.iter();
|
|
||||||
let data_iter = (0..data_length).map(|n| *(buff.next().unwrap()));
|
|
||||||
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let output_buffer = {
|
|
||||||
let mut buff = data.iter();
|
|
||||||
let data_iter = (0..data_length).map(|n| *(buff.next().unwrap()));
|
|
||||||
CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), data_iter).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Settings buffer which holds i32's
|
|
||||||
// Compile macros into the kernel eventually to index them
|
|
||||||
let settings_buffer = {
|
|
||||||
let vec = vec![dimensions.0, dimensions.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()
|
|
||||||
};
|
|
||||||
|
|
||||||
CompuBuffers {
|
|
||||||
dimensions: dimensions,
|
|
||||||
device: device.clone(),
|
|
||||||
|
|
||||||
io_buffers: vec![input_buffer, output_buffer],
|
|
||||||
settings_buffer: settings_buffer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_size(&self) -> (u32, u32) {
|
|
||||||
self.dimensions
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>)
|
|
||||||
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> {
|
|
||||||
Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0)
|
|
||||||
.add_buffer(self.io_buffers.get(0).unwrap().clone()).unwrap()
|
|
||||||
.add_buffer(self.io_buffers.get(1).unwrap().clone()).unwrap()
|
|
||||||
.add_buffer(self.settings_buffer.clone()).unwrap()
|
|
||||||
.build().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_output_buffer(&self) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
|
|
||||||
let xy = self.get_size();
|
|
||||||
|
|
||||||
self.io_buffers.get(1).unwrap().write().unwrap().map(|x| x);
|
|
||||||
let data_buffer_content = self.io_buffers.get(1).unwrap().read().unwrap();
|
|
||||||
ImageBuffer::from_fn(xy.0, xy.1, |x, y| {
|
|
||||||
let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8;
|
|
||||||
let g = data_buffer_content[((xy.0 * y + x) * 4 + 1) as usize] as u8;
|
|
||||||
let b = data_buffer_content[((xy.0 * y + x) * 4 + 2) as usize] as u8;
|
|
||||||
let a = data_buffer_content[((xy.0 * y + x) * 4 + 3) as usize] as u8;
|
|
||||||
|
|
||||||
image::Rgba([r, g, b, a])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canvas analog
|
|
||||||
pub struct CompuState {
|
|
||||||
compute_buffers: Vec<CompuBuffers>,
|
|
||||||
compute_buffer_handles: Vec<Arc<u32>>,
|
|
||||||
|
|
||||||
kernels: Vec<ComputeKernel>,
|
|
||||||
kernel_handles: Vec<Arc<u32>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompuState {
|
|
||||||
pub fn new() -> CompuState {
|
|
||||||
CompuState {
|
|
||||||
compute_buffers: vec![],
|
|
||||||
compute_buffer_handles: vec![],
|
|
||||||
kernels: vec![],
|
|
||||||
kernel_handles: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_compute_buffer(&mut self,
|
|
||||||
data: Vec<u8>,
|
|
||||||
dimensions: (u32, u32),
|
|
||||||
stride: u32,
|
|
||||||
device: Arc<Device>) -> Arc<u32> {
|
|
||||||
self.compute_buffers.push(
|
|
||||||
CompuBuffers::new(device.clone(), data, dimensions, stride));
|
|
||||||
|
|
||||||
let id = Arc::new(self.compute_buffers.len() as u32);
|
|
||||||
self.compute_buffer_handles.push(id.clone());
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_compute_buffer(&mut self, handle: Arc<u32>) -> Vec<u8> {
|
|
||||||
// This is way more difficult than it should be
|
|
||||||
//let compute_buffer : CompuBuffers = self.compute_buffers.get(handle.into()).unwrap();
|
|
||||||
//compute_buffer.read_output_buffer().to_vec()
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
pub fn write_compute_buffer(&self, handle: Arc<u32>, data: Vec<u8>) {}
|
|
||||||
|
|
||||||
pub fn new_kernel(&mut self,
|
|
||||||
filename: String,
|
|
||||||
device: &Arc<Device>) -> Arc<u32> {
|
|
||||||
let kernel = ComputeKernel::new(filename, device.clone());
|
|
||||||
|
|
||||||
self.kernels.push(kernel);
|
|
||||||
|
|
||||||
let id = Arc::new(self.kernels.len() as u32);
|
|
||||||
|
|
||||||
self.kernel_handles.push(id.clone());
|
|
||||||
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_commands(&mut self,
|
|
||||||
compute_frame: ComputeFrame,
|
|
||||||
mut command_buffer: AutoCommandBufferBuilder,
|
|
||||||
canvas: &Canvas)
|
|
||||||
-> AutoCommandBufferBuilder {
|
|
||||||
|
|
||||||
// i = (Buffer, Kernel)
|
|
||||||
for i in compute_frame.pure_compute {
|
|
||||||
let buffer_id = (*i.0).clone() as usize;
|
|
||||||
let kernel_id = (*i.1).clone() as usize;
|
|
||||||
|
|
||||||
let buffer = self.compute_buffers.get(buffer_id).unwrap();
|
|
||||||
let kernel = self.kernels.get(buffer_id).unwrap();
|
|
||||||
|
|
||||||
let p = kernel.clone().get_pipeline();
|
|
||||||
let d = buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
|
||||||
|
|
||||||
command_buffer = command_buffer
|
|
||||||
.dispatch([100,100,1], p, d, ()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// i = (Buffer, Image, Kernel)
|
|
||||||
for i in compute_frame.swapped_to_image {
|
|
||||||
let buffer_id = (*i.0).clone() as usize;
|
|
||||||
let image_id = i.1.clone();
|
|
||||||
let kernel_id = (*i.2).clone() as usize;
|
|
||||||
|
|
||||||
let buffer = self.compute_buffers.get(buffer_id).unwrap();
|
|
||||||
let image = canvas.get_image(image_id);
|
|
||||||
let kernel = self.kernels.get(buffer_id).unwrap();
|
|
||||||
|
|
||||||
let p = kernel.clone().get_pipeline();
|
|
||||||
let d = buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
|
||||||
|
|
||||||
command_buffer = command_buffer
|
|
||||||
.dispatch([100,100,1], p, d, ()).unwrap()
|
|
||||||
.copy_buffer_to_image(buffer.io_buffers.get(0).unwrap().clone(), image).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// i = (Input Buffer, Output Buffer, Kernel)
|
|
||||||
// Input buffer -> Kernel -> Output buffer
|
|
||||||
for i in compute_frame.swapped_to_buffer {
|
|
||||||
let input_buffer_id = (*i.0).clone() as usize;
|
|
||||||
let output_buffer_id = (*i.1).clone() as usize;
|
|
||||||
let kernel_id = (*i.2).clone() as usize;
|
|
||||||
|
|
||||||
let input_buffer = self.compute_buffers.get(input_buffer_id).unwrap();
|
|
||||||
let output_buffer = self.compute_buffers.get(output_buffer_id).unwrap();
|
|
||||||
let kernel = self.kernels.get(kernel_id).unwrap();
|
|
||||||
|
|
||||||
let pipeline = kernel.clone().get_pipeline();
|
|
||||||
let descriptor_set = input_buffer.get_descriptor_set(kernel.clone().get_pipeline());
|
|
||||||
|
|
||||||
command_buffer = command_buffer
|
|
||||||
.dispatch([100,100,1], pipeline, descriptor_set, ()).unwrap()
|
|
||||||
.copy_buffer(
|
|
||||||
input_buffer.io_buffers.get(1).unwrap().clone(),
|
|
||||||
output_buffer.io_buffers.get(0).unwrap().clone()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
command_buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub struct ComputeFrame {
|
|
||||||
// Vec<(Buffer, Kernel)>
|
|
||||||
pure_compute: Vec<(Arc<u32>, Arc<u32>)>,
|
|
||||||
|
|
||||||
// Vec<(Buffer, Image, Kernel)>
|
|
||||||
swapped_to_image: Vec<(Arc<u32>, Arc<u32>, Arc<u32>)>,
|
|
||||||
|
|
||||||
// Vec<(Input Buffer, Output Buffer, Kernel)>
|
|
||||||
swapped_to_buffer: Vec<(Arc<u32>, Arc<u32>, Arc<u32>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ComputeFrame {
|
|
||||||
pub fn new() -> ComputeFrame {
|
|
||||||
ComputeFrame {
|
|
||||||
pure_compute: vec![],
|
|
||||||
swapped_to_image: vec![],
|
|
||||||
swapped_to_buffer: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add(&mut self, buffer: Arc<u32>, kernel: Arc<u32>) {
|
|
||||||
self.pure_compute.push((buffer, kernel));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
INPUT_BUFFER -> input -> kernel -> output
|
|
||||||
v------------------^
|
|
||||||
OUTPUT_BUFFER -> input X kernel X output
|
|
||||||
*/
|
|
||||||
pub fn add_chained(&mut self, input_buffer: Arc<u32>, output_buffer: Arc<u32>, kernel: Arc<u32>) {
|
|
||||||
self.swapped_to_buffer.push((input_buffer, output_buffer, kernel));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_with_image_swap(&mut self, buffer: Arc<u32>, kernel: Arc<u32>, sprite: &CompuSprite) {
|
|
||||||
self.swapped_to_image.push((buffer, sprite.get_image_handle().clone(), kernel))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
39
src/main.rs
39
src/main.rs
@@ -19,9 +19,13 @@ use winit::{EventsLoop, WindowBuilder, WindowEvent, Event, DeviceEvent, VirtualK
|
|||||||
use winit::dpi::LogicalSize;
|
use winit::dpi::LogicalSize;
|
||||||
use vulkano_win::VkSurfaceBuild;
|
use vulkano_win::VkSurfaceBuild;
|
||||||
use sprite::Sprite;
|
use sprite::Sprite;
|
||||||
use crate::canvas::CanvasFrame;
|
use crate::canvas::{CanvasFrame, CanvasImage};
|
||||||
use crate::compu_wip::{CompuSprite, ComputeFrame, CompuBuffers, CompuState};
|
use crate::compu_state::CompuState;
|
||||||
use crate::util::compute_image::ComputeImage;
|
use crate::compu_frame::CompuFrame;
|
||||||
|
use crate::compu_sprite::CompuSprite;
|
||||||
|
use crate::compu_kernel::CompuKernel;
|
||||||
|
use crate::compu_buffer::CompuBuffers;
|
||||||
|
use crate::util::load_raw;
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
mod slider;
|
mod slider;
|
||||||
@@ -33,7 +37,12 @@ mod vertex_2d;
|
|||||||
mod vertex_3d;
|
mod vertex_3d;
|
||||||
mod sprite;
|
mod sprite;
|
||||||
mod canvas;
|
mod canvas;
|
||||||
mod compu_wip;
|
mod canvas_frame;
|
||||||
|
mod compu_state;
|
||||||
|
mod compu_frame;
|
||||||
|
mod compu_sprite;
|
||||||
|
mod compu_kernel;
|
||||||
|
mod compu_buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -174,7 +183,6 @@ vkprocessor.run(CanvasFrame, CompuFrame)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let instance = {
|
let instance = {
|
||||||
@@ -211,25 +219,24 @@ fn main() {
|
|||||||
let sprite = Sprite::new_with_color((0.,0.), (0.1,0.1), (1.,0.,0.,1.));
|
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.));
|
let sprite2 = Sprite::new_with_color((-1.,-0.5), (0.1,0.1), (0.,1.,0.,1.));
|
||||||
|
|
||||||
/*
|
|
||||||
I need to get the image id from the CompuState
|
|
||||||
But the CompuState is owned by the vkprocessor I think...
|
|
||||||
|
|
||||||
I will also need to get the texture id
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1), processor.new_swap_image((300, 300)));
|
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1), processor.new_swap_image((300, 300)));
|
||||||
|
|
||||||
let image_data = ComputeImage::load_raw(String::from("funky-bird.jpg"));
|
let image_data = load_raw(String::from("funky-bird.jpg"));
|
||||||
let compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4);
|
let compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4);
|
||||||
|
|
||||||
|
// TODO need to implement
|
||||||
let compute_kernel = processor.get_kernel_handle(String::from("simple-edge.compute"))
|
let compute_kernel = processor.get_kernel_handle(String::from("simple-edge.compute"))
|
||||||
.expect("Can't find that kernel");
|
.expect("Can't find that kernel");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while let Some(p) = window.get_position() {
|
while let Some(p) = window.get_position() {
|
||||||
|
|
||||||
elapsed_time = timer.elap_time();
|
elapsed_time = timer.elap_time();
|
||||||
@@ -278,7 +285,7 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut compu_frame = ComputeFrame::new();
|
let mut compu_frame = CompuFrame::new();
|
||||||
compu_frame.add(compute_buffer.clone(), compute_kernel.clone());
|
compu_frame.add(compute_buffer.clone(), compute_kernel.clone());
|
||||||
compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1);
|
compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1);
|
||||||
|
|
||||||
|
|||||||
@@ -1,172 +0,0 @@
|
|||||||
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
|
|
||||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet};
|
|
||||||
use vulkano::device::{Device};
|
|
||||||
use vulkano::pipeline::{ComputePipeline};
|
|
||||||
use std::time::SystemTime;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use image::{ImageBuffer};
|
|
||||||
use image::GenericImageView;
|
|
||||||
use vulkano::descriptor::pipeline_layout::PipelineLayout;
|
|
||||||
use vulkano::descriptor::descriptor_set::{PersistentDescriptorSetBuf};
|
|
||||||
use vulkano::image::attachment::AttachmentImage;
|
|
||||||
use vulkano::image::{ImageUsage};
|
|
||||||
use vulkano::format::Format;
|
|
||||||
use image::Rgba;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Compute Image holds read write swap and settings buffers for the kernel
|
|
||||||
|
|
||||||
This is a pretty specific use case. One in for settings. One in for data, two for the transfer.
|
|
||||||
|
|
||||||
multiple data inputs might be nice?
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ComputeImage {
|
|
||||||
|
|
||||||
device: Arc<Device>,
|
|
||||||
|
|
||||||
compute_graphics_swap_buffer: std::sync::Arc<vulkano::image::attachment::AttachmentImage>,
|
|
||||||
|
|
||||||
pub rw_buffers: Vec<Arc<CpuAccessibleBuffer<[u8]>>>,
|
|
||||||
pub settings_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl ComputeImage {
|
|
||||||
|
|
||||||
pub fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) {
|
|
||||||
|
|
||||||
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(filename.clone()));
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
(image_buffer, xy)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(device: Arc<Device>, image_filename: String) -> ComputeImage {
|
|
||||||
|
|
||||||
let (image_buffer, xy) = ComputeImage::load_raw(image_filename);
|
|
||||||
|
|
||||||
let compute_graphics_swap_buffer = {
|
|
||||||
|
|
||||||
let mut usage = ImageUsage::none();
|
|
||||||
usage.transfer_destination = true;
|
|
||||||
usage.storage = true;
|
|
||||||
|
|
||||||
AttachmentImage::with_usage(
|
|
||||||
device.clone(),
|
|
||||||
[xy.0, xy.1],
|
|
||||||
Format::R8G8B8A8Uint,
|
|
||||||
usage)
|
|
||||||
};
|
|
||||||
|
|
||||||
let data_length = xy.0 * xy.1 * 4;
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
};
|
|
||||||
|
|
||||||
ComputeImage{
|
|
||||||
device: device.clone(),
|
|
||||||
compute_graphics_swap_buffer: compute_graphics_swap_buffer.unwrap(),
|
|
||||||
|
|
||||||
rw_buffers: vec![write_buffer, read_buffer],
|
|
||||||
settings_buffer: settings_buffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_swap_buffer(&mut self) -> Arc<AttachmentImage> {
|
|
||||||
self.compute_graphics_swap_buffer.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_size(&self) -> (u32, u32) {
|
|
||||||
let xy = self.compute_graphics_swap_buffer.dimensions();
|
|
||||||
(xy[0], xy[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_read_buffer(&self) -> ImageBuffer<Rgba<u8>, Vec<u8>>{
|
|
||||||
|
|
||||||
let xy = self.get_size();
|
|
||||||
|
|
||||||
self.rw_buffers.get(0).unwrap().write().unwrap().map(|x| x);
|
|
||||||
let data_buffer_content = self.rw_buffers.get(0).unwrap().read().unwrap();
|
|
||||||
ImageBuffer::from_fn(xy.0, xy.1, |x, y| {
|
|
||||||
let r = data_buffer_content[((xy.0 * y + x) * 4 + 0) as usize] as u8;
|
|
||||||
let g = data_buffer_content[((xy.0 * y + x) * 4 + 1) as usize] as u8;
|
|
||||||
let b = data_buffer_content[((xy.0 * y + x) * 4 + 2) as usize] as u8;
|
|
||||||
let a = data_buffer_content[((xy.0 * y + x) * 4 + 3) as usize] as u8;
|
|
||||||
|
|
||||||
image::Rgba([r, g, b, a])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_image(&self) {
|
|
||||||
self.read_read_buffer().save(format!("output/{}.jpg", SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_descriptor_set(&self, compute_pipeline: std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>)
|
|
||||||
-> Arc<PersistentDescriptorSet<std::sync::Arc<ComputePipeline<PipelineLayout<shade_runner::layouts::ComputeLayout>>>, ((((),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u8]>>>),
|
|
||||||
PersistentDescriptorSetBuf<std::sync::Arc<vulkano::buffer::cpu_access::CpuAccessibleBuffer<[u32]>>>)>> {
|
|
||||||
|
|
||||||
Arc::new(PersistentDescriptorSet::start(compute_pipeline.clone(), 0)
|
|
||||||
.add_buffer(self.rw_buffers.get(0).unwrap().clone()).unwrap()
|
|
||||||
.add_buffer(self.rw_buffers.get(1).unwrap().clone()).unwrap()
|
|
||||||
.add_buffer(self.settings_buffer.clone()).unwrap()
|
|
||||||
.build().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,43 @@
|
|||||||
pub mod compute_image;
|
use image::GenericImageView;
|
||||||
pub mod compute_kernel;
|
use std::sync::Arc;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub mod shader_kernels;
|
pub mod shader_kernels;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) {
|
||||||
|
|
||||||
|
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(filename.clone()));
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
(image_buffer, xy)
|
||||||
|
}
|
||||||
@@ -7,11 +7,11 @@ use std::sync::Arc;
|
|||||||
use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities};
|
use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities};
|
||||||
use vulkano::image::swapchain::SwapchainImage;
|
use vulkano::image::swapchain::SwapchainImage;
|
||||||
use winit::{Window};
|
use winit::{Window};
|
||||||
use crate::util::compute_kernel::ComputeKernel;
|
use crate::canvas::{CanvasState, CanvasFrame, ImageHandle};
|
||||||
use crate::util::compute_image::ComputeImage;
|
use crate::compu_state::CompuState;
|
||||||
use crate::canvas::{Canvas, CanvasFrame};
|
|
||||||
use crate::compu_wip::{CompuState, ComputeFrame};
|
|
||||||
use vulkano::image::ImageUsage;
|
use vulkano::image::ImageUsage;
|
||||||
|
use crate::compu_buffer::CompuBufferHandle;
|
||||||
|
use crate::compu_frame::CompuFrame;
|
||||||
|
|
||||||
pub struct VkProcessor<'a> {
|
pub struct VkProcessor<'a> {
|
||||||
|
|
||||||
@@ -23,9 +23,6 @@ pub struct VkProcessor<'a> {
|
|||||||
pub queue: Arc<Queue>,
|
pub queue: Arc<Queue>,
|
||||||
pub dynamic_state: DynamicState,
|
pub dynamic_state: DynamicState,
|
||||||
|
|
||||||
pub compute_kernel: Option<ComputeKernel>,
|
|
||||||
pub compute_image: Option<ComputeImage>,
|
|
||||||
|
|
||||||
pub swapchain: Option<Arc<Swapchain<Window>>>,
|
pub swapchain: Option<Arc<Swapchain<Window>>>,
|
||||||
pub swapchain_images: Option<Vec<Arc<SwapchainImage<Window>>>>,
|
pub swapchain_images: Option<Vec<Arc<SwapchainImage<Window>>>>,
|
||||||
|
|
||||||
@@ -34,7 +31,7 @@ pub struct VkProcessor<'a> {
|
|||||||
compute_state: CompuState,
|
compute_state: CompuState,
|
||||||
|
|
||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
canvas: Canvas,
|
canvas: CanvasState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +71,7 @@ impl<'a> VkProcessor<'a> {
|
|||||||
swapchain_recreate_needed: false,
|
swapchain_recreate_needed: false,
|
||||||
compute_state: CompuState::new(),
|
compute_state: CompuState::new(),
|
||||||
capabilities: capabilities.clone(),
|
capabilities: capabilities.clone(),
|
||||||
canvas: Canvas::new(queue, device, physical, capabilities),
|
canvas: CanvasState::new(queue, device, physical, capabilities),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +152,7 @@ impl<'a> VkProcessor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new image which has the transfer usage
|
// Create a new image which has the transfer usage
|
||||||
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<u32> {
|
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<ImageHandle> {
|
||||||
let mut usage = ImageUsage::none();
|
let mut usage = ImageUsage::none();
|
||||||
usage.transfer_destination = true;
|
usage.transfer_destination = true;
|
||||||
usage.storage = true;
|
usage.storage = true;
|
||||||
@@ -163,25 +160,25 @@ impl<'a> VkProcessor<'a> {
|
|||||||
self.canvas.create_image(dimensions, usage)
|
self.canvas.create_image(dimensions, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<u32> {
|
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<CompuBufferHandle> {
|
||||||
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
|
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_compute_buffer(&mut self, handle: Arc<u32>) -> Vec<u8> {
|
pub fn read_compute_buffer(&mut self, handle: Arc<CompuBufferHandle>) -> Vec<u8> {
|
||||||
self.compute_state.read_compute_buffer(handle)
|
self.compute_state.read_compute_buffer(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_compute_buffer(&self, handle: Arc<u32>, data: Vec<u8>) {
|
pub fn write_compute_buffer(&self, handle: Arc<CompuBufferHandle>, data: Vec<u8>) {
|
||||||
self.compute_state.write_compute_buffer(handle, data)
|
self.compute_state.write_compute_buffer(handle, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self,
|
pub fn run(&mut self,
|
||||||
surface: &'a Arc<Surface<Window>>,
|
surface: &'a Arc<Surface<Window>>,
|
||||||
mut frame_future: Box<dyn GpuFuture>,
|
mut frame_future: Box<dyn GpuFuture>,
|
||||||
canvas_frame: CanvasFrame,
|
canvas_frame: CanvasFrame,
|
||||||
compute_frame: ComputeFrame,
|
compute_frame: CompuFrame,
|
||||||
)
|
)
|
||||||
-> Box<dyn GpuFuture> {
|
-> Box<dyn GpuFuture> {
|
||||||
|
|
||||||
// take the canvas frame and create the vertex buffers
|
// take the canvas frame and create the vertex buffers
|
||||||
// TODO: This performs gpu buffer creation. Shouldn't be in hotpath
|
// TODO: This performs gpu buffer creation. Shouldn't be in hotpath
|
||||||
|
|||||||
Reference in New Issue
Block a user