Merge pull request #1 from MitchellHansen/debugging

Pulling in the debug of the frame timing
master
Mitchell 5 years ago committed by GitHub
commit e8ddb67b9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -20,3 +20,5 @@ 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"
#criterion = "0.3.0"
hprof = "0.1.3"

@ -1,9 +1,11 @@
#version 450 #version 450
// These come in from the previous shader (vertex)
layout(location = 0) in vec4 out_color; layout(location = 0) in vec4 out_color;
// This goes out to the bound image in window_size_dependent setup
layout(location = 0) out vec4 f_color; layout(location = 0) out vec4 f_color;
void main() { void main() {
f_color = out_color; f_color = out_color;
} }

@ -1,7 +1,10 @@
#version 450 #version 450
// These come in from the vertex definition
layout(location = 0) in vec2 position; layout(location = 0) in vec2 position;
layout(location = 1) in vec4 color; layout(location = 1) in vec4 color;
// These are made up in the shader themselves
layout(location = 0) out vec4 out_color; layout(location = 0) out vec4 out_color;
void main() { void main() {

@ -1,6 +1,6 @@
#version 450 #version 450
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(set = 0, binding = 0) buffer wData { layout(set = 0, binding = 0) buffer wData {
int buf[]; int buf[];
@ -58,7 +58,6 @@ void main() {
p.z = 255; p.z = 255;
} }
else { else {
//p.w = 125; //p.w = 125;
} }
@ -69,10 +68,6 @@ void main() {
} }
// Just gonna keep this around // Just gonna keep this around
// read_buffer.buf[idx] = (read_buffer.buf[idx] & (~0x000000FF) ) | (p.x); // read_buffer.buf[idx] = (read_buffer.buf[idx] & (~0x000000FF) ) | (p.x);
// read_buffer.buf[idx] = (read_buffer.buf[idx] & (~0x0000FF00) ) | (p.y << 8); // read_buffer.buf[idx] = (read_buffer.buf[idx] & (~0x0000FF00) ) | (p.y << 8);

@ -1,8 +1,14 @@
#version 450 #version 450
// SIMPLE TEXTURE : FRAGMENT SHADER
// These come in from the previous shader (vertex)
layout(location = 0) in vec2 tex_coords; layout(location = 0) in vec2 tex_coords;
// This goes out to the bound image in window_size_dependent setup
layout(location = 0) out vec4 f_color; layout(location = 0) out vec4 f_color;
// This is bound by the descriptor set
// Currently handled by the individual buffer and are 1:1
layout(set = 0, binding = 0) uniform sampler2D tex; layout(set = 0, binding = 0) uniform sampler2D tex;
void main() { void main() {

@ -1,10 +1,16 @@
#version 450 #version 450
// SIMPLE TEXTURE : VERTEX SHADER
// These come in from the vertex definition
// TODO : Need to add texture coordinate attribute so I can single VBO all these sumbitches
layout(location = 0) in vec2 position; layout(location = 0) in vec2 position;
// These are made up in the shader themselves
layout(location = 0) out vec2 tex_coords; layout(location = 0) out vec2 tex_coords;
void main() { void main() {
gl_Position = vec4(position, 0.0, 1.0); gl_Position = vec4(position, 0.0, 1.0);
tex_coords = position; tex_coords = position;
} }

@ -22,46 +22,26 @@ use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
use crate::canvas_frame::CanvasFrame; use crate::canvas_frame::CanvasFrame;
use std::hash::Hash; use std::hash::Hash;
use crate::canvas_shader::CanvasShader; use crate::canvas_shader::CanvasShader;
use crate::canvas_buffer::{CanvasImage, CanvasTexture};
// Canvas is the accumulator of Sprites for drawing
// Needs to know:
// textured?
// colored?
// vertices
/* /*
If it is textured. It needs to be rendered with the texture shader which requires a separate 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. graphics pipeline. Might as well have a new render pass as well.
So framebuffer is tied to the swapchains images as well as the renderpass So framebuffer is tied to the swapchains images as well as the renderpass
it appears that renderpass is tied to the individual shader 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 trait for Drawable Vertices.
pub trait Vertex { pub trait Vertex {
fn position(&self) -> (f32, f32) { fn position(&self) -> (f32, f32) {
(0.0, 0.0) (0.0, 0.0)
} }
fn color(&self) -> Option<(f32, f32, f32, f32)> { fn color(&self) -> Option<(f32, f32, f32, f32)> {
Some((0., 0., 0., 0.)) Some((0., 0., 0., 0.))
} }
} }
impl Vertex for ColoredVertex2D { impl Vertex for ColoredVertex2D {
fn position(&self) -> (f32, f32) { fn position(&self) -> (f32, f32) {
(0.0, 0.0) (0.0, 0.0)
@ -72,6 +52,8 @@ impl Vertex for ColoredVertex2D {
} }
} }
/// A drawable object can be passed into a CanvasFrame to be rendered
/// Allows Texture or Image drawing via their handles
pub trait Drawable { pub trait Drawable {
fn get_vertices(&self) -> Vec<(f32, f32)>; fn get_vertices(&self) -> Vec<(f32, f32)>;
fn get_color(&self) -> (f32, f32, f32, f32); fn get_color(&self) -> (f32, f32, f32, f32);
@ -79,7 +61,7 @@ pub trait Drawable {
fn get_image_handle(&self) -> Option<Arc<CanvasImageHandle>>; fn get_image_handle(&self) -> Option<Arc<CanvasImageHandle>>;
} }
// Need three types of shaders. Solid, Textured, Image /// Legacy ShaderType enum for single type shaders.
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
pub enum ShaderType { pub enum ShaderType {
SOLID = 0, SOLID = 0,
@ -87,64 +69,18 @@ pub enum ShaderType {
IMAGE = 2, IMAGE = 2,
} }
/// Typed wrapper for a u32 texture handle (index id)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct CanvasTextureHandle { pub struct CanvasTextureHandle {
pub handle: u32 pub handle: u32
} }
/// Typed wrapper for a u32 image handle (index id)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct CanvasImageHandle { pub struct CanvasImageHandle {
pub handle: u32 pub handle: u32
} }
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct CanvasShaderHandle {
pub handle: u32
}
#[derive(Clone)]
pub struct CanvasTexture {
handle: Arc<CanvasTextureHandle>,
buffer: Arc<ImmutableImage<Format>>,
name: String,
size: (u32, u32),
}
impl CanvasTexture {
fn get_descriptor_set(&self,
shader: Arc<CanvasShader>,
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<CanvasImageHandle>,
buffer: Arc<AttachmentImage>,
size: (u32, u32),
}
impl CanvasImage {
fn get_descriptor_set(&mut self, shader: Arc<CanvasShader>)
-> 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)] #[derive(Clone)]
pub struct CanvasState { pub struct CanvasState {
dynamic_state: DynamicState, dynamic_state: DynamicState,
@ -200,9 +136,6 @@ impl CanvasState {
physical: PhysicalDevice, physical: PhysicalDevice,
capabilities: Capabilities) -> CanvasState { capabilities: Capabilities) -> CanvasState {
let solid_color_kernel = String::from("color-passthrough");
let texture_kernel = String::from("simple_texture");
CanvasState { CanvasState {
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,
@ -210,20 +143,7 @@ impl CanvasState {
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![],
texture_buffers: vec![], texture_buffers: vec![],
shader_buffers: HashMap::from_iter(vec![ shader_buffers: HashMap::from_iter(vec![]),
(solid_color_kernel.clone(), Arc::new(CanvasShader::new_colored(solid_color_kernel.clone(),
capabilities.clone(),
queue.clone(),
physical.clone(),
device.clone()))
),
(texture_kernel.clone(), Arc::new(CanvasShader::new_textured(texture_kernel.clone(),
capabilities.clone(),
queue.clone(),
physical.clone(),
device.clone()))
),
]),
colored_drawables: vec![], colored_drawables: vec![],
colored_vertex_buffer: vec![], colored_vertex_buffer: vec![],
@ -238,8 +158,7 @@ impl CanvasState {
} }
pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<CanvasImageHandle> { pub fn create_image(&mut self, dimensions: (u32, u32), usage: ImageUsage) -> Arc<CanvasImageHandle> {
let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 });
let handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32});
let image = CanvasImage { let image = CanvasImage {
handle: handle.clone(), handle: handle.clone(),
@ -322,9 +241,24 @@ impl CanvasState {
Some(handle) Some(handle)
} }
pub fn get_texture_handle(&self, texture_name: String) /// Load and Compile a shader with the filename at resources/shaders
-> Option<Arc<CanvasTextureHandle>> { /// Takes physical and capabilities as we don't store that in Canvas
pub fn load_shader(&mut self,
filename: String,
physical: PhysicalDevice,
capabilities: Capabilities) {
self.shader_buffers.insert(filename.clone(),
Arc::new(CanvasShader::new_colored(filename.clone(),
capabilities.clone(),
self.queue.clone(),
physical.clone(),
self.device.clone())));
}
/// Using the texture name, iterates through the stored textures and matches by the name
pub fn get_texture_handle(&self, texture_name: String)
-> Option<Arc<CanvasTextureHandle>> {
for i in self.texture_buffers.clone() { for i in self.texture_buffers.clone() {
if i.name == texture_name { if i.name == texture_name {
return Some(i.handle.clone()); return Some(i.handle.clone());
@ -333,9 +267,9 @@ impl CanvasState {
None None
} }
/// Using the texture handle, grab the stored texture and return the buffer
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>) pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
-> Arc<ImmutableImage<Format>> { -> Arc<ImmutableImage<Format>> {
let handle = texture_handle.handle as usize; let handle = texture_handle.handle as usize;
if let Some(i) = self.texture_buffers.get(handle) { if let Some(i) = self.texture_buffers.get(handle) {
@ -345,53 +279,64 @@ impl CanvasState {
} }
} }
// After done using this, need to call allocated vertex buffers /// Scrape all the values from the CanvasFrame and then allocate the vertex buffers
pub fn draw(&mut self, canvas_frame: CanvasFrame) { pub fn draw(&mut self, canvas_frame: CanvasFrame) {
self.textured_drawables = canvas_frame.textured_drawables; self.textured_drawables = canvas_frame.textured_drawables;
self.colored_drawables = canvas_frame.colored_drawables; self.colored_drawables = canvas_frame.colored_drawables;
self.image_drawables = canvas_frame.image_drawables; self.image_drawables = canvas_frame.image_drawables;
self.allocate_vertex_buffers(self.device.clone()); self.allocate_vertex_buffers();
} }
fn allocate_vertex_buffers(&mut self, device: Arc<Device>) { /// draw(canvas_fame) stored all the intermediate information, this function
self.colored_vertex_buffer.clear(); /// allocates the vertex buffers using that information
self.textured_vertex_buffer.clear(); fn allocate_vertex_buffers(&mut self) {
self.image_vertex_buffer.clear();
//TODO should probably use cpu accessible buffer instead of recreating immutes each frame
/*
CpuAccessibleBuffer::from_iter(
device.clone(), self.colored_vertex_buffer.clear();
BufferUsage::vertex_buffer(), {
self.colored_drawables.iter().cloned(), let g = hprof::enter("Colored Vertex Buffer");
).unwrap().0; self.colored_vertex_buffer.push(
*/
self.colored_vertex_buffer.push(
ImmutableBuffer::from_iter(
self.colored_drawables.iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).unwrap().0
);
for (k, v) in self.textured_drawables.drain() {
println!("{:?}", v.len());
self.textured_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter( ImmutableBuffer::from_iter(
v.first().unwrap().iter().cloned(), self.colored_drawables.iter().cloned(),
BufferUsage::vertex_buffer(), BufferUsage::vertex_buffer(),
self.queue.clone(), self.queue.clone(),
).unwrap().0, ).unwrap().0
); );
} }
self.textured_vertex_buffer.clear();
{
let g = hprof::enter("Textured Vertex Buffer");
for (k, v) in self.textured_drawables.drain() {
self.textured_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter(
v.first().unwrap().iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).unwrap().0,
);
}
}
self.image_vertex_buffer.clear();
{
let g = hprof::enter("Image Vertex Buffer");
for (k, v) in self.image_drawables.drain() {
self.image_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter(
v.first().unwrap().iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).unwrap().0,
);
}
}
} }
/// Builds the descriptor set for solid colors using the input kernel (needs to support solid colors)
fn get_solid_color_descriptor_set(&self, kernel: Arc<CanvasShader>) -> Box<dyn DescriptorSet + Send + Sync> { fn get_solid_color_descriptor_set(&self, kernel: Arc<CanvasShader>) -> 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(
kernel.clone().get_pipeline().clone(), 0, kernel.clone().get_pipeline().clone(), 0,
@ -399,6 +344,7 @@ impl CanvasState {
o o
} }
/// Pushes the draw commands s
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>>,
@ -414,47 +360,55 @@ impl CanvasState {
// Solid colors // Solid colors
let mut shader = self.shader_buffers.get("color-passthrough").unwrap().clone(); let mut shader = self.shader_buffers.get("color-passthrough").unwrap().clone();
command_buffer = command_buffer.draw( // This looks a little weird as colored_vertex_buffer is a vec of GPU allocated vecs.
shader.get_pipeline().clone(), // But we can pass in multiple vertex buffers
&self.dynamic_state.clone(), if !self.colored_vertex_buffer.is_empty() {
self.colored_vertex_buffer.clone(), command_buffer = command_buffer.draw(
(), (), shader.get_pipeline().clone(),
).unwrap(); &self.dynamic_state.clone(),
self.colored_vertex_buffer.clone(),
(), (),
).unwrap();
}
// Images // Textures
let mut shader = self.shader_buffers.get("simple_texture").unwrap().clone(); let mut shader = self.shader_buffers.get("simple_texture").unwrap().clone();
if !self.textured_vertex_buffer.is_empty() {
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
// TODO : BAD BAD BAD. SELECTS FIRST TEXTURE ONLY!!!!!!!!!!!!
let descriptor_set = self.texture_buffers.first().clone().unwrap().clone()
.get_descriptor_set(shader.clone(), self.sampler.clone());
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone(); let vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
let descriptor_set = self.texture_buffers.first().clone().unwrap().clone() command_buffer = command_buffer.draw(
.get_descriptor_set(shader.clone(), self.sampler.clone()); shader.get_pipeline().clone(),
&self.dynamic_state.clone(), vec![vertex_buffer],
vec![descriptor_set], (),
).unwrap();
}
let vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
println!("{:?}", self.texture_buffers.len()); let mut shader = self.shader_buffers.get("simple-image").unwrap().clone();
command_buffer = command_buffer.draw(
shader.get_pipeline().clone(),
&self.dynamic_state.clone(), vec![vertex_buffer],
vec![descriptor_set], ()
).unwrap();
/*for (shader_type, kernel) in self.shader_kernels.clone().iter() { if !self.image_vertex_buffer.is_empty() {
match shader_type {
ShaderType::SOLID => {
} let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
ShaderType::TEXTURED => {
command_buffer = command_buffer.draw( // TODO : BAD BAD BAD. SELECTS FIRST TEXTURE ONLY!!!!!!!!!!!!
kernel.clone().get_pipeline().clone(), let descriptor_set = self.texture_buffers.first().clone().unwrap().clone()
&dynamic_state.clone(), self.textured_vertex_buffer.clone(), .get_descriptor_set(shader.clone(), self.sampler.clone());
vec![self.get_textured_descriptor_set(String::from("funky-bird.jpg"))], ()
).unwrap(); let vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
}
ShaderType::IMAGE => {} command_buffer = command_buffer.draw(
} shader.get_pipeline().clone(),
}*/ &self.dynamic_state.clone(), vec![vertex_buffer],
vec![descriptor_set], (),
).unwrap();
}
command_buffer command_buffer
.end_render_pass() .end_render_pass()

@ -0,0 +1,50 @@
use crate::canvas::{CanvasTextureHandle, CanvasImageHandle};
use vulkano::image::{ImmutableImage, AttachmentImage};
use std::sync::Arc;
use vulkano::format::Format;
use crate::canvas_shader::CanvasShader;
use vulkano::sampler::Sampler;
use vulkano::descriptor::DescriptorSet;
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
#[derive(Clone)]
pub struct CanvasTexture {
pub(crate) handle: Arc<CanvasTextureHandle>,
pub(crate) buffer: Arc<ImmutableImage<Format>>,
pub(crate) name: String,
pub(crate) size: (u32, u32),
}
impl CanvasTexture {
pub fn get_descriptor_set(&self,
shader: Arc<CanvasShader>,
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 {
pub(crate) handle: Arc<CanvasImageHandle>,
pub(crate) buffer: Arc<AttachmentImage>,
pub(crate) size: (u32, u32),
}
impl CanvasImage {
pub fn get_descriptor_set(&mut self, shader: Arc<CanvasShader>)
-> 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
}
}

@ -1,7 +1,7 @@
use crate::vertex_2d::{ColoredVertex2D, Vertex2D}; use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
use std::sync::Arc; use std::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use crate::canvas::{Drawable, CanvasTextureHandle, CanvasImage, CanvasImageHandle}; use crate::canvas::{Drawable, CanvasTextureHandle, CanvasImageHandle};
pub struct CanvasFrame { pub struct CanvasFrame {
pub colored_drawables: Vec<ColoredVertex2D>, pub colored_drawables: Vec<ColoredVertex2D>,

@ -10,12 +10,13 @@ use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule, Specialization
use vulkano::swapchain::{Capabilities}; use vulkano::swapchain::{Capabilities};
use crate::vertex_2d::{ColoredVertex2D, Vertex2D}; use crate::vertex_2d::{ColoredVertex2D, Vertex2D};
/* /// Typed wrapper for a u32 shader handle (index id)
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
CanvasShader holds the pipeline and render pass for the inputted shader source pub struct CanvasShaderHandle {
pub handle: u32
*/ }
/// CanvasShader holds the pipeline and render pass for the input shader source
#[derive(Clone)] #[derive(Clone)]
pub struct CanvasShader { pub struct CanvasShader {
@ -27,6 +28,8 @@ pub struct CanvasShader {
impl CanvasShader { impl CanvasShader {
/// Takes the filename of a .vertex .fragment shader combo in resources/shaders/
/// Returns pathbuffer of that vertex and fragment shader
fn get_path(filename: String) -> (PathBuf, PathBuf) { fn get_path(filename: String) -> (PathBuf, PathBuf) {
let project_root = let project_root =
@ -47,10 +50,13 @@ impl CanvasShader {
(vertex_shader_path, fragment_shader_path) (vertex_shader_path, fragment_shader_path)
} }
/// Clone and returns the compiled graphics pipeline
pub fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> { pub fn get_pipeline(&self) -> Arc<dyn GraphicsPipelineAbstract + Sync + Send> {
self.graphics_pipeline.clone().unwrap() self.graphics_pipeline.clone().unwrap()
} }
/// Create a new `Colored` shader. Which just means that it uses ColoredVertex2D's
/// This will explode when the shader does not want to compile
pub fn new_colored(filename: String, pub fn new_colored(filename: String,
capabilities: Capabilities, capabilities: Capabilities,
queue: Arc<Queue>, queue: Arc<Queue>,
@ -168,6 +174,8 @@ impl CanvasShader {
} }
} }
/// Create a new `Textured` shader. Which just means that it uses plain Vertex2D's
/// This will explode when the shader does not want to compile
pub fn new_textured(filename: String, pub fn new_textured(filename: String,
capabilities: Capabilities, capabilities: Capabilities,
queue: Arc<Queue>, queue: Arc<Queue>,
@ -289,7 +297,7 @@ impl CanvasShader {
#[repr(C)] #[repr(C)]
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
// TODO: This needs to be duplicated and moved into their respective containers shaderkenrels copute /// Specialization constants which can be passed to the shader. Pretty much placeholder ATM
struct ShaderSpecializationConstants { struct ShaderSpecializationConstants {
first_constant: i32, first_constant: i32,
second_constant: u32, second_constant: u32,

@ -1,7 +1,7 @@
use std::ffi::CStr; use std::ffi::CStr;
use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage}; use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage};
use std::sync::Arc; use std::sync::Arc;
use crate::canvas::{Drawable, CanvasState, CanvasImageHandle, CanvasImage, CanvasTextureHandle}; use crate::canvas::{Drawable, CanvasState, CanvasImageHandle, CanvasTextureHandle};
use vulkano::framebuffer::RenderPassAbstract; use vulkano::framebuffer::RenderPassAbstract;
use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline}; use vulkano::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
use vulkano::device::Device; use vulkano::device::Device;
@ -104,7 +104,7 @@ impl CompuState {
let size = buffer.get_size(); let size = buffer.get_size();
command_buffer = command_buffer command_buffer = command_buffer
.dispatch([size.0,size.1,1], p, d, ()).unwrap() .dispatch([size.0/8,size.1/8,1], p, d, ()).unwrap()
} }
// i = (Buffer, Image, Kernel) // i = (Buffer, Image, Kernel)
@ -126,8 +126,10 @@ impl CompuState {
panic!("Buffer sizes not the same"); panic!("Buffer sizes not the same");
} }
let size = buffer.get_size();
command_buffer = command_buffer command_buffer = command_buffer
.dispatch([100,100,1], p, d, ()).unwrap() .dispatch([size.0,size.1,1], p, d, ()).unwrap()
.copy_buffer_to_image(buffer.get_input_buffer(), image).unwrap(); .copy_buffer_to_image(buffer.get_input_buffer(), image).unwrap();
} }

@ -9,6 +9,7 @@ extern crate nalgebra as na;
extern crate rand; extern crate rand;
extern crate sfml; extern crate sfml;
extern crate time; extern crate time;
extern crate hprof;
use sfml::system::*; use sfml::system::*;
use vulkano::sync; use vulkano::sync;
@ -27,23 +28,25 @@ use crate::compu_buffer::CompuBuffers;
use crate::util::load_raw; use crate::util::load_raw;
use crate::canvas_frame::CanvasFrame; use crate::canvas_frame::CanvasFrame;
mod util; pub mod util;
mod timer; pub mod timer;
mod input; pub mod input;
mod vkprocessor; pub mod vkprocessor;
mod vertex_2d; pub mod vertex_2d;
mod vertex_3d; pub mod vertex_3d;
mod sprite; pub mod sprite;
mod canvas; pub mod canvas;
mod canvas_frame; pub mod canvas_frame;
mod canvas_shader; pub mod canvas_shader;
pub mod canvas_buffer;
pub mod compu_state;
pub mod compu_frame;
pub mod compu_sprite;
pub mod compu_kernel;
pub mod compu_buffer;
mod compu_state;
mod compu_frame;
mod compu_sprite;
mod compu_kernel;
mod compu_buffer;
/* /*
@ -53,7 +56,13 @@ Canvas works, but I want to use CPU accessible buffer instead of immutable buffe
I think it would be faster if we reuse fewer oversized buffers than vis versa I think it would be faster if we reuse fewer oversized buffers than vis versa
*/ */
fn main() {
/// Main Entry
pub fn main() {
hprof::start_frame();
let q1 = hprof::enter("setup");
let instance = { let instance = {
let extensions = vulkano_win::required_extensions(); let extensions = vulkano_win::required_extensions();
@ -67,11 +76,16 @@ fn main() {
let mut window = surface.window(); let mut window = surface.window();
let mut processor = vkprocessor::VkProcessor::new(&instance, &surface); let mut processor = vkprocessor::VkProcessor::new(&instance, &surface);
processor.create_swapchain(&surface); {
let g = hprof::enter("vulkan preload");
processor.create_swapchain(&surface);
processor.preload_kernels();
processor.preload_shaders();
processor.preload_textures();
}
processor.preload_kernels(); let q2 = hprof::enter("Game Objects");
processor.preload_shaders();
processor.preload_textures();
let mut timer = Timer::new(); let mut timer = Timer::new();
let mut frame_future = Box::new(sync::now(processor.device.clone())) as Box<dyn GpuFuture>; let mut frame_future = Box::new(sync::now(processor.device.clone())) as Box<dyn GpuFuture>;
@ -84,10 +98,6 @@ fn main() {
let mut mouse_xy = Vector2i::new(0,0); let mut mouse_xy = Vector2i::new(0,0);
let sprite = Sprite::new_with_color((0.,0.), (0.1,0.1), (1.,0.,0.,1.)); let 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.));
@ -105,9 +115,14 @@ fn main() {
let sprite3 = Sprite::new_with_texture((0.3, 0.5), (0.1,0.1), handle.clone()); let sprite3 = Sprite::new_with_texture((0.3, 0.5), (0.1,0.1), handle.clone());
drop(q2);
drop(q1);
while let Some(p) = window.get_position() { let l = hprof::enter("Loop");
let mut exit = false;
while let Some(p) = window.get_position() {
elapsed_time = timer.elap_time(); elapsed_time = timer.elap_time();
delta_time = elapsed_time - current_time; delta_time = elapsed_time - current_time;
current_time = elapsed_time; current_time = elapsed_time;
@ -120,9 +135,7 @@ fn main() {
accumulator_time -= step_size; accumulator_time -= step_size;
} }
println!("{}", delta_time); // println!("{}", delta_time);
let mut exit = false;
events_loop.poll_events(|event| { events_loop.poll_events(|event| {
match event { match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
@ -133,11 +146,10 @@ fn main() {
processor.recreate_swapchain(&surface); processor.recreate_swapchain(&surface);
}, },
Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => { Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => {
match keyboard_input.virtual_keycode.unwrap() { match keyboard_input.virtual_keycode.unwrap() {
VirtualKeyCode::A => { VirtualKeyCode::A => {
if keyboard_input.state == ElementState::Pressed { if keyboard_input.state == ElementState::Pressed {
// processor.save_edges_image(); // processor.save_edges_image();
} }
} }
_ => () _ => ()
@ -151,7 +163,7 @@ fn main() {
}); });
if exit { if exit {
return; break;
} }
let mut compu_frame = CompuFrame::new(); let mut compu_frame = CompuFrame::new();
@ -162,12 +174,20 @@ fn main() {
canvas.draw(&sprite); canvas.draw(&sprite);
canvas.draw(&sprite2); canvas.draw(&sprite2);
canvas.draw(&sprite3); canvas.draw(&sprite3);
canvas.draw(&compu_sprite1); //canvas.draw(&compu_sprite1);
{
(frame_future) = processor.run(&surface, frame_future, let g = hprof::enter("Run");
canvas, processor.run(&surface,
compu_frame); //frame_future,
canvas,
compu_frame);
}
} }
drop(l);
hprof::end_frame();
hprof::profiler().print_timing();
} }

@ -1,22 +1,26 @@
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue}; use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue};
use vulkano::instance::{Instance, PhysicalDevice}; use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::sync::{GpuFuture, FlushError}; use vulkano::sync::{GpuFuture, FlushError, NowFuture};
use vulkano::sync::now;
use vulkano::sync; use vulkano::sync;
use std::sync::Arc; 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::compu_state::CompuState; use crate::compu_state::CompuState;
use vulkano::image::ImageUsage; use vulkano::image::ImageUsage;
use crate::compu_frame::CompuFrame; use crate::compu_frame::CompuFrame;
use crate::canvas::{CanvasState, CanvasTextureHandle, CanvasShaderHandle, CanvasImageHandle}; use crate::canvas::{CanvasState, CanvasTextureHandle, CanvasImageHandle};
use crate::canvas_frame::CanvasFrame; use crate::canvas_frame::CanvasFrame;
use crate::compu_kernel::{CompuKernel, CompuKernelHandle}; use crate::compu_kernel::{CompuKernel, CompuKernelHandle};
use crate::compu_buffer::{CompuBuffers, CompuBufferHandle}; use crate::compu_buffer::{CompuBuffers, CompuBufferHandle};
use std::time::Duration;
use crate::canvas_shader::CanvasShaderHandle;
/// VKProcessor holds the vulkan instance information, the swapchain, and the compute and canvas states
///
pub struct VkProcessor<'a> { pub struct VkProcessor<'a> {
// Vulkan state fields // Vulkan state fields
pub instance: Arc<Instance>, pub instance: Arc<Instance>,
pub physical: PhysicalDevice<'a>, pub physical: PhysicalDevice<'a>,
@ -39,7 +43,10 @@ pub struct VkProcessor<'a> {
impl<'a> VkProcessor<'a> { impl<'a> VkProcessor<'a> {
/// Creates a new VkProcessor from an instance and surface
/// This includes the physical device, queues, compute and canvas state
pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> { pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> {
let physical = PhysicalDevice::enumerate(instance).next().unwrap(); let physical = PhysicalDevice::enumerate(instance).next().unwrap();
let queue_family = physical.queue_families().find(|&q| { let queue_family = physical.queue_families().find(|&q| {
@ -75,6 +82,7 @@ impl<'a> VkProcessor<'a> {
} }
} }
/// Using the surface, we calculate the surface capabilities and create the swapchain and swapchain images
pub fn create_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) { pub fn create_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) {
let (mut swapchain, images) = { let (mut swapchain, images) = {
let capabilities = surface.capabilities(self.physical).unwrap(); let capabilities = surface.capabilities(self.physical).unwrap();
@ -103,14 +111,14 @@ impl<'a> VkProcessor<'a> {
&self.queue, &self.queue,
SurfaceTransform::Identity, SurfaceTransform::Identity,
alpha, alpha,
PresentMode::Fifo, true, None).unwrap() PresentMode::Immediate, true, None).unwrap()
}; };
self.swapchain = Some(swapchain); self.swapchain = Some(swapchain);
self.swapchain_images = Some(images); self.swapchain_images = Some(images);
} }
// On resizes we have to recreate the swapchain /// On screen resizes, the swapchain and images must be recreated
pub fn recreate_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) { pub fn recreate_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) {
let dimensions = if let Some(dimensions) = surface.window().get_inner_size() { let dimensions = if let Some(dimensions) = surface.window().get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into(); let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into();
@ -131,20 +139,27 @@ impl<'a> VkProcessor<'a> {
self.swapchain_images = Some(new_images); self.swapchain_images = Some(new_images);
} }
/// A hardcoded list of textures which can be preloaded from this function
pub fn preload_textures(&mut self) { pub fn preload_textures(&mut self) {
self.canvas.load_texture(String::from("funky-bird.jpg")); self.canvas.load_texture(String::from("funky-bird.jpg"));
self.canvas.load_texture(String::from("button.png")); self.canvas.load_texture(String::from("button.png"));
self.canvas.load_texture(String::from("background.jpg")); self.canvas.load_texture(String::from("background.jpg"));
self.canvas.load_texture(String::from("test2.png")); self.canvas.load_texture(String::from("test2.png"));
} }
/// A hardcoded list of kernels which can be preloaded from this function
pub fn preload_kernels(&mut self) { pub fn preload_kernels(&mut self) {
self.compute_state.new_kernel(String::from("simple-homogenize.compute"), self.device.clone()); self.compute_state.new_kernel(String::from("simple-homogenize.compute"), self.device.clone());
self.compute_state.new_kernel(String::from("simple-edge.compute"), self.device.clone()); self.compute_state.new_kernel(String::from("simple-edge.compute"), self.device.clone());
} }
pub fn preload_shaders(&mut self) {
/// A hardcoded list of shaders which can be proloaded from this function
pub fn preload_shaders(&mut self) {
self.canvas.load_shader(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
self.canvas.load_shader(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
} }
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> { pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> {
self.canvas.get_texture_handle(texture_name) self.canvas.get_texture_handle(texture_name)
} }
@ -178,22 +193,19 @@ impl<'a> VkProcessor<'a> {
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>,
canvas_frame: CanvasFrame, canvas_frame: CanvasFrame,
compute_frame: CompuFrame, compute_frame: CompuFrame,
) ) {
-> Box<dyn GpuFuture> {
// take the canvas frame and create the vertex buffers {
// TODO: This performs gpu buffer creation. Shouldn't be in hotpath let g = hprof::enter("Waiting at queue");
self.canvas.draw(canvas_frame); self.queue.wait();
}
let g = hprof::enter("Frame buffer, future, swapchain recreate");
let mut framebuffers = let mut framebuffers =
self.canvas.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone()); self.canvas.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone());
// 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. // 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. // In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
if self.swapchain_recreate_needed { if self.swapchain_recreate_needed {
@ -205,44 +217,69 @@ impl<'a> VkProcessor<'a> {
// This function can block if no image is available. The parameter is an optional timeout // This function can block if no image is available. The parameter is an optional timeout
// after which the function call will return an error. // after which the function call will return an error.
let (image_num, acquire_future) = match vulkano::swapchain::acquire_next_image(self.swapchain.clone().unwrap().clone(), None) { let (image_num, acquire_future) =
Ok(r) => r, match vulkano::swapchain::acquire_next_image(
Err(AcquireError::OutOfDate) => { self.swapchain.clone().unwrap().clone(),
self.swapchain_recreate_needed = true; None,
return Box::new(sync::now(self.device.clone())) as Box<_>; ) {
} Ok(r) => r,
Err(err) => panic!("{:?}", err) Err(AcquireError::OutOfDate) => {
}; self.swapchain_recreate_needed = true;
return;
}
Err(err) => panic!("{:?}", err)
};
drop(g);
{
let g = hprof::enter("Canvas creates GPU buffers");
// take the canvas frame and create the vertex buffers
// TODO: This performs gpu buffer creation. Shouldn't be in hotpath??
self.canvas.draw(canvas_frame);
}
let mut command_buffer = let mut command_buffer =
AutoCommandBufferBuilder::primary_one_time_submit(self.device.clone(), self.queue.family()).unwrap(); AutoCommandBufferBuilder::primary_one_time_submit(self.device.clone(), self.queue.family()).unwrap();
let g = hprof::enter("Push compute commands to command buffer");
// Add the compute commands // Add the compute commands
let mut command_buffer = self.compute_state.compute_commands(compute_frame, command_buffer, &self.canvas); let mut command_buffer = self.compute_state.compute_commands(compute_frame, command_buffer, &self.canvas);
drop(g);
let g = hprof::enter("Push draw commands to command buffer");
// Add the draw commands // Add the draw commands
let mut command_buffer = self.canvas.draw_commands(command_buffer, framebuffers, image_num); let mut command_buffer = self.canvas.draw_commands(command_buffer, framebuffers, image_num);
// And build // And build
let command_buffer = command_buffer.build().unwrap(); let command_buffer = command_buffer.build().unwrap();
drop(g);
// Wait on the previous frame, then execute the command buffer and present the image // Wait on the previous frame, then execute the command buffer and present the image
let future = frame_future.join(acquire_future) {
.then_execute(self.queue.clone(), command_buffer).unwrap()
.then_swapchain_present(self.queue.clone(), self.swapchain.clone().unwrap().clone(), image_num) let g = hprof::enter("Joining on the framebuffer");
.then_signal_fence_and_flush(); let mut future = sync::now(self.device.clone())
.join(acquire_future);
match future { drop(g);
Ok(future) => {
(Box::new(future) as Box<_>) let g = hprof::enter("Running the kernel and waiting on the future");
}
Err(FlushError::OutOfDate) => { let future = future
self.swapchain_recreate_needed = true; .then_execute(self.queue.clone(), command_buffer).unwrap()
(Box::new(sync::now(self.device.clone())) as Box<_>) .then_swapchain_present(self.queue.clone(), self.swapchain.clone().unwrap().clone(), image_num)
} .then_signal_fence_and_flush();
Err(e) => {
println!("{:?}", e); match future {
(Box::new(sync::now(self.device.clone())) as Box<_>) Ok(future) => {
future.wait(None).unwrap();
}
Err(FlushError::OutOfDate) => {
self.swapchain_recreate_needed = true;
}
Err(e) => {
println!("{:?}", e);
}
} }
} }
} }
@ -265,4 +302,3 @@ impl<'a> VkProcessor<'a> {

Loading…
Cancel
Save