use crate::shaders::*;
use crate::vertex::Vertex;
use std::sync::Arc;
use vulkano::command_buffer::DynamicState;
use vulkano::device::{Device, DeviceExtensions, Queue};
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract, Subpass};
use vulkano::image::SwapchainImage;
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::pipeline::viewport::Viewport;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::swapchain::*;
use vulkano::swapchain::{PresentMode, SurfaceTransform, Swapchain};
use vulkano::sync;
use vulkano::sync::GpuFuture;
use vulkano_win::VkSurfaceBuild;
use winit::dpi::LogicalSize;
use winit::EventsLoop;
use winit::{Window, WindowBuilder};
pub struct Preper {
pub device: Arc<Device>,
pub queue: Arc<Queue>,
pub surface: Arc<Surface<Window>>,
pub swapchain: Arc<Swapchain<Window>>,
pub images: Vec<Arc<SwapchainImage<Window>>>,
pub render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
pub fill_pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
pub tex_pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
pub stroke_pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
pub dynamic_state: DynamicState,
pub framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
pub recreate_swapchain: bool,
pub previous_frame_end: Option<Box<dyn GpuFuture>>,
}
pub fn init(w: u16, h: u16) -> (Preper, EventsLoop) {
let instance = {
let extensions = vulkano_win::required_extensions();
Instance::new(None, &extensions, None).unwrap()
};
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
let events_loop = EventsLoop::new();
let surface = WindowBuilder::new()
.with_dimensions(LogicalSize {
width: w as f64,
height: h as f64,
})
.with_title("Canvas")
.with_decorations(true)
.build_vk_surface(&events_loop, instance.clone())
.unwrap();
let window = surface.window();
let queue_family = physical
.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
.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 (swapchain, images) = {
let caps = surface.capabilities(physical).unwrap();
let usage = caps.supported_usage_flags;
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let initial_dimensions = {
let dimensions: (u32, u32) = window
.get_inner_size()
.unwrap()
.to_physical(window.get_hidpi_factor())
.into();
[dimensions.0, dimensions.1]
};
Swapchain::new(
device.clone(),
surface.clone(),
caps.min_image_count,
format,
initial_dimensions,
1,
usage,
&queue,
SurfaceTransform::Identity,
alpha,
PresentMode::Fifo,
true,
None,
)
.unwrap()
};
let render_pass = Arc::new(
vulkano::single_pass_renderpass!(
device.clone(),
attachments: {
color: {
load:Clear,
store: Store,
format: swapchain.format(),
samples: 1,
}
},
pass: {
color: [color],
depth_stencil: {}
}
)
.unwrap(),
);
let vs = vs::Shader::load(device.clone()).unwrap();
let fs = fs::Shader::load(device.clone()).unwrap();
let fsimg = fsimg::Shader::load(device.clone()).unwrap();
let fill_pipeline = Arc::new(
GraphicsPipeline::start()
.vertex_input_single_buffer::<Vertex>()
.vertex_shader(vs.main_entry_point(), ())
.triangle_list()
.line_width_dynamic()
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(fs.main_entry_point(), ())
.blend_alpha_blending()
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap(),
);
let tex_pipeline = Arc::new(
GraphicsPipeline::start()
.vertex_input_single_buffer::<Vertex>()
.vertex_shader(vs.main_entry_point(), ())
.triangle_list()
.line_width_dynamic()
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(fsimg.main_entry_point(), ())
.blend_alpha_blending()
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap(),
);
let stroke_pipeline = Arc::new(
GraphicsPipeline::start()
.vertex_input_single_buffer::<Vertex>()
.vertex_shader(vs.main_entry_point(), ())
.line_list()
.line_width_dynamic()
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(fs.main_entry_point(), ())
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap(),
);
let mut dynamic_state = DynamicState {
line_width: None,
viewports: None,
scissors: None,
compare_mask: None,
write_mask: None,
reference: None,
};
let framebuffers =
window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
let recreate_swapchain = false;
let previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<dyn GpuFuture>);
(
Preper {
device,
queue,
surface,
swapchain,
images,
render_pass,
fill_pipeline,
tex_pipeline,
stroke_pipeline,
dynamic_state,
framebuffers,
recreate_swapchain,
previous_frame_end,
},
events_loop,
)
}
pub fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
dynamic_state: &mut DynamicState,
) -> Vec<Arc<dyn FramebufferAbstract + Send + Sync>> {
let dimensions = images[0].dimensions();
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0..1.0,
};
dynamic_state.viewports = Some(vec![viewport]);
images
.iter()
.map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone())
.unwrap()
.build()
.unwrap(),
) as Arc<dyn FramebufferAbstract + Send + Sync>
})
.collect::<Vec<_>>()
}