lots of refactoring

master
mitchellhansen 5 years ago
parent 878b37c3e0
commit 1737319fc5

@ -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"

@ -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 { #[derive(Clone)]
pub struct TextureHandle {
handle: u32
}
pub fn new() -> CanvasFrame { #[derive(Clone)]
CanvasFrame { pub struct ImageHandle {
colored_drawables: vec![], handle: u32
textured_drawables: Default::default(), }
image_drawables: Default::default()
}
}
// Accumulates the drawables vertices and colors #[derive(Clone)]
pub fn draw(&mut self, drawable: &dyn Drawable) { pub struct ShaderHandle {
handle: u32
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() { #[derive(Clone)]
pub struct CanvasTexture {
handle: Arc<TextureHandle>,
buffer: Arc<ImmutableImage<Format>>,
name: String,
size: (u32, u32),
}
Some(handle) => { impl CanvasTexture {
self.image_drawables fn get_descriptor_set(&mut self,
.entry(handle.clone()) shader: Arc<ShaderKernels>,
.or_insert(Vec::new()) sampler: Arc<Sampler>) -> Box<dyn DescriptorSet + Send + Sync> {
.push(drawable.get_vertices().iter().map(|n| let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
Vertex2D { PersistentDescriptorSet::start(
position: [n.0, n.1], shader.clone().get_pipeline().clone(), 0,
}
).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],
}
) )
); .add_sampled_image(self.buffer.clone(), sampler.clone()).unwrap()
} .build().unwrap());
} o
}
}
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Canvas { pub struct CanvasImage {
shader_kernels: HashMap<ShaderType, ShaderKernels>, handle: Arc<ImageHandle>,
buffer: Arc<AttachmentImage>,
size: (u32, u32),
}
texture_store: HashMap<String, Arc<ImmutableImage<Format>>>, 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,8 +171,7 @@ 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>> {
@ -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,43 +353,21 @@ 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();
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new( } else {
PersistentDescriptorSet::start( panic!("{} : Texture not loaded", texture_id);
self.shader_kernels.get(&ShaderType::SOLID).unwrap().clone().get_pipeline().clone(), 0,
).build().unwrap());
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 fn get_solid_color_descriptor_set(&self, kernel: Arc<ShaderKernels>) -> Box<dyn DescriptorSet + Send + Sync> {
// 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( let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
PersistentDescriptorSet::start( PersistentDescriptorSet::start(
self.shader_kernels.get(&ShaderType::IMAGE).clone().unwrap().clone().get_pipeline(), 0, kernel.clone().get_pipeline().clone(), 0,
) ).build().unwrap());
.add_image(compute_image.clone().get_swap_buffer().clone()).unwrap()
.build().unwrap());
o o
} }
@ -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()
} }
} }

@ -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],
}
)
);
}
}
}
}
}
}

@ -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,
}

@ -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,

@ -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()
}
}

@ -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
}
}

@ -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))
}
}

@ -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,15 +160,15 @@ 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)
} }
@ -179,7 +176,7 @@ impl<'a> VkProcessor<'a> {
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> {

Loading…
Cancel
Save