in the midst of a very messy refactor of the way i build the command buffer

master
mitchellhansen 5 years ago
parent 56455774bc
commit c5b3c29ad4

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@ -1,5 +1,21 @@
use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use crate::Sprite;
use std::collections::HashMap;
use vulkano::buffer::{BufferAccess, CpuAccessibleBuffer, BufferUsage};
use std::sync::Arc;
use vulkano::format::{ClearValue, Format};
use vulkano::framebuffer::FramebufferAbstract;
use vulkano::device::{Device, Queue};
use vulkano::instance::PhysicalDevice;
use vulkano::image::immutable::ImmutableImage;
use crate::util::shader_kernels::ShaderKernels;
use vulkano::image::{Dimensions, ImageUsage, ImageAccess, ImageDimensions};
use vulkano::sampler::{Sampler, SamplerAddressMode, MipmapMode, Filter};
use vulkano::descriptor::DescriptorSet;
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
use std::path::PathBuf;
use image::GenericImageView;
// Canvas is the accumulator of Sprites for drawing
// Needs to know:
@ -12,34 +28,283 @@
If it is textured. It needs to be rendered with the texture shader which requires a separate
graphics pipeline. Might as well have a new render pass as well.
Need to pull recreate swapchain out of shader_kernels.rs
I need a second version of shaderkernels
So framebuffer is tied to the swapchains images as well as the renderpass
it appears that renderpass is tied to the individual shader
*/
// I want to be able to draw 2d sprites.
// These sprites might be textured or a single color
// All of the single colors will be grouped into one batch using colored vertices.
// The rest will be grouped by their texture and run individually
/*
vertex count differing is a big nono
ColoredVertex2D
Non-Textured
Vertex2D
Textured
Colored, vs non-colored:
Calling the color() field or not
I just wanna
*/
pub trait Vertex {
fn position(&self) -> (f32, f32) {
(0.0,0.0)
}
fn color(&self) -> Option<(f32, f32, f32, f32)> {
Some((0.,0.,0.,0.))
}
fn textured(&self) -> bool {
false
}
}
trait Drawable {
fn draw() {
impl Vertex for ColoredVertex2D {
fn position(&self) -> (f32, f32) {
(0.0,0.0)
}
fn color(&self) -> Option<(f32, f32, f32, f32)> {
Some((0.,0.,0.,0.))
}
fn textured(&self) -> bool {
false
}
}
pub trait Drawable {
fn get_vertices(&self) -> Vec<(f32, f32)>;
fn get_color(&self) -> (f32, f32, f32, f32);
fn get_texture_id(&self) -> Option<i32>;
}
pub struct Canvas {
colored_drawables : Vec<ColoredVertex2D>,
textured_drawables: HashMap<String, Vec<Vertex2D>>,
vertex_buffers: Vec<Arc<(dyn BufferAccess + std::marker::Send + std::marker::Sync + 'static)>>,
shader_kernels: Vec<ShaderKernels>,
textures: Vec<Arc<ImmutableImage<Format>>>,
}
impl Canvas {
// needs to take in the texture list
pub fn new() -> Canvas {
Canvas {
colored_drawables: vec![],
textured_drawables: Default::default(),
vertex_buffers: vec![],
shader_kernels: Vec::new(),
textures: vec![]
}
}
fn get_texture_from_file(image_filename: String, queue: Arc<Queue>) -> Arc<ImmutableImage<Format>> {
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(image_filename));
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();
}
let (texture, tex_future) = ImmutableImage::from_iter(
image_buffer.iter().cloned(),
Dimensions::Dim2d { width: xy.0, height: xy.1 },
Format::R8G8B8A8Srgb,
queue.clone()
).unwrap();
texture
}
pub fn draw() ->
pub fn load_texture_from_filename(&mut self, filename: String, queue: Arc<Queue>) {
let texture = Canvas::get_texture_from_file(filename.clone(), queue.clone());
self.textures.push(texture);
let texture1 = Canvas::get_texture_from_file(String::from("button.png"), queue.clone());
self.textures.push(texture1);
}
pub fn draw(&mut self, drawable: &dyn Drawable) {
match drawable.get_texture_id() {
Some(id) => {
// This dont work
self.textured_drawables.get(&id).unwrap();
},
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]
}
)
);
}
}
}
pub fn allocate_vertex_buffers(&mut self, device: Arc<Device>) {
self.vertex_buffers.push(
CpuAccessibleBuffer::from_iter(
device.clone(),
BufferUsage::vertex_buffer(),
self.colored_drawables.iter().cloned()
).unwrap()
);
}
// The image set is the containing object for all texture and image hooks.
fn get_texture_set(&mut self, device: Arc<Device>) -> Box<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<DescriptorSet + Send + Sync> = Box::new(
PersistentDescriptorSet::start(
self.shader_kernels.get(0).unwrap().clone().unwrap().get_pipeline(), 0
)
.add_sampled_image(self.textures.get(0).unwrap().clone(), sampler.clone()).unwrap()
.build().unwrap());
o
}
// The image set is the containing object for all texture and image hooks.
fn get_compute_swap_set(&mut self, device: Arc<Device>) -> Box<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<DescriptorSet + Send + Sync> = Box::new(
PersistentDescriptorSet::start(
self.shader_kernels.get(0).unwrap().clone().unwrap().get_pipeline(), 0
)
.add_image(self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap()
.build().unwrap());
o
}
/*
So I need the image set in order to get my texture or compute texture
compute image currently holds the set for compute and its swap buffer
vkprocessor creates the image sets for draw calls
takes the pipeline from the ShaderKernel
adds vk processor owned texture
adds compute image taken from the ComputeImage
we have shaderkernel in here so thats fine
Who should own the texture?
I would need to borrow it each time I created an image set...
These are tied very closely to the input output of a shader, which we would own
I just need to add a third option on sprite and allow it to have a swap buffer
*/
pub fn draw_commands(&mut self,
command_buffer: AutoCommandBufferBuilder,
framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
image_num: usize) -> AutoCommandBufferBuilder {
// Specify the color to clear the framebuffer with i.e. blue
let clear_values = vec!(ClearValue::Float([0.0, 0.0, 1.0, 1.0]));
let dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None };
let mut command_buffer = command_buffer.begin_render_pass(
framebuffers[image_num].clone(), false, clear_values.clone()
).unwrap();
// for i in self.shader_kernels {
// command_buffer = command_buffer.draw(
// i.clone().unwrap().get_pipeline(),
// &dynamic_state.clone(), self.vertex_buffers,
// vec![self.get_image_set()], ()
// ).unwrap();
// }
//
// .draw(self.shader_kernels.clone().unwrap().get_pipeline(),
// &dynamic_state.clone(), self.vertex_buffers,
// vec![self.get_gui_image_set()], ())
// .unwrap();
//
command_buffer
.end_render_pass()
.unwrap()
}
}

@ -47,15 +47,17 @@ use winit::dpi::LogicalSize;
use vulkano_win::VkSurfaceBuild;
use sprite::Sprite;
mod util;
mod slider;
mod timer;
mod input;
mod vkprocessor;
mod util;
mod button;
mod vertex_2d;
mod vertex_3d;
mod sprite;
mod canvas;
fn main() {
@ -87,10 +89,8 @@ fn main() {
let mut mouse_xy = Vector2i::new(0,0);
Sprite::new_with_color((0.,0.), (0,0), (0.,0.,0.,0.));
while let Some(p) = window.get_position() {
elapsed_time = timer.elap_time();

@ -1,9 +1,18 @@
use crate::vertex_2d::ColoredVertex2D;
use crate::canvas::Drawable;
#[derive(Debug, Clone)]
pub struct Sprite {
vertices: [ColoredVertex2D; 6],
color: [f32; 4],
pub vertices: [(f32, f32); 6],
position: (f32, f32),
size: (u32, u32),
color: (f32, f32, f32, f32),
textured: bool,
texture_id: i32,
}
impl Sprite {
@ -14,21 +23,80 @@ impl Sprite {
pub fn new_with_color(position: (f32, f32), size: (u32, u32), color: (f32, f32, f32, f32)) -> Sprite {
let size = (size.0 as f32, size.1 as f32);
let color = [color.0, color.1, color.2, color.3];
let fsize = (size.0 as f32, size.1 as f32);
Sprite {
vertices: [
ColoredVertex2D { position: [ position.0, position.1 ], color }, // top left
ColoredVertex2D { position: [ position.0, position.1 + size.1], color }, // bottom left
ColoredVertex2D { position: [ position.0 + size.0, position.1 + size.1 ], color }, // bottom right
ColoredVertex2D { position: [ position.0, position.1 ], color }, // top left
ColoredVertex2D { position: [ position.0 + size.0, position.1 + size.1 ], color }, // bottom right
ColoredVertex2D { position: [ position.0 + size.0, position.1 ], color }, // 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: color,
textured: false,
texture_id: 0
}
}
pub fn new_with_texture(position: (f32, f32), size: (u32, u32), texture_id: i32) -> Sprite {
let fsize = (size.0 as f32, size.1 as f32);
Sprite {
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,
size,
color: (0.0, 0.0, 0.0, 0.0),
textured: false,
texture_id
}
}
}
impl Drawable for Sprite {
fn get_vertices(&self) -> Vec<(f32,f32)> {
self.vertices.to_vec()
}
fn get_color(&self) -> (f32, f32, f32, f32) {
self.color.clone()
}
fn get_texture_id(&self) -> Option<i32> {
match self.textured {
true => {
Some(self.texture_id.clone())
},
false => None,
}
}
}
/*
let vertex_buffer = {
CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::all(), [
ColoredVertex2D { position: [ 1.0, 1.0 ], color },
ColoredVertex2D { position: [ 1.0, 0.5 ], color },
ColoredVertex2D { position: [ 0.5, 0.5 ], color },
ColoredVertex2D { position: [ 0.5, 1.0 ], color },
].iter().cloned()).unwrap()
};
*/

@ -1,34 +0,0 @@
//use crate::error::CompileError;
//use shaderc::{IncludeType, ResolvedInclude};
//use shaderc::{ShaderKind, CompileOptions};
//use std::fs::File;
//use std::io::Read;
//use std::path::{Path, PathBuf};
//
//
//
//pub fn compile<T>(path: T, shader_kind: ShaderKind) -> Result<Vec<u32>, CompileError>
// where
// T: AsRef<Path>,
//{
// // TODO Probably shouldn't create this every time.
// let mut compiler = shaderc::Compiler::new().ok_or(CompileError::CreateCompiler)?;
// let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler)?;
// let mut f = File::open(&path).map_err(CompileError::Open)?;
// let mut src = String::new();
// f.read_to_string(&mut src).map_err(CompileError::Open)?;
// options.set_include_callback(|path, include_type, folder_path, depth| {
// get_include(path, include_type, folder_path, depth)
// });
// let result = compiler
// .compile_into_spirv(
// src.as_str(),
// shader_kind,
// path.as_ref().to_str().ok_or(CompileError::InvalidPath)?,
// "main",
// Some(&options),
// )
// .map_err(CompileError::Compile)?;
// let data = result.as_binary();
// Ok(data.to_owned())
//}

@ -0,0 +1,3 @@
pub mod compute_image;
pub mod compute_kernel;
pub mod shader_kernels;

@ -11,3 +11,12 @@ pub struct ColoredVertex2D {
}
vulkano::impl_vertex!(ColoredVertex2D, position, color);
vulkano::impl_vertex!(Vertex2D, position);
impl From<(f32, f32)> for Vertex2D {
fn from(item: (f32, f32)) -> Self {
Vertex2D { position: [item.0, item.1] }
}
}

@ -9,3 +9,7 @@ pub struct ColoredVertex3D {
position: [f32; 3],
color : [u8; 4],
}
vulkano::impl_vertex!(ColoredVertex3D, position, color);
vulkano::impl_vertex!(Vertex3D, position);

@ -35,22 +35,19 @@ use vulkano::image::immutable::ImmutableImage;
use vulkano::image::attachment::AttachmentImage;
use vulkano::image::{Dimensions, ImageUsage, ImageAccess, ImageDimensions};
use vulkano::format::Format;
use vulkano::format::ClearValue;
use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode};
use image::flat::NormalForm::ColumnMajorPacked;
mod compute_kernel;
use crate::vkprocessor::compute_kernel::ComputeKernel;
mod shader_kernels;
use crate::vkprocessor::shader_kernels::ShaderKernels;
mod compute_image;
use crate::vkprocessor::compute_image::ComputeImage;
use crate::util::compute_kernel::ComputeKernel;
use crate::util::shader_kernels::ShaderKernels;
use crate::util::compute_image::ComputeImage;
use vulkano::descriptor::descriptor::DescriptorDesc;
use crate::vertex_2d::ColoredVertex2D;
/// This method is called once during initialization, then again whenever the window is resized
fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
@ -100,6 +97,8 @@ pub struct VkProcessor<'a> {
pub swapchain: Option<Arc<Swapchain<Window>>>,
pub swapchain_images: Option<Vec<Arc<SwapchainImage<Window>>>>,
swapchain_recreate_needed: bool,
}
@ -137,7 +136,8 @@ impl<'a> VkProcessor<'a> {
textures: vec![],
compute_image: None,
swapchain: None,
swapchain_images: None
swapchain_images: None,
swapchain_recreate_needed: false,
}
}
@ -176,7 +176,7 @@ impl<'a> VkProcessor<'a> {
Swapchain::new(self.device.clone(),
surface.clone(),
capabilities.min_image_count,
capabilities.min_image_count, // number of attachment images
format,
initial_dimensions,
1, // Layers
@ -287,6 +287,9 @@ impl<'a> VkProcessor<'a> {
].iter().cloned()).unwrap()
};
self.vertex_buffer = Some(vertex_buffer);
self.vertex_buffer2 = Some(vertex_buffer2);
@ -344,20 +347,17 @@ impl<'a> VkProcessor<'a> {
self.shader_kernels.clone().unwrap().render_pass.clone(),
&mut self.dynamic_state);
let mut recreate_swapchain = false;
// The docs said to call this on each loop.
frame_future.cleanup_finished();
// Whenever the window resizes we need to recreate everything dependent on the window size.
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
if recreate_swapchain {
if self.swapchain_recreate_needed {
self.recreate_swapchain(surface);
framebuffers = window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone(),
self.shader_kernels.clone().unwrap().render_pass.clone(),
//self.render_pass.clone().unwrap().clone(),
&mut self.dynamic_state);
recreate_swapchain = false;
self.swapchain_recreate_needed = false;
}
// This function can block if no image is available. The parameter is an optional timeout
@ -365,15 +365,14 @@ impl<'a> VkProcessor<'a> {
let (image_num, acquire_future) = match vulkano::swapchain::acquire_next_image(self.swapchain.clone().unwrap().clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
//continue;
panic!("Weird thing");
self.swapchain_recreate_needed = true;
return Box::new(sync::now(self.device.clone())) as Box<_>;
}
Err(err) => panic!("{:?}", err)
};
// Specify the color to clear the framebuffer with i.e. blue
let clear_values = vec!([0.0, 0.0, 1.0, 1.0].into());
let clear_values = vec!(ClearValue::Float([0.0, 0.0, 1.0, 1.0]));
let mut v = Vec::new();
v.push(self.vertex_buffer.clone().unwrap().clone());
@ -383,7 +382,7 @@ impl<'a> VkProcessor<'a> {
let xy = self.compute_image.clone().unwrap().get_size();
let command_buffer =
let mut command_buffer =
AutoCommandBufferBuilder::primary_one_time_submit(self.device.clone(), self.queue.family())
.unwrap()
@ -395,19 +394,20 @@ impl<'a> VkProcessor<'a> {
.copy_buffer_to_image(self.compute_image.clone().unwrap().clone().rw_buffers.get(0).unwrap().clone(),
self.compute_image.clone().unwrap().clone().get_swap_buffer().clone()).unwrap()
.begin_render_pass(framebuffers[image_num].clone(), false, clear_values)
.begin_render_pass(framebuffers[image_num].clone(), false, clear_values.clone())
.unwrap()
.draw(self.shader_kernels.clone().unwrap().get_pipeline(),
&self.dynamic_state.clone(), v,
vec![self.get_image_set()], ())
.unwrap()
.unwrap();
.draw(self.shader_kernels.clone().unwrap().get_pipeline(),
command_buffer = command_buffer.draw(self.shader_kernels.clone().unwrap().get_pipeline(),
&self.dynamic_state.clone(), v2,
vec![self.get_gui_image_set()], ())
.unwrap()
.unwrap();
let command_buffer = command_buffer
.end_render_pass()
.unwrap()
@ -424,7 +424,7 @@ impl<'a> VkProcessor<'a> {
(Box::new(future) as Box<_>)
}
Err(FlushError::OutOfDate) => {
recreate_swapchain = true;
self.swapchain_recreate_needed = true;
(Box::new(sync::now(self.device.clone())) as Box<_>)
}
Err(e) => {

Loading…
Cancel
Save