librashader/librashader-runtime-vk/src/hello_triangle/mod.rs

438 lines
16 KiB
Rust
Raw Normal View History

2023-01-10 14:54:54 +11:00
mod command;
mod debug;
2023-01-10 14:54:54 +11:00
mod framebuffer;
mod physicaldevice;
2023-01-10 14:54:54 +11:00
mod pipeline;
mod surface;
2023-01-04 16:49:42 +11:00
mod swapchain;
2023-01-10 11:17:13 +11:00
mod syncobjects;
2023-01-10 14:54:54 +11:00
pub mod vulkan_base;
2023-01-16 04:17:27 +11:00
use crate::filter_chain::FilterChainVulkan;
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;
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;
use crate::hello_triangle::vulkan_base::VulkanBase;
2023-01-13 13:29:42 +11:00
use crate::texture::VulkanImage;
use crate::util;
2023-01-10 14:54:54 +11:00
use ash::vk;
2023-01-16 03:08:13 +11:00
2023-01-15 19:06:09 +11:00
use librashader_common::Viewport;
2023-01-16 03:08:13 +11:00
2023-01-10 14:54:54 +11:00
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
use winit::platform::windows::EventLoopBuilderExtWindows;
// Constants
2023-01-16 03:08:13 +11:00
const WINDOW_TITLE: &str = "librashader Vulkan";
const WINDOW_WIDTH: u32 = 800;
const WINDOW_HEIGHT: u32 = 600;
2023-01-13 14:10:25 +11:00
const MAX_FRAMES_IN_FLIGHT: usize = 3;
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)
.build(event_loop)
.expect("Failed to create window.")
}
2023-01-10 14:54:54 +11:00
pub fn main_loop(
event_loop: EventLoop<()>,
window: winit::window::Window,
vulkan: VulkanDraw,
mut filter_chain: FilterChainVulkan,
2023-01-10 14:54:54 +11:00
) {
2023-01-13 13:11:44 +11:00
let mut counter = 0;
2023-01-13 13:29:42 +11:00
event_loop.run(move |event, _, control_flow| match event {
2023-01-10 14:54:54 +11:00
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 14:54:54 +11:00
}
_ => {}
},
2023-01-10 11:17:13 +11:00
},
2023-01-10 14:54:54 +11:00
_ => {}
},
Event::MainEventsCleared => {
window.request_redraw();
}
2023-01-10 14:54:54 +11:00
Event::RedrawRequested(_window_id) => {
2023-01-13 13:11:44 +11:00
VulkanWindow::draw_frame(counter, &vulkan, &mut filter_chain);
counter += 1;
2023-01-10 14:54:54 +11:00
}
_ => (),
})
}
2023-01-10 11:17:13 +11:00
2023-01-10 14:54:54 +11:00
unsafe fn record_command_buffer(
vulkan: &VulkanDraw,
framebuffer: vk::Framebuffer,
cmd: vk::CommandBuffer,
) {
let clear_values = [vk::ClearValue {
color: vk::ClearColorValue {
float32: [0.3, 0.3, 0.5, 0.0],
2023-01-10 11:17:13 +11:00
},
2023-01-10 14:54:54 +11:00
}];
2023-01-10 11:17:13 +11:00
let render_pass_begin = vk::RenderPassBeginInfo::builder()
.render_pass(vulkan.pipeline.renderpass)
.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();
2023-01-10 14:54:54 +11:00
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 {
2023-01-10 11:17:13 +11:00
max_depth: 1.0,
width: vulkan.swapchain.extent.width as f32,
height: vulkan.swapchain.extent.height as f32,
..Default::default()
2023-01-10 14:54:54 +11:00
}],
);
2023-01-10 11:17:13 +11:00
2023-01-10 14:54:54 +11:00
vulkan.base.device.cmd_set_scissor(
cmd,
0,
&[vk::Rect2D {
2023-01-10 11:17:13 +11:00
offset: Default::default(),
2023-01-10 14:54:54 +11:00
extent: vulkan.swapchain.extent,
}],
);
2023-01-10 11:17:13 +11:00
vulkan.base.device.cmd_draw(cmd, 3, 1, 0, 0);
vulkan.base.device.cmd_end_render_pass(cmd);
}
fn draw_frame(frame: usize, vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) {
2023-01-13 14:10:25 +11:00
let index = frame % MAX_FRAMES_IN_FLIGHT;
let in_flight = [vulkan.sync.in_flight[index]];
let image_available = [vulkan.sync.image_available[index]];
let render_finished = [vulkan.sync.render_finished[index]];
2023-01-13 14:10:25 +11:00
2023-01-10 11:17:13 +11:00
unsafe {
2023-01-10 14:54:54 +11:00
vulkan
.base
.device
.wait_for_fences(&in_flight, true, u64::MAX)
2023-01-10 11:17:13 +11:00
.unwrap();
2023-01-13 17:48:04 +11:00
vulkan.base.device.reset_fences(&in_flight).unwrap();
2023-01-10 11:17:13 +11:00
2023-01-10 14:54:54 +11:00
let (swapchain_index, _) = vulkan
.swapchain
.loader
.acquire_next_image(
vulkan.swapchain.swapchain,
u64::MAX,
image_available[0],
2023-01-10 14:54:54 +11:00
vk::Fence::null(),
)
2023-01-10 11:17:13 +11:00
.unwrap();
2023-01-13 14:10:25 +11:00
let cmd = vulkan.render_command_pool.buffers[index];
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];
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");
util::vulkan_image_layout_transition_levels(
&vulkan.base.device,
cmd,
framebuffer_image,
1,
vk::ImageLayout::UNDEFINED,
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
vk::AccessFlags::MEMORY_READ
| vk::AccessFlags::MEMORY_WRITE | vk::AccessFlags::HOST_READ | vk::AccessFlags::HOST_WRITE
| vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::SHADER_READ,
vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::COLOR_ATTACHMENT_READ,
vk::PipelineStageFlags::ALL_COMMANDS,
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED
);
Self::record_command_buffer(vulkan, framebuffer, cmd);
util::vulkan_image_layout_transition_levels(
&vulkan.base.device,
cmd,
framebuffer_image,
1,
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
vk::AccessFlags::MEMORY_READ
| vk::AccessFlags::MEMORY_WRITE | vk::AccessFlags::HOST_READ | vk::AccessFlags::HOST_WRITE
| vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE | vk::AccessFlags::SHADER_READ,
vk::AccessFlags::SHADER_READ,
vk::PipelineStageFlags::ALL_COMMANDS,
vk::PipelineStageFlags::FRAGMENT_SHADER,
vk::QUEUE_FAMILY_IGNORED,
vk::QUEUE_FAMILY_IGNORED
);
//
// util::vulkan_image_layout_transition_levels(
// &vulkan.base.device,
// cmd,
// framebuffer_image,
// 1,
// vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
// vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
// vk::AccessFlags::empty(),
// vk::AccessFlags::SHADER_READ,
// vk::PipelineStageFlags::ALL_GRAPHICS,
// vk::PipelineStageFlags::VERTEX_SHADER,
// vk::QUEUE_FAMILY_IGNORED,
// vk::QUEUE_FAMILY_IGNORED
// );
2023-01-15 19:06:09 +11:00
filter
2023-01-13 13:29:42 +11:00
.frame(
2023-01-14 09:59:22 +11:00
&VulkanImage {
size: vulkan.swapchain.extent.into(),
image: framebuffer_image,
format: vulkan.swapchain.format.format,
},
2023-01-13 13:29:42 +11:00
&Viewport {
x: 0.0,
y: 0.0,
output: VulkanImage {
size: vulkan.swapchain.extent.into(),
image: swapchain_image,
format: vulkan.swapchain.format.format,
},
mvp: None,
},
cmd,
2023-01-14 09:59:22 +11:00
frame,
2023-01-13 13:29:42 +11:00
None,
)
.unwrap();
2023-01-12 09:28:09 +11:00
// eprintln!("{:x}", framebuffer_image.as_raw());
// // todo: output image will remove need for ImageLayout::GENERAL
// // todo: make `frame` render into swapchain image rather than blit.
// util::vulkan_image_layout_transition_levels(
// &vulkan.base.device,
// cmd,
// framebuffer_image,
// 1,
// vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
// vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
// vk::AccessFlags::SHADER_READ,
// vk::AccessFlags::TRANSFER_READ,
// vk::PipelineStageFlags::VERTEX_SHADER,
// 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,
// );
2023-01-10 14:54:54 +11:00
util::vulkan_image_layout_transition_levels(
&vulkan.base.device,
cmd,
swapchain_image,
1,
2023-01-12 09:28:09 +11:00
vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
2023-01-10 14:54:54 +11:00
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,
);
2023-01-10 14:54:54 +11:00
vulkan
.base
.device
.end_command_buffer(cmd)
.expect("failed to record commandbuffer");
2023-01-10 11:17:13 +11:00
let stage_mask = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
let cmd = [cmd];
let submit_info = [vk::SubmitInfo::builder()
.wait_dst_stage_mask(&stage_mask)
.wait_semaphores(&image_available)
.signal_semaphores(&render_finished)
.command_buffers(&cmd)
.build()];
2023-01-10 11:17:13 +11:00
2023-01-10 14:54:54 +11:00
vulkan
.base
.device
2023-01-13 17:48:04 +11:00
.queue_submit(vulkan.base.graphics_queue, &submit_info, in_flight[0])
2023-01-10 11:17:13 +11:00
.expect("failed to submit queue");
let swapchain_index = [swapchain_index];
let swapchain = [vulkan.swapchain.swapchain];
2023-01-10 11:17:13 +11:00
let present_info = vk::PresentInfoKHR::builder()
.wait_semaphores(&render_finished)
.swapchains(&swapchain)
.image_indices(&swapchain_index)
2023-01-10 11:17:13 +11:00
.build();
2023-01-10 14:54:54 +11:00
vulkan
.swapchain
.loader
.queue_present(vulkan.base.graphics_queue, &present_info)
2023-01-10 11:17:13 +11:00
.unwrap();
// vulkan.base.device.device_wait_idle().unwrap();
// intermediates.dispose();
2023-01-10 11:17:13 +11:00
}
}
}
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 _)
}
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,
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,
}
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);
2023-01-10 14:54:54 +11:00
let surface = VulkanSurface::new(&vulkan, &window).unwrap();
2023-01-10 14:54:54 +11:00
let swapchain = VulkanSwapchain::new(&vulkan, &surface, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap();
2023-01-04 16:49:42 +11:00
2023-01-10 14:54:54 +11:00
let pipeline = unsafe { VulkanPipeline::new(&vulkan, &swapchain) }.unwrap();
2023-01-10 11:17:13 +11:00
let mut render_framebuffers = vec![];
2023-01-16 03:08:13 +11:00
for (_index, image) in swapchain.render_image_views.iter().enumerate() {
2023-01-10 14:54:54 +11:00
render_framebuffers.push(
VulkanFramebuffer::new(
&vulkan.device,
image,
&pipeline.renderpass,
WINDOW_WIDTH,
WINDOW_HEIGHT,
)
.unwrap(),
)
}
2023-01-13 17:48:04 +11:00
let swapchain_command_pool =
VulkanCommandPool::new(&vulkan, MAX_FRAMES_IN_FLIGHT as u32).unwrap();
2023-01-13 14:10:25 +11:00
let render_command_pool = VulkanCommandPool::new(&vulkan, MAX_FRAMES_IN_FLIGHT as u32).unwrap();
2023-01-10 11:17:13 +11:00
2023-01-13 14:10:25 +11:00
let sync = SyncObjects::new(&vulkan.device, MAX_FRAMES_IN_FLIGHT).unwrap();
2023-01-10 11:17:13 +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,
swapchain_command_pool,
sync,
render_command_pool,
render_framebuffers,
};
2023-01-10 11:17:13 +11:00
VulkanWindow::main_loop(event_loop, window, vulkan, filter_chain);
2023-01-10 14:54:54 +11:00
}