Skip to content

Instantly share code, notes, and snippets.

@AtheMathmo
Created August 28, 2020 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AtheMathmo/3fed0665400fd6850cf0d144bb9b9070 to your computer and use it in GitHub Desktop.
Save AtheMathmo/3fed0665400fd6850cf0d144bb9b9070 to your computer and use it in GitHub Desktop.
use vulkano::instance::Instance;
use vulkano::instance::PhysicalDevice;
use vulkano::device::Device;
use vulkano::swapchain;
use vulkano::swapchain::AcquireError;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::CpuAccessibleBuffer;
use vulkano::framebuffer::Framebuffer;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::framebuffer::Subpass;
use vulkano::command_buffer::DynamicState;
use vulkano::pipeline::viewport::Viewport;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::CommandBuffer;
use vulkano::sync::GpuFuture;
use vulkano_win::VkSurfaceBuild;
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
use vulkano::swapchain::{Swapchain, SurfaceTransform, PresentMode, ColorSpace, FullscreenExclusive};
use vulkano::image::ImageUsage;
use std::sync::Arc;
#[derive(Default, Copy, Clone)]
struct Vertex {
position: [f32; 2],
}
vulkano::impl_vertex!(Vertex, position);
mod vs {
vulkano_shaders::shader!{
ty: "vertex",
path: "examples/triangle.vert"
}
}
mod fs {
vulkano_shaders::shader!{
ty: "fragment",
path: "examples/triangle.frag"
}
}
fn main() {
let instance = {
let extensions = vulkano_win::required_extensions();
Instance::new(None, &extensions, None).expect("failed to create Vulkan instance")
};
let physical = PhysicalDevice::enumerate(&instance).next().expect("no device available");
for family in physical.queue_families() {
println!("Found a queue family with {:?} queue(s)", family.queues_count());
}
let queue_family = physical.queue_families()
.find(|&q| q.supports_graphics())
.expect("couldn't find a graphical queue family");
let (device, mut queues) = {
let device_ext = vulkano::device::DeviceExtensions {
khr_swapchain: true,
.. vulkano::device::DeviceExtensions::none()
};
Device::new(physical, physical.supported_features(), &device_ext,
[(queue_family, 0.5)].iter().cloned()).expect("failed to create device")
};
let queue = queues.next().unwrap();
// Set up surface and swapchain
let events_loop = EventLoop::new();
let surface = WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let caps = surface.capabilities(physical)
.expect("failed to get surface capabilities");
let dimensions = caps.current_extent.unwrap_or([1280, 1024]);
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let mut swapchain = Swapchain::new(device.clone(), surface.clone(),
caps.min_image_count, format, dimensions, 1, ImageUsage::color_attachment(), &queue,
SurfaceTransform::Identity, alpha, PresentMode::Fifo, FullscreenExclusive::Default,
true, ColorSpace::SrgbNonLinear)
.expect("failed to create swapchain");
// Get shaders
let vs = vs::Shader::load(device.clone()).expect("failed to create vertex shader module");
let fs = fs::Shader::load(device.clone()).expect("failed to create fragment shader module");
// Create vertex buffer
let vertex1 = Vertex { position: [-0.5, -0.5] };
let vertex2 = Vertex { position: [ 0.0, 0.5] };
let vertex3 = Vertex { position: [ 0.5, -0.25] };
let vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), false,
vec![vertex1, vertex2, vertex3].into_iter()).unwrap();
let render_pass = Arc::new(vulkano::single_pass_renderpass!(device.clone(),
attachments: {
color: {
load: Clear,
store: Store,
format: format,
samples: 1,
}
},
pass: {
color: [color],
depth_stencil: {}
}
).unwrap());
let dynamic_state = DynamicState {
viewports: Some(vec![Viewport {
origin: [0.0, 0.0],
dimensions: [1024.0, 1024.0],
depth_range: 0.0 .. 1.0,
}]),
.. DynamicState::none()
};
let pipeline = Arc::new(GraphicsPipeline::start()
// Defines what kind of vertex input is expected.
.vertex_input_single_buffer::<Vertex>()
// The vertex shader.
.vertex_shader(vs.main_entry_point(), ())
// Defines the viewport (explanations below).
.viewports_dynamic_scissors_irrelevant(1)
// The fragment shader.
.fragment_shader(fs.main_entry_point(), ())
// This graphics pipeline object concerns the first pass of the render pass.
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
// Now that everything is specified, we call `build`.
.build(device.clone())
.unwrap());
let mut staleSwapchain = false;
events_loop.run(move |event, _, control_flow| {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
*control_flow = ControlFlow::Exit;
},
_ => {
*control_flow = ControlFlow::Poll;
if staleSwapchain {
let size = surface.window().inner_size();
swapchain = swapchain.0.recreate_with_dimensions([size.width, size.height]).unwrap();
staleSwapchain = false;
}
let (image_num, _suboptimal, acquire_future)
= match swapchain::acquire_next_image(swapchain.0.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
staleSwapchain = true;
return ();
}
Err(err) => panic!("{:?}", err)
};
let framebuffer = Arc::new(Framebuffer::start(render_pass.clone())
.add(swapchain.1[image_num].clone()).unwrap()
.build().unwrap());
let mut builder = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap();
builder
.begin_render_pass(framebuffer.clone(), false, vec![[0.0, 0.0, 1.0, 1.0].into()])
.unwrap()
.draw(pipeline.clone(), &dynamic_state, vertex_buffer.clone(), (), ())
.unwrap()
.end_render_pass()
.unwrap();
let command_buffer = builder.build().unwrap();
acquire_future
.then_execute(queue.clone(), command_buffer).unwrap()
.then_swapchain_present(queue.clone(), swapchain.0.clone(), image_num)
.then_signal_fence_and_flush().unwrap().wait(None).unwrap();
}
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment