Most of the compute side is mocked up and compiling.

master
mitchellhansen 5 years ago
parent 9b8d5cd828
commit a3607ebc7d

@ -9,7 +9,7 @@ use vulkano::device::{Device, Queue};
use vulkano::instance::PhysicalDevice;
use vulkano::image::immutable::ImmutableImage;
use crate::util::shader_kernels::ShaderKernels;
use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage};
use vulkano::image::{Dimensions, ImageAccess, ImageDimensions, SwapchainImage, ImageUsage, AttachmentImage};
use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter};
use vulkano::descriptor::DescriptorSet;
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
@ -82,7 +82,8 @@ impl Vertex for ColoredVertex2D {
pub trait Drawable {
fn get_vertices(&self) -> Vec<(f32, f32)>;
fn get_color(&self) -> (f32, f32, f32, f32);
fn get_texture_id(&self) -> Option<String>;
fn get_texture_handle(&self) -> Option<Arc<u32>>;
fn get_image_handle(&self) -> Option<Arc<u32>>;
}
// Need three types of shaders. Solid, Textured, Compute
@ -95,7 +96,7 @@ pub enum ShaderType {
pub struct CanvasFrame {
colored_drawables : Vec<ColoredVertex2D>,
textured_drawables: HashMap<String, Vec<Vertex2D>>,
textured_drawables: HashMap<Arc<u32>, Vec<Vertex2D>>,
}
impl CanvasFrame {
@ -110,10 +111,10 @@ impl CanvasFrame {
// After done using this, need to call allocated vertex buffers
pub fn draw(&mut self, drawable: &dyn Drawable) {
match drawable.get_texture_id() {
match drawable.get_texture_handle() {
Some(id) => {
self.textured_drawables
.entry(id)
.entry(id.clone())
.or_insert(Vec::new())
.extend(drawable.get_vertices().iter().map(|n|
Vertex2D {
@ -145,8 +146,8 @@ pub struct Canvas {
colored_drawables : Vec<ColoredVertex2D>,
colored_vertex_buffer: Vec<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
textured_drawables: HashMap<String, Vec<Vertex2D>>,
textured_vertex_buffer: HashMap<String, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
textured_drawables: HashMap<Arc<u32>, Vec<Vertex2D>>,
textured_vertex_buffer: HashMap<Arc<u32>, Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync)>>,
shader_kernels: HashMap<ShaderType, ShaderKernels>,
@ -154,9 +155,13 @@ pub struct Canvas {
dynamic_state: DynamicState,
image_buffers: Vec<std::sync::Arc<vulkano::image::attachment::AttachmentImage>>,
image_buffer_handles: Vec<Arc<u32>>,
// Looks like we gotta hold onto the queue for managing textures
queue: Arc<Queue>,
sampler: Arc<Sampler>
sampler: Arc<Sampler>,
device: Arc<Device>,
}
@ -177,6 +182,7 @@ impl Canvas {
]);
Canvas {
colored_drawables: vec![],
colored_vertex_buffer: vec![],
@ -188,6 +194,10 @@ impl Canvas {
dynamic_state: DynamicState { line_width: None, viewports: None, scissors: None },
image_buffers: Vec::new(),
image_buffer_handles: Vec::new(),
device: device.clone(),
queue: queue.clone(),
sampler: Sampler::new(device.clone(), Filter::Linear, Filter::Linear,
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
@ -196,6 +206,18 @@ impl Canvas {
}
}
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<u32> {
self.image_buffers.push(
AttachmentImage::with_usage(
self.device.clone(),
[dimensions.0, dimensions.1],
Format::R8G8B8A8Uint,
usage).unwrap());
let id = Arc::new(self.image_buffers.len() as u32);
self.image_buffer_handles.push(id.clone());
id
}
// TODO Handle file not found gracefully
fn get_texture_from_file(&self, image_filename: String) -> Arc<ImmutableImage<Format>> {

@ -5,14 +5,15 @@ use vulkano::framebuffer::RenderPassAbstract;
use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
use vulkano::device::Device;
use crate::util::compute_kernel::ComputeKernel;
use image::{ImageBuffer};
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;
pub struct CompuSprite {
vertices: [(f32, f32); 6],
@ -22,28 +23,44 @@ pub struct CompuSprite {
image_handle: Arc<u32>,
}
impl CompuSprite {
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.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()
color: (0.0, 0.0, 0.0, 0.0),
image_handle: image_handle.clone(),
}
}
@ -60,7 +77,7 @@ impl CompuSprite {
}
}
#[derive(Clone)]
pub struct CompuBuffers {
dimensions: (u32, u32),
device: Arc<Device>,
@ -72,7 +89,6 @@ pub struct CompuBuffers {
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 = {
@ -99,33 +115,46 @@ impl CompuBuffers {
data_iter).unwrap()
};
CompuBuffers{
CompuBuffers {
dimensions: dimensions,
device: device.clone(),
io_buffers: vec![input_buffer, output_buffer],
settings_buffer: settings_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]>>>)>> {
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
@ -138,14 +167,42 @@ pub struct CompuState {
}
impl CompuState {
fn new_compute_buffer() -> Arc<u32> {
pub fn new() -> CompuState {
CompuState {
compute_buffers: vec![],
compute_buffer_handles: vec![],
kernels: vec![],
kernel_handles: vec![],
}
}
fn new_kernel(&mut self,
filename: String,
device: &Arc<Device>) -> Arc<u32> {
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);
@ -168,17 +225,39 @@ impl CompuState {
It will need to convert these into a logical list of command_buffer commands
*/
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 {
fn add() {
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));
}
fn add_chained(output_buffer_id: Arc<u32>, input_buffer_id: Arc<u32>, kernel_id: Arc<u32> ) {
/*
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));
}
fn add_with_image_swap(buffer_id: Arc<u32>, sprite: CompuSprite, ) {
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))
}
}

@ -21,6 +21,7 @@ use vulkano_win::VkSurfaceBuild;
use sprite::Sprite;
use crate::canvas::CanvasFrame;
use crate::compu_wip::{CompuSprite, ComputeFrame, CompuBuffers, CompuState};
use crate::util::compute_image::ComputeImage;
mod util;
mod slider;
@ -221,9 +222,14 @@ fn main() {
I will also need to get the texture id
*/
let compu_sprite1 = CompuSprite::new((-1.,-0.5), (0.1,0.1));
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 compute_buffer = processor.new_compute_buffer(image_data.0, image_data.1, 4);
let compute_kernel = processor.get_kernel_handle(String::from("simple-edge.compute"))
.expect("Can't find that kernel");
while let Some(p) = window.get_position() {
@ -273,13 +279,18 @@ fn main() {
return;
}
let mut compu_frame = ComputeFrame::new();
compu_frame.add(compute_buffer.clone(), compute_kernel.clone());
compu_frame.add_with_image_swap(compute_buffer.clone(), compute_kernel.clone(), &compu_sprite1);
let mut canvas = CanvasFrame::new();
canvas.draw(&sprite);
canvas.draw(&sprite2);
canvas.draw(&compu_sprite1);
(frame_future) = processor.run(&surface, frame_future, canvas);
(frame_future) = processor.run(&surface, frame_future,
canvas,
compu_frame);
}
}

@ -1,4 +1,5 @@
use crate::canvas::Drawable;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct Sprite {
@ -9,7 +10,7 @@ pub struct Sprite {
color: (f32, f32, f32, f32),
textured: bool,
texture_id: Option<String>,
texture_id: Option<Arc<u32>>,
}
@ -41,7 +42,7 @@ impl Sprite {
}
}
pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: String) -> Sprite {
pub fn new_with_texture(position: (f32, f32), size: (f32, f32), texture_id: Arc<u32>) -> Sprite {
let fsize = (size.0 as f32, size.1 as f32);
@ -75,7 +76,7 @@ impl Drawable for Sprite {
self.color.clone()
}
fn get_texture_id(&self) -> Option<String> {
fn get_texture_handle(&self) -> Option<Arc<u32>> {
match self.textured {
true => {
self.texture_id.clone()
@ -83,6 +84,10 @@ impl Drawable for Sprite {
false => None,
}
}
fn get_image_handle(&self) -> Option<Arc<u32>> {
None
}
}
/*

@ -38,7 +38,7 @@ pub struct ComputeImage {
impl ComputeImage {
fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) {
pub fn load_raw(filename: String) -> (Vec<u8>, (u32,u32)) {
let project_root =
std::env::current_dir()
@ -141,6 +141,7 @@ impl ComputeImage {
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;

@ -10,6 +10,8 @@ use winit::{Window};
use crate::util::compute_kernel::ComputeKernel;
use crate::util::compute_image::ComputeImage;
use crate::canvas::{Canvas, CanvasFrame};
use crate::compu_wip::{CompuState, ComputeFrame};
use vulkano::image::ImageUsage;
pub struct VkProcessor<'a> {
@ -29,6 +31,8 @@ pub struct VkProcessor<'a> {
swapchain_recreate_needed: bool,
compute_state: CompuState,
capabilities: Capabilities,
canvas: Canvas,
}
@ -36,6 +40,45 @@ pub struct VkProcessor<'a> {
impl<'a> VkProcessor<'a> {
pub fn preload_textures(&mut self) {
}
pub fn preload_kernels(&mut self) {
}
pub fn preload_shaders(&mut self) {
}
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<u32>> {
None
}
pub fn get_kernel_handle(&self, kernel_name: String) -> Option<Arc<u32>> {
None
}
pub fn get_shader_handle(&self, shader_name: String) -> Option<Arc<u32>> {
None
}
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<u32> {
let mut usage = ImageUsage::none();
usage.transfer_destination = true;
usage.storage = true;
self.canvas.create_image(dimensions, usage)
}
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<u32> {
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
}
pub fn read_compute_buffer(&mut self, handle: Arc<u32>) -> Vec<u8> {
self.compute_state.read_compute_buffer(handle)
}
pub fn write_compute_buffer(&self, handle: Arc<u32>, data: Vec<u8>) {
self.compute_state.write_compute_buffer(handle, data)
}
pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> {
let physical = PhysicalDevice::enumerate(instance).next().unwrap();
@ -68,6 +111,7 @@ impl<'a> VkProcessor<'a> {
swapchain: None,
swapchain_images: None,
swapchain_recreate_needed: false,
compute_state: CompuState::new(),
capabilities: capabilities.clone(),
canvas: Canvas::new(queue, device, physical, capabilities),
}
@ -153,8 +197,12 @@ impl<'a> VkProcessor<'a> {
surface: &'a Arc<Surface<Window>>,
mut frame_future: Box<dyn GpuFuture>,
canvas_frame: CanvasFrame,
compute_frame: ComputeFrame,
) -> Box<dyn GpuFuture> {
//
self.canvas.draw(canvas_frame);
self.canvas.allocate_vertex_buffers(self.device.clone());

Loading…
Cancel
Save