minimal example of 15ms lag

master
mitchellhansen 5 years ago
parent 3f14555c99
commit 9135d9ec84

@ -20,3 +20,5 @@ shaderc = "0.5.0"
#shade_runner = {version = "0.1.1", git = "https://github.com/MitchellHansen/shade_runner"}
shade_runner = {path = "../shade_runner"}
winit = "0.19.1"
#criterion = "0.3.0"
hprof = "0.1.3"

@ -1,9 +1,11 @@
#version 450
// These come in from the previous shader (vertex)
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;
void main() {
f_color = out_color;
}

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

@ -35,37 +35,37 @@ void main() {
uint idx = get_idx(0,0);
ivec4 p = separate(read_buffer.buf[get_idx(0 , 0)]);
ivec4 p0 = separate(read_buffer.buf[get_idx(0 , 1)]);
ivec4 p1 = separate(read_buffer.buf[get_idx(0 ,-1)]);
ivec4 p2 = separate(read_buffer.buf[get_idx(1 , 1)]);
ivec4 p3 = separate(read_buffer.buf[get_idx(-1,-1)]);
ivec4 p4 = separate(read_buffer.buf[get_idx(1 , 0)]);
ivec4 p5 = separate(read_buffer.buf[get_idx(-1, 0)]);
ivec4 p6 = separate(read_buffer.buf[get_idx(1 ,-1)]);
ivec4 p7 = separate(read_buffer.buf[get_idx(-1, 1)]);
ivec3 d0 = abs(p0.xyz - p1.xyz);
ivec3 d1 = abs(p2.xyz - p3.xyz);
ivec3 d2 = abs(p4.xyz - p5.xyz);
ivec3 d3 = abs(p6.xyz - p7.xyz);
ivec3 m = max(max(max(d0, d1), d2), d3);
if ((m.x + m.y + m.z) > 200){
p.x = 0;
p.y = 0;
p.z = 255;
}
else {
//p.w = 125;
}
write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x000000FF) ) | (p.x);
write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x0000FF00) ) | (p.y << 8);
write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x00FF0000) ) | (p.z << 16);
write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0xFF000000) ) | (p.w << 24);
// ivec4 p = separate(read_buffer.buf[get_idx(0 , 0)]);
// ivec4 p0 = separate(read_buffer.buf[get_idx(0 , 1)]);
// ivec4 p1 = separate(read_buffer.buf[get_idx(0 ,-1)]);
// ivec4 p2 = separate(read_buffer.buf[get_idx(1 , 1)]);
// ivec4 p3 = separate(read_buffer.buf[get_idx(-1,-1)]);
// ivec4 p4 = separate(read_buffer.buf[get_idx(1 , 0)]);
// ivec4 p5 = separate(read_buffer.buf[get_idx(-1, 0)]);
// ivec4 p6 = separate(read_buffer.buf[get_idx(1 ,-1)]);
// ivec4 p7 = separate(read_buffer.buf[get_idx(-1, 1)]);
//
// ivec3 d0 = abs(p0.xyz - p1.xyz);
// ivec3 d1 = abs(p2.xyz - p3.xyz);
// ivec3 d2 = abs(p4.xyz - p5.xyz);
// ivec3 d3 = abs(p6.xyz - p7.xyz);
//
// ivec3 m = max(max(max(d0, d1), d2), d3);
//
// if ((m.x + m.y + m.z) > 200){
// p.x = 0;
// p.y = 0;
// p.z = 255;
// }
// else {
//
// //p.w = 125;
// }
// write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x000000FF) ) | (p.x);
// write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x0000FF00) ) | (p.y << 8);
// write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0x00FF0000) ) | (p.z << 16);
// write_buffer.buf[idx] = (write_buffer.buf[idx] & (~0xFF000000) ) | (p.w << 24);
}

@ -1,8 +1,14 @@
#version 450
// SIMPLE TEXTURE : FRAGMENT SHADER
// These come in from the previous shader (vertex)
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;
// 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;
void main() {

@ -1,10 +1,16 @@
#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;
// These are made up in the shader themselves
layout(location = 0) out vec2 tex_coords;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
tex_coords = position;
}

@ -22,6 +22,7 @@ use vulkano::descriptor::descriptor::DescriptorDescTy::TexelBuffer;
use crate::canvas_frame::CanvasFrame;
use std::hash::Hash;
use crate::canvas_shader::CanvasShader;
use crate::canvas_buffer::{CanvasImage, CanvasTexture};
// Canvas is the accumulator of Sprites for drawing
@ -103,48 +104,6 @@ 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)]
pub struct CanvasState {
dynamic_state: DynamicState,
@ -199,7 +158,6 @@ impl CanvasState {
device: Arc<Device>,
physical: PhysicalDevice,
capabilities: Capabilities) -> CanvasState {
let solid_color_kernel = String::from("color-passthrough");
let texture_kernel = String::from("simple_texture");
@ -238,7 +196,6 @@ impl CanvasState {
}
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 image = CanvasImage {
@ -324,7 +281,6 @@ impl CanvasState {
pub fn get_texture_handle(&self, texture_name: String)
-> Option<Arc<CanvasTextureHandle>> {
for i in self.texture_buffers.clone() {
if i.name == texture_name {
return Some(i.handle.clone());
@ -335,7 +291,6 @@ impl CanvasState {
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
-> Arc<ImmutableImage<Format>> {
let handle = texture_handle.handle as usize;
if let Some(i) = self.texture_buffers.get(handle) {
@ -355,10 +310,25 @@ impl CanvasState {
}
fn allocate_vertex_buffers(&mut self, device: Arc<Device>) {
self.colored_vertex_buffer.clear();
self.textured_vertex_buffer.clear();
self.image_vertex_buffer.clear();
/*
So a bit of brainstorming with the shaders:
I compile shaders into their respective buffers and add them to a descriptor set
along with the textures or whatever other resource buffer
So I'm gonna fix that texturing issue by adding vertex texture coordinate attributes
Still don't really know how I'm gonna do this...
* Going to definitely need to use the CpuAccessbileBuffer
* Maybe calculate deltas between frames???
*
*/
//TODO should probably use cpu accessible buffer instead of recreating immutes each frame
/*
CpuAccessibleBuffer::from_iter(
@ -369,6 +339,21 @@ impl CanvasState {
).unwrap().0;
*/
//if self.colored_vertex_buffer.len() == 0 {
self.colored_vertex_buffer.clear();
{
let g = hprof::enter("Colored Vertex Buffer : From Data");
self.colored_vertex_buffer.push(
ImmutableBuffer::from_data(self.colored_drawables.clone(),
BufferUsage::vertex_buffer(),
self.queue.clone()).unwrap().0
);
}
{
let g = hprof::enter("Colored Vertex Buffer : From Iter");
self.colored_vertex_buffer.push(
ImmutableBuffer::from_iter(
self.colored_drawables.iter().cloned(),
@ -376,9 +361,20 @@ impl CanvasState {
self.queue.clone(),
).unwrap().0
);
}
self.colored_vertex_buffer.clear();
//println!("{:?}", self.colored_vertex_buffer.last().unwrap().size());
//self.colored_vertex_buffer.pop();
// }
// println!("{} {}", self.textured_vertex_buffer.len() , self.textured_drawables.len());
// if self.textured_vertex_buffer.len() != self.textured_drawables.len() {
self.textured_vertex_buffer.clear();
for (k, v) in self.textured_drawables.drain() {
println!("{:?}", v.len());
{
let g = hprof::enter("Textured Vertex Buffer : From Iter");
self.textured_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter(
@ -388,10 +384,22 @@ impl CanvasState {
).unwrap().0,
);
}
// {
// let g = hprof::enter("Textured Vertex Buffer : From Data");
// self.textured_vertex_buffer.insert(
// k.clone(),
// ImmutableBuffer::from_data(v.first().unwrap().clone(),
// BufferUsage::vertex_buffer(),
// self.queue.clone()
// ).unwrap().0
// );
// }
//self.textured_vertex_buffer.pop();
}
// }
}
fn get_solid_color_descriptor_set(&self, kernel: Arc<CanvasShader>) -> Box<dyn DescriptorSet + Send + Sync> {
let o: Box<dyn DescriptorSet + Send + Sync> = Box::new(
PersistentDescriptorSet::start(
kernel.clone().get_pipeline().clone(), 0,
@ -414,32 +422,36 @@ impl CanvasState {
// Solid colors
let mut shader = self.shader_buffers.get("color-passthrough").unwrap().clone();
// This looks a little weird as colored_vertex_buffer is a vec of GPU allocated vecs.
// But we can pass in multiple vertex buffers
if !self.colored_vertex_buffer.is_empty() {
command_buffer = command_buffer.draw(
shader.get_pipeline().clone(),
&self.dynamic_state.clone(),
self.colored_vertex_buffer.clone(),
(), (),
).unwrap();
}
// Images
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 vertex_buffer = self.textured_vertex_buffer.get(&handle).unwrap().clone();
println!("{:?}", self.texture_buffers.len());
command_buffer = command_buffer.draw(
shader.get_pipeline().clone(),
&self.dynamic_state.clone(), vec![vertex_buffer],
vec![descriptor_set], ()
vec![descriptor_set], (),
).unwrap();
}
/*for (shader_type, kernel) in self.shader_kernels.clone().iter() {
match shader_type {
ShaderType::SOLID => {

@ -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 std::sync::Arc;
use std::collections::HashMap;
use crate::canvas::{Drawable, CanvasTextureHandle, CanvasImage, CanvasImageHandle};
use crate::canvas::{Drawable, CanvasTextureHandle, CanvasImageHandle};
pub struct CanvasFrame {
pub colored_drawables: Vec<ColoredVertex2D>,

@ -1,7 +1,7 @@
use std::ffi::CStr;
use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage};
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::pipeline::{GraphicsPipelineAbstract, ComputePipeline};
use vulkano::device::Device;

@ -9,6 +9,7 @@ extern crate nalgebra as na;
extern crate rand;
extern crate sfml;
extern crate time;
extern crate hprof;
use sfml::system::*;
use vulkano::sync;
@ -38,6 +39,7 @@ mod sprite;
mod canvas;
mod canvas_frame;
mod canvas_shader;
mod canvas_buffer;
mod compu_state;
mod compu_frame;
@ -45,6 +47,7 @@ mod compu_sprite;
mod compu_kernel;
mod compu_buffer;
/*
Alright, what the hell do I do next...
@ -55,6 +58,10 @@ Canvas works, but I want to use CPU accessible buffer instead of immutable buffe
fn main() {
hprof::start_frame();
let q1 = hprof::enter("setup");
let instance = {
let extensions = vulkano_win::required_extensions();
Instance::new(None, &extensions, None).unwrap()
@ -67,11 +74,16 @@ fn main() {
let mut window = surface.window();
let mut processor = vkprocessor::VkProcessor::new(&instance, &surface);
{
let g = hprof::enter("vulkan preload");
processor.create_swapchain(&surface);
processor.preload_kernels();
processor.preload_shaders();
processor.preload_textures();
}
let q2 = hprof::enter("Game Objects");
let mut timer = Timer::new();
let mut frame_future = Box::new(sync::now(processor.device.clone())) as Box<dyn GpuFuture>;
@ -84,10 +96,6 @@ fn main() {
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 sprite2 = Sprite::new_with_color((-1.,-0.5), (0.1,0.1), (0.,1.,0.,1.));
@ -105,9 +113,14 @@ fn main() {
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();
delta_time = elapsed_time - current_time;
current_time = elapsed_time;
@ -120,9 +133,7 @@ fn main() {
accumulator_time -= step_size;
}
println!("{}", delta_time);
let mut exit = false;
// println!("{}", delta_time);
events_loop.poll_events(|event| {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } =>
@ -133,7 +144,6 @@ fn main() {
processor.recreate_swapchain(&surface);
},
Event::DeviceEvent { event: DeviceEvent::Key(keyboard_input), .. } => {
match keyboard_input.virtual_keycode.unwrap() {
VirtualKeyCode::A => {
if keyboard_input.state == ElementState::Pressed {
@ -151,25 +161,32 @@ fn main() {
});
if exit {
return;
break;
}
let mut compu_frame = CompuFrame::new();
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(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(&sprite3);
canvas.draw(&compu_sprite1);
//canvas.draw(&sprite2);
//canvas.draw(&sprite3);
//canvas.draw(&compu_sprite1);
{
let g = hprof::enter("Run");
(frame_future) = processor.run(&surface, frame_future,
canvas,
compu_frame);
}
}
drop(l);
hprof::end_frame();
hprof::profiler().print_timing();
}

@ -1,12 +1,13 @@
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue};
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::sync::{GpuFuture, FlushError};
use vulkano::sync::{GpuFuture, FlushError, NowFuture};
use vulkano::sync::now;
use vulkano::sync;
use std::sync::Arc;
use vulkano::swapchain::{Swapchain, PresentMode, SurfaceTransform, Surface, SwapchainCreationError, AcquireError, Capabilities};
use vulkano::image::swapchain::SwapchainImage;
use winit::{Window};
use winit::Window;
use crate::compu_state::CompuState;
use vulkano::image::ImageUsage;
use crate::compu_frame::CompuFrame;
@ -16,7 +17,6 @@ use crate::compu_kernel::{CompuKernel, CompuKernelHandle};
use crate::compu_buffer::{CompuBuffers, CompuBufferHandle};
pub struct VkProcessor<'a> {
// Vulkan state fields
pub instance: Arc<Instance>,
pub physical: PhysicalDevice<'a>,
@ -38,7 +38,6 @@ pub struct VkProcessor<'a> {
impl<'a> VkProcessor<'a> {
pub fn new(instance: &'a Arc<Instance>, surface: &'a Arc<Surface<Window>>) -> VkProcessor<'a> {
let physical = PhysicalDevice::enumerate(instance).next().unwrap();
@ -141,10 +140,7 @@ impl<'a> VkProcessor<'a> {
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());
}
pub fn preload_shaders(&mut self) {
}
pub fn preload_shaders(&mut self) {}
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> {
self.canvas.get_texture_handle(texture_name)
}
@ -183,10 +179,11 @@ impl<'a> VkProcessor<'a> {
compute_frame: CompuFrame,
)
-> Box<dyn GpuFuture> {
{
let g = hprof::enter("Waiting at queue");
self.queue.wait();
}
// 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 framebuffers =
self.canvas.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone());
@ -214,20 +211,33 @@ impl<'a> VkProcessor<'a> {
Err(err) => panic!("{:?}", err)
};
let future = frame_future.join(acquire_future);
{
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 =
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
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
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);
drop(g);
// And build
let command_buffer = command_buffer.build().unwrap();
// Wait on the previous frame, then execute the command buffer and present the image
let future = frame_future.join(acquire_future)
let future = 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)
.then_signal_fence_and_flush();

Loading…
Cancel
Save