minimal example of 15ms lag

This commit is contained in:
2019-09-05 21:40:56 -07:00
parent 3f14555c99
commit 9135d9ec84
12 changed files with 273 additions and 165 deletions

View File

@@ -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");
@@ -212,16 +170,16 @@ impl CanvasState {
texture_buffers: 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()))
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()))
capabilities.clone(),
queue.clone(),
physical.clone(),
device.clone()))
),
]),
@@ -238,8 +196,7 @@ 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 handle = Arc::new(CanvasImageHandle { handle: self.image_buffers.len() as u32 });
let image = CanvasImage {
handle: handle.clone(),
@@ -323,8 +280,7 @@ impl CanvasState {
}
pub fn get_texture_handle(&self, texture_name: String)
-> Option<Arc<CanvasTextureHandle>> {
-> Option<Arc<CanvasTextureHandle>> {
for i in self.texture_buffers.clone() {
if i.name == texture_name {
return Some(i.handle.clone());
@@ -334,8 +290,7 @@ impl CanvasState {
}
pub fn get_texture(&self, texture_handle: Arc<CanvasTextureHandle>)
-> Arc<ImmutableImage<Format>> {
-> 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,29 +339,67 @@ impl CanvasState {
).unwrap().0;
*/
self.colored_vertex_buffer.push(
ImmutableBuffer::from_iter(
self.colored_drawables.iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).unwrap().0
);
//if self.colored_vertex_buffer.len() == 0 {
for (k, v) in self.textured_drawables.drain() {
println!("{:?}", v.len());
self.textured_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter(
v.first().unwrap().iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).unwrap().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(),
BufferUsage::vertex_buffer(),
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() {
{
let g = hprof::enter("Textured Vertex Buffer : From Iter");
self.textured_vertex_buffer.insert(
k.clone(),
ImmutableBuffer::from_iter(
v.first().unwrap().iter().cloned(),
BufferUsage::vertex_buffer(),
self.queue.clone(),
).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();
command_buffer = command_buffer.draw(
shader.get_pipeline().clone(),
&self.dynamic_state.clone(),
self.colored_vertex_buffer.clone(),
(), (),
).unwrap();
// 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();
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
if !self.textured_vertex_buffer.is_empty() {
let handle = self.get_texture_handle(String::from("funky-bird.jpg")).unwrap().clone();
let descriptor_set = self.texture_buffers.first().clone().unwrap().clone()
.get_descriptor_set(shader.clone(), self.sampler.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], ()
).unwrap();
let vertex_buffer = self.textured_vertex_buffer.get(&handle).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() {
match shader_type {
ShaderType::SOLID => {

50
src/canvas_buffer.rs Normal file
View File

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

View File

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

View File

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

View File

@@ -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);
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();
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);
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,11 +144,10 @@ 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 {
// processor.save_edges_image();
// processor.save_edges_image();
}
}
_ => ()
@@ -151,23 +161,30 @@ 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);
(frame_future) = processor.run(&surface, frame_future,
canvas,
compu_frame);
//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();
}

View File

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