use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::{Device, DeviceExtensions, QueuesIter, Queue};
use vulkano::instance::{Instance, PhysicalDevice};
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 crate::compute::compu_state::CompuState;
use vulkano::image::ImageUsage;
use crate::compute::compu_frame::CompuFrame;
use crate::canvas::canvas_frame::{CanvasFrame};
use std::time::Duration;
use vulkano::pipeline::depth_stencil::{DynamicStencilValue, StencilFaceFlags};
use vulkano::pipeline::vertex::{OneVertexOneInstanceDefinition, SingleBufferDefinition};
use crate::canvas::canvas_state::CanvasState;
use crate::canvas::managed::shader::generic_shader::GenericShader;
use crate::canvas::managed::shader::text_shader::TextShader;
use crate::canvas::managed::handles::{CanvasTextureHandle, CompiledShaderHandle, CanvasFontHandle, CanvasImageHandle};
use crate::compute::managed::handles::{CompuKernelHandle, CompuBufferHandle};
use crate::util::vertex::{VertexTypes, ColorVertex3D, TextVertex3D, TextureVertex3D, ImageVertex3D};
pub struct VkProcessor<'a> {
pub instance: Arc<Instance>,
pub physical: PhysicalDevice<'a>,
pub device: Arc<Device>,
pub queues: QueuesIter,
pub queue: Arc<Queue>,
pub swapchain: Option<Arc<Swapchain<Window>>>,
pub swapchain_images: Option<Vec<Arc<SwapchainImage<Window>>>>,
swapchain_recreate_needed: bool,
canvas_state: CanvasState,
compute_state: CompuState,
capabilities: Capabilities,
}
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();
let queue_family = physical.queue_families().find(|&q| {
q.supports_graphics() &&
surface.is_supported(q).unwrap_or(false) &&
q.supports_compute()
}).unwrap();
let device_ext = DeviceExtensions { khr_swapchain: true, ..DeviceExtensions::none() };
let (device, mut queues) = Device::new(physical,
physical.supported_features(),
&device_ext,
[(queue_family, 0.5)].iter().cloned()).unwrap();
let queue = queues.next().unwrap();
let capabilities = surface.capabilities(physical).unwrap();
VkProcessor {
instance: instance.clone(),
physical: physical.clone(),
device: device.clone(),
queue: queue.clone(),
queues: queues,
swapchain: None,
swapchain_images: None,
swapchain_recreate_needed: false,
compute_state: CompuState::new(),
capabilities: capabilities.clone(),
canvas_state: CanvasState::new(queue, device, physical, capabilities),
}
}
pub fn is_open(&mut self) -> bool {
true
}
pub fn create_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) {
let (mut swapchain, images) = {
let capabilities = surface.capabilities(self.physical).unwrap();
let usage = capabilities.supported_usage_flags;
let alpha = capabilities.supported_composite_alpha.iter().next().unwrap();
let format = capabilities.supported_formats[0].0;
let initial_dimensions = if let Some(dimensions) = surface.window().get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
panic!("window closed");
};
Swapchain::new(self.device.clone(),
surface.clone(),
capabilities.min_image_count,
format,
initial_dimensions,
1,
usage,
&self.queue,
SurfaceTransform::Identity,
alpha,
PresentMode::Immediate, true, None).unwrap()
};
self.swapchain = Some(swapchain);
self.swapchain_images = Some(images);
}
pub fn recreate_swapchain(&mut self, surface: &'a Arc<Surface<Window>>) {
let dimensions = if let Some(dimensions) = surface.window().get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(surface.window().get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match self.swapchain.clone().unwrap().clone().recreate_with_dimension(dimensions) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => panic!("Uh oh"),
Err(err) => panic!("{:?}", err)
};
self.swapchain = Some(new_swapchain);
self.swapchain_images = Some(new_images);
}
pub fn preload_textures(&mut self) {
self.canvas_state.load_texture(String::from("funky-bird.jpg"));
self.canvas_state.load_texture(String::from("button.png"));
self.canvas_state.load_texture(String::from("background.jpg"));
self.canvas_state.load_texture(String::from("test2.png"));
self.canvas_state.load_texture(String::from("sfml.png"));
}
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-edge.compute"), self.device.clone());
}
pub fn preload_shaders(&mut self) {
self.canvas_state.load_shader::<GenericShader, ColorVertex3D>(String::from("color-passthrough"), self.physical.clone(), self.capabilities.clone());
self.canvas_state.load_shader::<GenericShader, TextureVertex3D>(String::from("simple_texture"), self.physical.clone(), self.capabilities.clone());
self.canvas_state.load_shader::<GenericShader, ImageVertex3D>(String::from("simple_image"), self.physical.clone(), self.capabilities.clone());
}
pub fn preload_fonts(&mut self) {
self.canvas_state.load_font(String::from("sansation.ttf"));
}
pub fn get_texture_handle(&self, texture_name: String) -> Option<Arc<CanvasTextureHandle>> {
self.canvas_state.get_texture_handle(texture_name)
}
pub fn get_kernel_handle(&self, kernel_name: String) -> Option<Arc<CompuKernelHandle>> {
self.compute_state.get_kernel_handle(kernel_name)
}
pub fn get_shader_handle(&self, shader_name: String) -> Option<Arc<CompiledShaderHandle>> {
self.canvas_state.get_shader_handle(shader_name)
}
pub fn get_font_handle(&self, font_name: String) -> Option<Arc<CanvasFontHandle>> {
self.canvas_state.get_font_handle(font_name)
}
pub fn new_swap_image(&mut self, dimensions: (u32, u32)) -> Arc<CanvasImageHandle> {
let mut usage = ImageUsage::none();
usage.transfer_destination = true;
usage.storage = true;
self.canvas_state.create_image(dimensions, usage)
}
pub fn new_compute_buffer(&mut self, data: Vec<u8>, dimensions: (u32, u32), stride: u32) -> Arc<CompuBufferHandle> {
self.compute_state.new_compute_buffer(data, dimensions, stride, self.device.clone())
}
pub fn read_compute_buffer(&mut self, handle: Arc<CompuBufferHandle>) -> Vec<u8> {
self.compute_state.read_compute_buffer(handle)
}
pub fn write_compute_buffer(&self, handle: Arc<CompuBufferHandle>, data: Vec<u8>) {
self.compute_state.write_compute_buffer(handle, data)
}
pub fn run(&mut self,
surface: &'a Arc<Surface<Window>>,
canvas_frame: CanvasFrame,
compute_frame: CompuFrame,
) {
{
let g = hprof::enter("Waiting at queue");
self.queue.wait();
}
let g = hprof::enter("Frame buffer, future, swapchain recreate");
let mut framebuffers =
self.canvas_state.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone());
if self.swapchain_recreate_needed {
self.recreate_swapchain(surface);
framebuffers =
self.canvas_state.window_size_dependent_setup(&self.swapchain_images.clone().unwrap().clone());
self.swapchain_recreate_needed = false;
}
let (image_num, acquire_future) =
match vulkano::swapchain::acquire_next_image(
self.swapchain.clone().unwrap().clone(),
None,
) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
self.swapchain_recreate_needed = true;
return;
}
Err(err) => panic!("{:?}", err)
};
drop(g);
let allocated_buffers = {
let g = hprof::enter("Canvas creates GPU buffers");
self.canvas_state.allocate(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");
let mut command_buffer = self.compute_state.compute_commands(compute_frame, command_buffer, &self.canvas_state);
drop(g);
let g = hprof::enter("Push draw commands to command buffer");
let mut command_buffer =
self.canvas_state.draw_commands(command_buffer, framebuffers, image_num, allocated_buffers);
let command_buffer = command_buffer.build().unwrap();
drop(g);
{
let g = hprof::enter("Joining on the framebuffer");
let mut future = sync::now(self.device.clone())
.join(acquire_future);
drop(g);
let g = hprof::enter("Running the kernel and waiting on the future");
let future = 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();
match future {
Ok(future) => {
future.wait(None).unwrap();
}
Err(FlushError::OutOfDate) => {
self.swapchain_recreate_needed = true;
}
Err(e) => {
println!("{:?}", e);
}
}
}
}
}