2023-01-03 16:55:35 +11:00
|
|
|
pub mod vulkan_base;
|
|
|
|
mod debug;
|
|
|
|
mod physicaldevice;
|
|
|
|
mod surface;
|
2023-01-04 16:49:42 +11:00
|
|
|
mod swapchain;
|
2023-01-10 11:17:13 +11:00
|
|
|
mod pipeline;
|
|
|
|
mod framebuffer;
|
|
|
|
mod command;
|
|
|
|
mod syncobjects;
|
2023-01-03 16:55:35 +11:00
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
use ash::vk;
|
2023-01-10 14:53:28 +11:00
|
|
|
use ash::vk::RenderingInfo;
|
2023-01-03 16:55:35 +11:00
|
|
|
use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent};
|
|
|
|
use winit::event_loop::{EventLoop, ControlFlow, EventLoopBuilder};
|
|
|
|
use winit::platform::windows::EventLoopBuilderExtWindows;
|
2023-01-04 16:49:42 +11:00
|
|
|
use crate::filter_chain::{FilterChainVulkan, Vulkan};
|
2023-01-10 11:17:13 +11:00
|
|
|
use crate::hello_triangle::command::VulkanCommandPool;
|
|
|
|
use crate::hello_triangle::framebuffer::VulkanFramebuffer;
|
|
|
|
use crate::hello_triangle::pipeline::VulkanPipeline;
|
2023-01-03 16:55:35 +11:00
|
|
|
use crate::hello_triangle::surface::VulkanSurface;
|
2023-01-04 16:49:42 +11:00
|
|
|
use crate::hello_triangle::swapchain::VulkanSwapchain;
|
2023-01-10 11:17:13 +11:00
|
|
|
use crate::hello_triangle::syncobjects::SyncObjects;
|
2023-01-03 16:55:35 +11:00
|
|
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
2023-01-10 14:53:28 +11:00
|
|
|
use crate::util;
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
// Constants
|
|
|
|
const WINDOW_TITLE: &'static str = "librashader Vulkan";
|
|
|
|
const WINDOW_WIDTH: u32 = 800;
|
|
|
|
const WINDOW_HEIGHT: u32 = 600;
|
|
|
|
|
|
|
|
struct VulkanWindow;
|
|
|
|
|
|
|
|
impl VulkanWindow {
|
|
|
|
fn init_window(event_loop: &EventLoop<()>) -> winit::window::Window {
|
|
|
|
winit::window::WindowBuilder::new()
|
|
|
|
.with_title(WINDOW_TITLE)
|
|
|
|
.with_inner_size(winit::dpi::LogicalSize::new(WINDOW_WIDTH, WINDOW_HEIGHT))
|
2023-01-10 11:17:13 +11:00
|
|
|
.with_resizable(false)
|
2023-01-03 16:55:35 +11:00
|
|
|
.build(event_loop)
|
|
|
|
.expect("Failed to create window.")
|
|
|
|
}
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
pub fn main_loop(event_loop: EventLoop<()>, window: winit::window::Window, vulkan: VulkanDraw, mut filter_chain: FilterChainVulkan) {
|
2023-01-03 16:55:35 +11:00
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
|
|
match event {
|
|
|
|
| Event::WindowEvent { event, .. } => {
|
|
|
|
match event {
|
|
|
|
| WindowEvent::CloseRequested => {
|
|
|
|
*control_flow = ControlFlow::Exit
|
|
|
|
},
|
|
|
|
| WindowEvent::KeyboardInput { input, .. } => {
|
|
|
|
match input {
|
|
|
|
| KeyboardInput { virtual_keycode, state, .. } => {
|
|
|
|
match (virtual_keycode, state) {
|
|
|
|
| (Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
|
|
|
*control_flow = ControlFlow::Exit
|
|
|
|
},
|
|
|
|
| _ => {},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
| _ => {},
|
|
|
|
}
|
|
|
|
},
|
2023-01-10 11:17:13 +11:00
|
|
|
| Event::MainEventsCleared => {
|
|
|
|
window.request_redraw();
|
|
|
|
},
|
|
|
|
| Event::RedrawRequested(_window_id) => {
|
|
|
|
VulkanWindow::draw_frame(&vulkan, &mut filter_chain);
|
|
|
|
},
|
2023-01-03 16:55:35 +11:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
2023-01-10 11:17:13 +11:00
|
|
|
|
2023-01-10 14:53:28 +11:00
|
|
|
unsafe fn record_command_buffer(vulkan: &VulkanDraw, framebuffer: vk::Framebuffer, cmd: vk::CommandBuffer) {
|
2023-01-10 11:17:13 +11:00
|
|
|
let clear_values = [
|
|
|
|
vk::ClearValue {
|
|
|
|
color: vk::ClearColorValue {
|
|
|
|
float32: [0.3, 0.3, 0.5, 0.0],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
let render_pass_begin = vk::RenderPassBeginInfo::builder()
|
|
|
|
.render_pass(vulkan.pipeline.renderpass)
|
2023-01-10 14:53:28 +11:00
|
|
|
.framebuffer(framebuffer)
|
2023-01-10 11:17:13 +11:00
|
|
|
.render_area(vk::Rect2D {
|
|
|
|
extent: vulkan.swapchain.extent,
|
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.clear_values(&clear_values)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
vulkan.base.device.reset_command_buffer(cmd, vk::CommandBufferResetFlags::empty())
|
|
|
|
.expect("could not reset command buffer");
|
|
|
|
|
|
|
|
vulkan.base.device.begin_command_buffer(cmd, &vk::CommandBufferBeginInfo::default())
|
|
|
|
.expect("failed to begin command buffer");
|
|
|
|
|
|
|
|
vulkan.base.device
|
|
|
|
.cmd_begin_render_pass(cmd,
|
|
|
|
&render_pass_begin, vk::SubpassContents::INLINE);
|
|
|
|
|
|
|
|
vulkan.base.device
|
|
|
|
.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, vulkan.pipeline.graphic_pipeline);
|
|
|
|
|
|
|
|
vulkan.base.device
|
|
|
|
.cmd_set_viewport(cmd, 0, &[vk::Viewport {
|
|
|
|
max_depth: 1.0,
|
|
|
|
width: vulkan.swapchain.extent.width as f32,
|
|
|
|
height: vulkan.swapchain.extent.height as f32,
|
|
|
|
..Default::default()
|
|
|
|
}]);
|
|
|
|
|
|
|
|
vulkan.base.device
|
|
|
|
.cmd_set_scissor(cmd, 0, &[vk::Rect2D {
|
|
|
|
offset: Default::default(),
|
|
|
|
extent: vulkan.swapchain.extent
|
|
|
|
}]);
|
|
|
|
|
|
|
|
vulkan.base.device.cmd_draw(cmd, 3, 1, 0, 0);
|
|
|
|
vulkan.base.device.cmd_end_render_pass(cmd);
|
|
|
|
|
|
|
|
|
2023-01-10 14:53:28 +11:00
|
|
|
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
fn draw_frame(vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) {
|
|
|
|
unsafe {
|
|
|
|
vulkan.base.device.wait_for_fences(&[vulkan.sync.in_flight], true, u64::MAX)
|
|
|
|
.unwrap();
|
|
|
|
vulkan.base.device.reset_fences(&[vulkan.sync.in_flight])
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let (swapchain_index, _) = vulkan.swapchain.loader.acquire_next_image(vulkan.swapchain.swapchain, u64::MAX, vulkan.sync.image_available, vk::Fence::null())
|
|
|
|
.unwrap();
|
|
|
|
|
2023-01-10 14:53:28 +11:00
|
|
|
let cmd = vulkan.render_command_pool.buffers[swapchain_index as usize];
|
|
|
|
let framebuffer = vulkan.render_framebuffers[swapchain_index as usize].framebuffer;
|
|
|
|
let framebuffer_image = vulkan.swapchain.render_images[swapchain_index as usize].0;
|
|
|
|
let swapchain_image = vulkan.swapchain.swapchain_images[swapchain_index as usize];
|
|
|
|
|
|
|
|
Self::record_command_buffer(vulkan, framebuffer, cmd);
|
|
|
|
|
|
|
|
util::vulkan_image_layout_transition_levels(&vulkan.base.device,
|
|
|
|
cmd,
|
|
|
|
framebuffer_image,
|
|
|
|
1,
|
|
|
|
vk::ImageLayout::UNDEFINED,
|
|
|
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
|
|
|
vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
|
|
|
|
vk::AccessFlags::TRANSFER_READ,
|
|
|
|
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
|
|
|
|
vk::PipelineStageFlags::TRANSFER,
|
|
|
|
vk::QUEUE_FAMILY_IGNORED,
|
|
|
|
vk::QUEUE_FAMILY_IGNORED
|
|
|
|
);
|
|
|
|
|
|
|
|
let blit_subresource =vk::ImageSubresourceLayers::builder()
|
|
|
|
.layer_count(1)
|
|
|
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let src_offsets = [
|
|
|
|
vk::Offset3D { x: 0, y: 0, z: 0 },
|
|
|
|
vk::Offset3D {
|
|
|
|
x: vulkan.swapchain.extent.width as i32,
|
|
|
|
y: vulkan.swapchain.extent.height as i32,
|
|
|
|
z: 1,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
let dst_offsets = [
|
|
|
|
vk::Offset3D { x: 0, y: 0, z: 0 },
|
|
|
|
vk::Offset3D {
|
|
|
|
x: vulkan.swapchain.extent.width as i32,
|
|
|
|
y: vulkan.swapchain.extent.height as i32,
|
|
|
|
z: 1,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
vulkan.base.device.cmd_blit_image(cmd, framebuffer_image, vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
|
|
|
swapchain_image,
|
|
|
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
|
|
|
&[vk::ImageBlit {
|
|
|
|
src_subresource: blit_subresource,
|
|
|
|
src_offsets,
|
|
|
|
dst_subresource: blit_subresource,
|
|
|
|
dst_offsets,
|
|
|
|
}],
|
|
|
|
vk::Filter::LINEAR
|
|
|
|
);
|
|
|
|
|
|
|
|
util::vulkan_image_layout_transition_levels(&vulkan.base.device,
|
|
|
|
cmd,
|
|
|
|
swapchain_image,
|
|
|
|
1,
|
|
|
|
vk::ImageLayout::UNDEFINED,
|
|
|
|
vk::ImageLayout::PRESENT_SRC_KHR,
|
|
|
|
vk::AccessFlags::empty(),
|
|
|
|
vk::AccessFlags::TRANSFER_READ,
|
|
|
|
vk::PipelineStageFlags::TRANSFER,
|
|
|
|
vk::PipelineStageFlags::TRANSFER,
|
|
|
|
vk::QUEUE_FAMILY_IGNORED,
|
|
|
|
vk::QUEUE_FAMILY_IGNORED
|
|
|
|
);
|
|
|
|
|
|
|
|
vulkan.base.device.end_command_buffer(cmd).expect("failed to record commandbuffer");
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
|
|
|
|
let submit_info = vk::SubmitInfo::builder()
|
|
|
|
.wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT])
|
|
|
|
.wait_semaphores(&[vulkan.sync.image_available])
|
|
|
|
.signal_semaphores(&[vulkan.sync.render_finished])
|
|
|
|
.command_buffers(&[cmd])
|
|
|
|
.build();
|
|
|
|
|
|
|
|
vulkan.base.device.queue_submit(vulkan.base.graphics_queue, &[submit_info], vulkan.sync.in_flight)
|
|
|
|
.expect("failed to submit queue");
|
|
|
|
|
|
|
|
let present_info = vk::PresentInfoKHR::builder()
|
|
|
|
.wait_semaphores(&[vulkan.sync.render_finished])
|
|
|
|
.swapchains(&[vulkan.swapchain.swapchain])
|
|
|
|
.image_indices(&[swapchain_index])
|
|
|
|
.build();
|
|
|
|
|
|
|
|
vulkan.swapchain.loader.queue_present(vulkan.base.graphics_queue, &present_info)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn find_memorytype_index(
|
|
|
|
memory_req: &vk::MemoryRequirements,
|
|
|
|
memory_prop: &vk::PhysicalDeviceMemoryProperties,
|
|
|
|
flags: vk::MemoryPropertyFlags,
|
|
|
|
) -> Option<u32> {
|
|
|
|
memory_prop.memory_types[..memory_prop.memory_type_count as _]
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find(|(index, memory_type)| {
|
|
|
|
(1 << index) & memory_req.memory_type_bits != 0
|
|
|
|
&& memory_type.property_flags & flags == flags
|
|
|
|
})
|
|
|
|
.map(|(index, _memory_type)| index as _)
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
|
2023-01-03 16:55:35 +11:00
|
|
|
pub struct VulkanDraw {
|
|
|
|
surface: VulkanSurface,
|
|
|
|
base: VulkanBase,
|
2023-01-04 16:49:42 +11:00
|
|
|
pub swapchain: VulkanSwapchain,
|
2023-01-10 11:17:13 +11:00
|
|
|
pub pipeline: VulkanPipeline,
|
2023-01-10 14:53:28 +11:00
|
|
|
pub swapchain_framebuffers: Vec<VulkanFramebuffer>,
|
|
|
|
pub swapchain_command_pool: VulkanCommandPool,
|
|
|
|
pub render_command_pool: VulkanCommandPool,
|
|
|
|
pub render_framebuffers: Vec<VulkanFramebuffer>,
|
2023-01-10 11:17:13 +11:00
|
|
|
pub sync: SyncObjects,
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) {
|
|
|
|
let event_loop = EventLoopBuilder::new()
|
|
|
|
.with_any_thread(true)
|
|
|
|
.with_dpi_aware(true)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let window = VulkanWindow::init_window(&event_loop);
|
|
|
|
let surface = VulkanSurface::new(&vulkan, &window)
|
|
|
|
.unwrap();
|
|
|
|
|
2023-01-04 16:49:42 +11:00
|
|
|
let swapchain = VulkanSwapchain::new(&vulkan, &surface, WINDOW_WIDTH, WINDOW_HEIGHT)
|
|
|
|
.unwrap();
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
let pipeline = unsafe { VulkanPipeline::new(&vulkan, &swapchain) }
|
|
|
|
.unwrap();
|
|
|
|
|
2023-01-10 14:53:28 +11:00
|
|
|
let mut swapchain_framebuffers = vec![];
|
|
|
|
for image in &swapchain.swapchain_image_views {
|
|
|
|
swapchain_framebuffers.push(VulkanFramebuffer::new(&vulkan.device, image, &pipeline.renderpass, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap())
|
2023-01-10 11:17:13 +11:00
|
|
|
}
|
|
|
|
|
2023-01-10 14:53:28 +11:00
|
|
|
let mut render_framebuffers = vec![];
|
|
|
|
for image in &swapchain.render_image_views {
|
|
|
|
render_framebuffers.push(VulkanFramebuffer::new(&vulkan.device, image, &pipeline.renderpass, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
let swapchain_command_pool = VulkanCommandPool::new(&vulkan, 3)
|
|
|
|
.unwrap();
|
|
|
|
let render_command_pool = VulkanCommandPool::new(&vulkan, 3)
|
2023-01-10 11:17:13 +11:00
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let sync = SyncObjects::new(&vulkan.device)
|
|
|
|
.unwrap();
|
|
|
|
|
2023-01-03 16:55:35 +11:00
|
|
|
let vulkan = VulkanDraw {
|
|
|
|
surface,
|
2023-01-04 16:49:42 +11:00
|
|
|
swapchain,
|
2023-01-10 11:17:13 +11:00
|
|
|
base: vulkan,
|
|
|
|
pipeline,
|
2023-01-10 14:53:28 +11:00
|
|
|
swapchain_framebuffers,
|
|
|
|
swapchain_command_pool,
|
|
|
|
sync,
|
|
|
|
render_command_pool,
|
|
|
|
render_framebuffers,
|
2023-01-03 16:55:35 +11:00
|
|
|
};
|
|
|
|
|
2023-01-10 11:17:13 +11:00
|
|
|
VulkanWindow::main_loop(event_loop, window, vulkan, filter_chain);
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|