parent
8801d9268d
commit
7f32c3a64f
@ -0,0 +1,131 @@
|
|||||||
|
let SessionLoad = 1
|
||||||
|
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
|
||||||
|
let v:this_session=expand("<sfile>:p")
|
||||||
|
silent only
|
||||||
|
silent tabonly
|
||||||
|
cd ~/bin/rs/tri
|
||||||
|
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
|
||||||
|
let s:wipebuf = bufnr('%')
|
||||||
|
endif
|
||||||
|
let s:shortmess_save = &shortmess
|
||||||
|
if &shortmess =~ 'A'
|
||||||
|
set shortmess=aoOA
|
||||||
|
else
|
||||||
|
set shortmess=aoO
|
||||||
|
endif
|
||||||
|
badd +1 ~/bin/rs/tri
|
||||||
|
badd +1 src/render.rs
|
||||||
|
badd +0 src/utility/share.rs
|
||||||
|
argglobal
|
||||||
|
%argdel
|
||||||
|
$argadd ~/bin/rs/tri
|
||||||
|
edit src/render.rs
|
||||||
|
let s:save_splitbelow = &splitbelow
|
||||||
|
let s:save_splitright = &splitright
|
||||||
|
set splitbelow splitright
|
||||||
|
wincmd _ | wincmd |
|
||||||
|
vsplit
|
||||||
|
wincmd _ | wincmd |
|
||||||
|
vsplit
|
||||||
|
2wincmd h
|
||||||
|
wincmd w
|
||||||
|
wincmd w
|
||||||
|
let &splitbelow = s:save_splitbelow
|
||||||
|
let &splitright = s:save_splitright
|
||||||
|
wincmd t
|
||||||
|
let s:save_winminheight = &winminheight
|
||||||
|
let s:save_winminwidth = &winminwidth
|
||||||
|
set winminheight=0
|
||||||
|
set winheight=1
|
||||||
|
set winminwidth=0
|
||||||
|
set winwidth=1
|
||||||
|
exe 'vert 1resize ' . ((&columns * 71 + 107) / 214)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 71 + 107) / 214)
|
||||||
|
exe 'vert 3resize ' . ((&columns * 70 + 107) / 214)
|
||||||
|
argglobal
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
silent! normal! zE
|
||||||
|
let &fdl = &fdl
|
||||||
|
let s:l = 61 - ((45 * winheight(0) + 40) / 81)
|
||||||
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
|
keepjumps exe s:l
|
||||||
|
normal! zt
|
||||||
|
keepjumps 61
|
||||||
|
normal! 0
|
||||||
|
lcd ~/bin/rs/tri
|
||||||
|
wincmd w
|
||||||
|
argglobal
|
||||||
|
if bufexists(fnamemodify("~/bin/rs/tri/src/utility/share.rs", ":p")) | buffer ~/bin/rs/tri/src/utility/share.rs | else | edit ~/bin/rs/tri/src/utility/share.rs | endif
|
||||||
|
if &buftype ==# 'terminal'
|
||||||
|
silent file ~/bin/rs/tri/src/utility/share.rs
|
||||||
|
endif
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
silent! normal! zE
|
||||||
|
let &fdl = &fdl
|
||||||
|
let s:l = 190 - ((53 * winheight(0) + 40) / 81)
|
||||||
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
|
keepjumps exe s:l
|
||||||
|
normal! zt
|
||||||
|
keepjumps 190
|
||||||
|
normal! 013|
|
||||||
|
lcd ~/bin/rs/tri
|
||||||
|
wincmd w
|
||||||
|
argglobal
|
||||||
|
if bufexists(fnamemodify("~/bin/rs/tri/src/utility/share.rs", ":p")) | buffer ~/bin/rs/tri/src/utility/share.rs | else | edit ~/bin/rs/tri/src/utility/share.rs | endif
|
||||||
|
if &buftype ==# 'terminal'
|
||||||
|
silent file ~/bin/rs/tri/src/utility/share.rs
|
||||||
|
endif
|
||||||
|
setlocal fdm=manual
|
||||||
|
setlocal fde=0
|
||||||
|
setlocal fmr={{{,}}}
|
||||||
|
setlocal fdi=#
|
||||||
|
setlocal fdl=0
|
||||||
|
setlocal fml=1
|
||||||
|
setlocal fdn=20
|
||||||
|
setlocal fen
|
||||||
|
silent! normal! zE
|
||||||
|
let &fdl = &fdl
|
||||||
|
let s:l = 1651 - ((36 * winheight(0) + 40) / 81)
|
||||||
|
if s:l < 1 | let s:l = 1 | endif
|
||||||
|
keepjumps exe s:l
|
||||||
|
normal! zt
|
||||||
|
keepjumps 1651
|
||||||
|
normal! 016|
|
||||||
|
lcd ~/bin/rs/tri
|
||||||
|
wincmd w
|
||||||
|
3wincmd w
|
||||||
|
exe 'vert 1resize ' . ((&columns * 71 + 107) / 214)
|
||||||
|
exe 'vert 2resize ' . ((&columns * 71 + 107) / 214)
|
||||||
|
exe 'vert 3resize ' . ((&columns * 70 + 107) / 214)
|
||||||
|
tabnext 1
|
||||||
|
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
|
||||||
|
silent exe 'bwipe ' . s:wipebuf
|
||||||
|
endif
|
||||||
|
unlet! s:wipebuf
|
||||||
|
set winheight=1 winwidth=20
|
||||||
|
let &shortmess = s:shortmess_save
|
||||||
|
let &winminheight = s:save_winminheight
|
||||||
|
let &winminwidth = s:save_winminwidth
|
||||||
|
let s:sx = expand("<sfile>:p:r")."x.vim"
|
||||||
|
if filereadable(s:sx)
|
||||||
|
exe "source " . fnameescape(s:sx)
|
||||||
|
endif
|
||||||
|
let &g:so = s:so_save | let &g:siso = s:siso_save
|
||||||
|
set hlsearch
|
||||||
|
doautoall SessionLoadPost
|
||||||
|
unlet SessionLoad
|
||||||
|
" vim: set ft=vim :
|
@ -0,0 +1,602 @@
|
|||||||
|
diff --git a/src/render.rs b/src/render.rs
|
||||||
|
index c8f2dc6..b094570 100644
|
||||||
|
--- a/src/render.rs
|
||||||
|
+++ b/src/render.rs
|
||||||
|
@@ -14,6 +14,22 @@ use std::ptr;
|
||||||
|
// Constants
|
||||||
|
const WINDOW_TITLE: &'static str = "Template";
|
||||||
|
|
||||||
|
+const IS_PAINT_FPS_COUNTER: bool = true;
|
||||||
|
+
|
||||||
|
+pub fn init_window(
|
||||||
|
+ event_loop: &EventLoop<()>,
|
||||||
|
+ title: &str,
|
||||||
|
+ width: u32,
|
||||||
|
+ height: u32,
|
||||||
|
+) -> winit::window::Window {
|
||||||
|
+ winit::window::WindowBuilder::new()
|
||||||
|
+ .with_title(title)
|
||||||
|
+ .with_inner_size(winit::dpi::LogicalSize::new(width, height))
|
||||||
|
+ .build(event_loop)
|
||||||
|
+ .expect("Failed to create window.")
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
pub struct VulkanApp {
|
||||||
|
window: winit::window::Window,
|
||||||
|
|
||||||
|
@@ -31,7 +47,10 @@ pub struct VulkanApp {
|
||||||
|
queue_family: QueueFamilyIndices,
|
||||||
|
graphics_queue: vk::Queue,
|
||||||
|
present_queue: vk::Queue,
|
||||||
|
+ //new from C++
|
||||||
|
+ compute_queue: vk::Queue,
|
||||||
|
|
||||||
|
+ //not in C++
|
||||||
|
swapchain_loader: ash::extensions::khr::Swapchain,
|
||||||
|
swapchain: vk::SwapchainKHR,
|
||||||
|
swapchain_images: Vec<vk::Image>,
|
||||||
|
@@ -41,14 +60,31 @@ pub struct VulkanApp {
|
||||||
|
swapchain_framebuffers: Vec<vk::Framebuffer>,
|
||||||
|
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
- pipeline_layout: vk::PipelineLayout,
|
||||||
|
+
|
||||||
|
+ graphics_pipeline_layout: vk::PipelineLayout,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
+
|
||||||
|
+ //new from C++
|
||||||
|
+ compute_descriptor_set_layout: vk::DescriptorSetLayout,
|
||||||
|
+ compute_pipeline_layout: vk::PipelineLayout,
|
||||||
|
+ compute_pipeline: vk::Pipeline,
|
||||||
|
+
|
||||||
|
+ //vertex buffer for the triangle verticies
|
||||||
|
+ //i think this is the same as shaderStorageBuffers in C++ version
|
||||||
|
+ shader_storage_buffers: Vec<vk::Buffer>,
|
||||||
|
+ shader_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
+
|
||||||
|
+ uniform_buffers: Vec<vk::Buffer>,
|
||||||
|
+ uniform_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
+ uniform_buffers_mapped: Vec<*mut c_void>,
|
||||||
|
+
|
||||||
|
|
||||||
|
- vertex_buffer: vk::Buffer,
|
||||||
|
- vertex_buffer_memory: vk::DeviceMemory,
|
||||||
|
+ descriptor_pool: vk::DescriptorPool,
|
||||||
|
+ compute_descriptor_sets: Vec<vk::DescriptorSet>,
|
||||||
|
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
+ compute_command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
|
||||||
|
image_available_semaphores: Vec<vk::Semaphore>,
|
||||||
|
render_finished_semaphores: Vec<vk::Semaphore>,
|
||||||
|
@@ -59,9 +95,33 @@ pub struct VulkanApp {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanApp {
|
||||||
|
+ //C++ code::
|
||||||
|
+ /*
|
||||||
|
+ ### cleanup();
|
||||||
|
+ createInstance(); DONE
|
||||||
|
+ setupDebugMessenger(); DONE
|
||||||
|
+ createSurface(); SurfaceStuff::new DONE
|
||||||
|
+ pickPhysicalDevice(); DONE
|
||||||
|
+ createLogicalDevice();
|
||||||
|
+ createSwapChain();
|
||||||
|
+ createImageViews();
|
||||||
|
+ createRenderPass();
|
||||||
|
+ createComputeDescriptorSetLayout();
|
||||||
|
+ createGraphicsPipeline();
|
||||||
|
+ createComputePipeline();
|
||||||
|
+ createFramebuffers(); DONE
|
||||||
|
+ createCommandPool(); DONE
|
||||||
|
+ createShaderStorageBuffers(); DONE
|
||||||
|
+ createUniformBuffers(); DONE
|
||||||
|
+ createDescriptorPool(); DONE
|
||||||
|
+ createComputeDescriptorSets(); DONE
|
||||||
|
+ createCommandBuffers(); DONE
|
||||||
|
+ createComputeCommandBuffers(); DONE
|
||||||
|
+ createSyncObjects(); DONE
|
||||||
|
+ */
|
||||||
|
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> VulkanApp {
|
||||||
|
let window =
|
||||||
|
- utility::window::init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
+ init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
// init vulkan stuff
|
||||||
|
let entry = unsafe { Entry::load().unwrap() };
|
||||||
|
@@ -72,7 +132,7 @@ impl VulkanApp {
|
||||||
|
&VALIDATION.required_validation_layers.to_vec(),
|
||||||
|
);
|
||||||
|
let surface_stuff =
|
||||||
|
- share::create_surface(&entry, &instance, &window, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
+ SurfaceStuff::new(&entry, &instance, &window, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
let (debug_utils_loader, debug_merssager) =
|
||||||
|
setup_debug_utils(VALIDATION.is_enable, &entry, &instance);
|
||||||
|
let physical_device =
|
||||||
|
@@ -88,7 +148,9 @@ impl VulkanApp {
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
- let swapchain_stuff = share::create_swapchain(
|
||||||
|
+ let compute_queue =
|
||||||
|
+ unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
+ let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
@@ -102,11 +164,19 @@ impl VulkanApp {
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
- let (graphics_pipeline, pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
+ let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
+ &device,
|
||||||
|
+ render_pass,
|
||||||
|
+ swapchain_stuff.swapchain_extent,
|
||||||
|
+ );
|
||||||
|
+ let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
+
|
||||||
|
+ let compute_pipeline = compute_pipelines[0];
|
||||||
|
+
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
@@ -125,7 +195,7 @@ impl VulkanApp {
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
- let sync_ojbects = share::create_sync_objects(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
+ let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
||||||
|
VulkanApp {
|
||||||
|
@@ -146,6 +216,7 @@ impl VulkanApp {
|
||||||
|
queue_family,
|
||||||
|
graphics_queue,
|
||||||
|
present_queue,
|
||||||
|
+ compute_queue,
|
||||||
|
|
||||||
|
swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
swapchain: swapchain_stuff.swapchain,
|
||||||
|
@@ -155,10 +226,15 @@ impl VulkanApp {
|
||||||
|
swapchain_imageviews,
|
||||||
|
swapchain_framebuffers,
|
||||||
|
|
||||||
|
- pipeline_layout,
|
||||||
|
+ graphics_pipeline_layout,
|
||||||
|
render_pass,
|
||||||
|
graphics_pipeline,
|
||||||
|
|
||||||
|
+
|
||||||
|
+ compute_descriptor_sets,
|
||||||
|
+ compute_pipeline_layout,
|
||||||
|
+ compute_pipeline,
|
||||||
|
+
|
||||||
|
vertex_buffer,
|
||||||
|
vertex_buffer_memory,
|
||||||
|
|
||||||
|
@@ -174,6 +250,56 @@ impl VulkanApp {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ pub fn main_loop(self) {
|
||||||
|
+ let mut tick_counter = super::fps_limiter::FPSLimiter::new();
|
||||||
|
+
|
||||||
|
+ self.event_loop
|
||||||
|
+ .run(move |event, _, control_flow| match event {
|
||||||
|
+ Event::WindowEvent { event, .. } => match event {
|
||||||
|
+ WindowEvent::CloseRequested => {
|
||||||
|
+ vulkan_app.wait_device_idle();
|
||||||
|
+ *control_flow = ControlFlow::Exit
|
||||||
|
+ }
|
||||||
|
+ WindowEvent::KeyboardInput { input, .. } => match input {
|
||||||
|
+ KeyboardInput {
|
||||||
|
+ virtual_keycode,
|
||||||
|
+ state,
|
||||||
|
+ ..
|
||||||
|
+ } => match (virtual_keycode, state) {
|
||||||
|
+ (Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
||||||
|
+ vulkan_app.wait_device_idle();
|
||||||
|
+ *control_flow = ControlFlow::Exit
|
||||||
|
+ }
|
||||||
|
+ _ => {}
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
|
+ WindowEvent::Resized(_new_size) => {
|
||||||
|
+ vulkan_app.wait_device_idle();
|
||||||
|
+ vulkan_app.resize_framebuffer();
|
||||||
|
+ }
|
||||||
|
+ _ => {}
|
||||||
|
+ },
|
||||||
|
+ Event::MainEventsCleared => {
|
||||||
|
+ vulkan_app.window_ref().request_redraw();
|
||||||
|
+ }
|
||||||
|
+ Event::RedrawRequested(_window_id) => {
|
||||||
|
+ let delta_time = tick_counter.delta_time();
|
||||||
|
+ vulkan_app.draw_frame(delta_time);
|
||||||
|
+
|
||||||
|
+ if IS_PAINT_FPS_COUNTER {
|
||||||
|
+ print!("FPS: {}\r", tick_counter.fps());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ tick_counter.tick_frame();
|
||||||
|
+ }
|
||||||
|
+ Event::LoopDestroyed => {
|
||||||
|
+ vulkan_app.wait_device_idle();
|
||||||
|
+ }
|
||||||
|
+ _ => (),
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
fn create_vertex_buffer(
|
||||||
|
instance: &ash::Instance,
|
||||||
|
device: &ash::Device,
|
||||||
|
@@ -263,10 +389,111 @@ impl VulkanApp {
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Failed to find suitable memory type!")
|
||||||
|
+ share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
}
|
||||||
|
+ /*
|
||||||
|
+ * IDEK WHERE THIS CAME FROM I FUCKED UP THIS FILE, SHITS WHACK
|
||||||
|
+ * let (device, queue_family) = share::create_logical_device(
|
||||||
|
+ &instance,
|
||||||
|
+ physical_device,
|
||||||
|
+ &VALIDATION,
|
||||||
|
+ &DEVICE_EXTENSIONS,
|
||||||
|
+ &surface_stuff,
|
||||||
|
+ );
|
||||||
|
+ let graphics_queue =
|
||||||
|
+ unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
+ let present_queue =
|
||||||
|
+ unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
+ let compute_queue =
|
||||||
|
+ unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
+ let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
+ &instance,
|
||||||
|
+ &device,
|
||||||
|
+ physical_device,
|
||||||
|
+ &window,
|
||||||
|
+ &surface_stuff,
|
||||||
|
+ &queue_family,
|
||||||
|
+ );
|
||||||
|
+ let swapchain_imageviews = share::create_image_views(
|
||||||
|
+ &device,
|
||||||
|
+ swapchain_stuff.swapchain_format,
|
||||||
|
+ &swapchain_stuff.swapchain_images,
|
||||||
|
+ );
|
||||||
|
+ let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
+ let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
+ &device,
|
||||||
|
+ render_pass,
|
||||||
|
+ swapchain_stuff.swapchain_extent,
|
||||||
|
+ );
|
||||||
|
+ let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
+ &device,
|
||||||
|
+ render_pass,
|
||||||
|
+ swapchain_stuff.swapchain_extent,
|
||||||
|
+ );
|
||||||
|
|
||||||
|
- fn create_command_buffers(
|
||||||
|
- device: &ash::Device,
|
||||||
|
+ let compute_pipeline = compute_pipelines[0];
|
||||||
|
+
|
||||||
|
+ let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
+ &device,
|
||||||
|
+ render_pass,
|
||||||
|
+ &swapchain_imageviews,
|
||||||
|
+ swapchain_stuff.swapchain_extent,
|
||||||
|
+ );
|
||||||
|
+ let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
+ let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
+ VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
+ let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
+ &device,
|
||||||
|
+ command_pool,
|
||||||
|
+ graphics_pipeline,
|
||||||
|
+ &swapchain_framebuffers,
|
||||||
|
+ render_pass,
|
||||||
|
+ swapchain_stuff.swapchain_extent,
|
||||||
|
+ vertex_buffer,
|
||||||
|
+ );
|
||||||
|
+ let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
+
|
||||||
|
+ // cleanup(); the 'drop' function will take care of it.
|
||||||
|
+ VulkanApp {
|
||||||
|
+ // winit stuff
|
||||||
|
+ window,
|
||||||
|
+
|
||||||
|
+ // vulkan stuff
|
||||||
|
+ _entry: entry,
|
||||||
|
+ instance,
|
||||||
|
+ surface: surface_stuff.surface,
|
||||||
|
+ surface_loader: surface_stuff.surface_loader,
|
||||||
|
+ debug_utils_loader,
|
||||||
|
+ debug_merssager,
|
||||||
|
+
|
||||||
|
+ physical_device,
|
||||||
|
+ device,
|
||||||
|
+
|
||||||
|
+ queue_family,
|
||||||
|
+ graphics_queue,
|
||||||
|
+ present_queue,
|
||||||
|
+ compute_queue,
|
||||||
|
+
|
||||||
|
+ swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
+ swapchain: swapchain_stuff.swapchain,
|
||||||
|
+ swapchain_format: swapchain_stuff.swapchain_format,
|
||||||
|
+ swapchain_images: swapchain_stuff.swapchain_images,
|
||||||
|
+ swapchain_extent: swapchain_stuff.swapchain_extent,
|
||||||
|
+ swapchain_imageviews,
|
||||||
|
+ swapchain_framebuffers,
|
||||||
|
+
|
||||||
|
+ graphics_pipeline_layout,
|
||||||
|
+ render_pass,
|
||||||
|
+ graphics_pipeline,
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ compute_descriptor_set,
|
||||||
|
+ compute_pipeline_layout,
|
||||||
|
+ compute_pipeline,*/
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* FUCKED UP GRAPHICS PIPELINE CREATION FUNCTION WITH INTEGRATED COMPUTE PIPELINE CCREATION, THIS
|
||||||
|
+ * IS SUPER FUCKED
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
framebuffers: &Vec<vk::Framebuffer>,
|
||||||
|
@@ -346,31 +573,42 @@ impl VulkanApp {
|
||||||
|
.end_command_buffer(command_buffer)
|
||||||
|
.expect("Failed to record Command Buffer at Ending!");
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- command_buffers
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-// Fix content -------------------------------------------------------------------------------
|
||||||
|
-impl VulkanApp {
|
||||||
|
- fn create_graphics_pipeline(
|
||||||
|
- device: &ash::Device,
|
||||||
|
- render_pass: vk::RenderPass,
|
||||||
|
- swapchain_extent: vk::Extent2D,
|
||||||
|
- ) -> (vk::Pipeline, vk::PipelineLayout) {
|
||||||
|
- let mut shader_modules: Vec<vk::PipelineShaderStageCreateInfo> = vec![];
|
||||||
|
- let main_function = CString::new("main").unwrap();
|
||||||
|
- for (shader, stage_i) in shaders() {
|
||||||
|
- shader_modules.push(vk::PipelineShaderStageCreateInfo {
|
||||||
|
- s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
- p_next: ptr::null(),
|
||||||
|
- flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
- module: share::create_shader_module(device, shader),
|
||||||
|
- p_name: main_function.as_ptr(),
|
||||||
|
- stage: stage_i,
|
||||||
|
- p_specialization_info: ptr::null(),
|
||||||
|
- })
|
||||||
|
+ shader_modules.push(vk::PipelineShaderStageCreateInfo {
|
||||||
|
+ s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
+ p_next: ptr::null(),
|
||||||
|
+ flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
+ module: share::create_shader_module(device, shader),
|
||||||
|
+ p_name: main_function.as_ptr(),
|
||||||
|
+ stage: stage_flag,
|
||||||
|
+ p_specialization_info: ptr::null(),
|
||||||
|
+ });
|
||||||
|
+ } else if stage_flag == vk::ShaderStageFlags::FRAGMENT {
|
||||||
|
+ shader_modules.push(
|
||||||
|
+ vk::PipelineShaderStageCreateInfo {
|
||||||
|
+ s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
+ p_next: ptr::null(),
|
||||||
|
+ flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
+ module: share::create_shader_module(device, shader),
|
||||||
|
+ p_name: main_function.as_ptr(),
|
||||||
|
+ stage: stage_flag,
|
||||||
|
+ p_specialization_info: ptr::null(),
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+ )
|
||||||
|
+ } else if stage_flag == vk::ShaderStageFlags::VERTEX {
|
||||||
|
+ shader_modules.push(
|
||||||
|
+ vk::PipelineShaderStageCreateInfo {
|
||||||
|
+ s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
+ p_next: ptr::null(),
|
||||||
|
+ flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
+ module: share::create_shader_module(device, shader),
|
||||||
|
+ p_name: main_function.as_ptr(),
|
||||||
|
+ stage: stage_flag,
|
||||||
|
+ p_specialization_info: ptr::null(),
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+ )
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
let binding_description = Vertex::get_binding_description();
|
||||||
|
@@ -417,6 +655,12 @@ impl VulkanApp {
|
||||||
|
p_viewports: viewports.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
+ let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
+ s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
+ p_next: ptr::null(),
|
||||||
|
+ p_viewports: viewports.as_ptr(),
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
@@ -492,21 +736,7 @@ impl VulkanApp {
|
||||||
|
blend_constants: [0.0, 0.0, 0.0, 0.0],
|
||||||
|
};
|
||||||
|
|
||||||
|
- let pipeline_layout_create_info = vk::PipelineLayoutCreateInfo {
|
||||||
|
- s_type: vk::StructureType::PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
- p_next: ptr::null(),
|
||||||
|
- flags: vk::PipelineLayoutCreateFlags::empty(),
|
||||||
|
- set_layout_count: 0,
|
||||||
|
- p_set_layouts: ptr::null(),
|
||||||
|
- push_constant_range_count: 0,
|
||||||
|
- p_push_constant_ranges: ptr::null(),
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- let pipeline_layout = unsafe {
|
||||||
|
- device
|
||||||
|
- .create_pipeline_layout(&pipeline_layout_create_info, None)
|
||||||
|
- .expect("Failed to create pipeline layout!")
|
||||||
|
- };
|
||||||
|
+ println!("shader module count: {}", shader_modules.len());
|
||||||
|
|
||||||
|
let graphic_pipeline_create_infos = [vk::GraphicsPipelineCreateInfo {
|
||||||
|
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
@@ -520,34 +750,26 @@ impl VulkanApp {
|
||||||
|
p_viewport_state: &viewport_state_create_info,
|
||||||
|
p_rasterization_state: &rasterization_statue_create_info,
|
||||||
|
p_multisample_state: &multisample_state_create_info,
|
||||||
|
- p_depth_stencil_state: &depth_state_create_info,
|
||||||
|
- p_color_blend_state: &color_blend_state,
|
||||||
|
- p_dynamic_state: ptr::null(),
|
||||||
|
- layout: pipeline_layout,
|
||||||
|
- render_pass,
|
||||||
|
- subpass: 0,
|
||||||
|
- base_pipeline_handle: vk::Pipeline::null(),
|
||||||
|
- base_pipeline_index: -1,
|
||||||
|
- }];
|
||||||
|
+ s_type: vk::StructureType::COMPUTE_PIPELINE_CREATE_INFO,
|
||||||
|
+ p_next: ptr::null(),
|
||||||
|
+ layout: pipeline_layout,
|
||||||
|
+ flags: vk::PipelineCreateFlags::empty(),
|
||||||
|
+ ..Default::default()
|
||||||
|
+ }
|
||||||
|
+ );
|
||||||
|
|
||||||
|
- let graphics_pipelines = unsafe {
|
||||||
|
+ }
|
||||||
|
+ let compute_pipelines = unsafe {
|
||||||
|
device
|
||||||
|
- .create_graphics_pipelines(
|
||||||
|
+ .create_compute_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
- &graphic_pipeline_create_infos,
|
||||||
|
+ &compute_infos,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
- .expect("Failed to create Graphics Pipeline!.")
|
||||||
|
- };
|
||||||
|
-
|
||||||
|
- unsafe {
|
||||||
|
- for shader in shader_modules {
|
||||||
|
- device.destroy_shader_module(shader.module, None)
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ }.unwrap();
|
||||||
|
|
||||||
|
- (graphics_pipelines[0], pipeline_layout)
|
||||||
|
- }
|
||||||
|
+ (compute_pipelines, pipeline_layout)
|
||||||
|
+ }*/
|
||||||
|
|
||||||
|
fn draw_frame(&mut self) {
|
||||||
|
let wait_fences = [self.in_flight_fences[self.current_frame]];
|
||||||
|
@@ -657,7 +879,7 @@ impl VulkanApp {
|
||||||
|
};
|
||||||
|
self.cleanup_swapchain();
|
||||||
|
|
||||||
|
- let swapchain_stuff = share::create_swapchain(
|
||||||
|
+ let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&self.instance,
|
||||||
|
&self.device,
|
||||||
|
self.physical_device,
|
||||||
|
@@ -680,7 +902,7 @@ impl VulkanApp {
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
self.graphics_pipeline = graphics_pipeline;
|
||||||
|
- self.pipeline_layout = pipeline_layout;
|
||||||
|
+ self.graphics_pipeline_layout = pipeline_layout;
|
||||||
|
|
||||||
|
self.swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&self.device,
|
||||||
|
@@ -708,7 +930,7 @@ impl VulkanApp {
|
||||||
|
}
|
||||||
|
self.device.destroy_pipeline(self.graphics_pipeline, None);
|
||||||
|
self.device
|
||||||
|
- .destroy_pipeline_layout(self.pipeline_layout, None);
|
||||||
|
+ .destroy_pipeline_layout(self.graphics_pipeline_layout, None);
|
||||||
|
self.device.destroy_render_pass(self.render_pass, None);
|
||||||
|
for &image_view in self.swapchain_imageviews.iter() {
|
||||||
|
self.device.destroy_image_view(image_view, None);
|
||||||
|
@@ -719,7 +941,10 @@ impl VulkanApp {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
+
|
||||||
|
impl Drop for VulkanApp {
|
||||||
|
+ //cleanup in C++
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..MAX_FRAMES_IN_FLIGHT {
|
||||||
|
@@ -732,6 +957,9 @@ impl Drop for VulkanApp {
|
||||||
|
|
||||||
|
self.cleanup_swapchain();
|
||||||
|
|
||||||
|
+ self.device
|
||||||
|
+ .destory
|
||||||
|
+
|
||||||
|
self.device.destroy_buffer(self.vertex_buffer, None);
|
||||||
|
self.device.free_memory(self.vertex_buffer_memory, None);
|
||||||
|
|
||||||
|
@@ -749,46 +977,3 @@ impl Drop for VulkanApp {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-impl VulkanApp {
|
||||||
|
- pub fn main_loop(mut self, event_loop: EventLoop<()>) {
|
||||||
|
- let mut tick_counter = utility::fps_limiter::FPSLimiter::new();
|
||||||
|
-
|
||||||
|
- 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
|
||||||
|
- }
|
||||||
|
- _ => {}
|
||||||
|
- },
|
||||||
|
- },
|
||||||
|
- _ => {}
|
||||||
|
- },
|
||||||
|
- Event::MainEventsCleared => {
|
||||||
|
- self.window.request_redraw();
|
||||||
|
- }
|
||||||
|
- Event::RedrawRequested(_window_id) => {
|
||||||
|
- self.draw_frame();
|
||||||
|
-
|
||||||
|
- tick_counter.tick_frame();
|
||||||
|
- if true {
|
||||||
|
- print!("FPS: {}\r", tick_counter.fps());
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- Event::LoopDestroyed => {
|
||||||
|
- unsafe {
|
||||||
|
- self.device
|
||||||
|
- .device_wait_idle()
|
||||||
|
- .expect("Failed to wait device idle!")
|
||||||
|
- };
|
||||||
|
- }
|
||||||
|
- _ => (),
|
||||||
|
- })
|
||||||
|
- }
|
||||||
|
-}
|
@ -0,0 +1,943 @@
|
|||||||
|
use crate::{
|
||||||
|
entities::*, shaders::*, utility, utility::constants::*, utility::debug::*, utility::share,
|
||||||
|
utility::structures::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use ash::{vk, Entry};
|
||||||
|
|
||||||
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const WINDOW_TITLE: &'static str = "Template";
|
||||||
|
|
||||||
|
pub struct VulkanApp {
|
||||||
|
window: winit::window::Window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: ash::Entry,
|
||||||
|
instance: ash::Instance,
|
||||||
|
surface_loader: ash::extensions::khr::Surface,
|
||||||
|
surface: vk::SurfaceKHR,
|
||||||
|
debug_utils_loader: ash::extensions::ext::DebugUtils,
|
||||||
|
debug_merssager: vk::DebugUtilsMessengerEXT,
|
||||||
|
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
device: ash::Device,
|
||||||
|
|
||||||
|
queue_family: QueueFamilyIndices,
|
||||||
|
graphics_queue: vk::Queue,
|
||||||
|
present_queue: vk::Queue,
|
||||||
|
//new from C++
|
||||||
|
compute_queue: vk::Queue,
|
||||||
|
|
||||||
|
//not in C++
|
||||||
|
swapchain_loader: ash::extensions::khr::Swapchain,
|
||||||
|
swapchain: vk::SwapchainKHR,
|
||||||
|
swapchain_images: Vec<vk::Image>,
|
||||||
|
swapchain_format: vk::Format,
|
||||||
|
swapchain_extent: vk::Extent2D,
|
||||||
|
swapchain_imageviews: Vec<vk::ImageView>,
|
||||||
|
swapchain_framebuffers: Vec<vk::Framebuffer>,
|
||||||
|
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
|
||||||
|
graphics_pipeline_layout: vk::PipelineLayout,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
|
||||||
|
//new from C++
|
||||||
|
compute_descriptor_set_layout: vk::DescriptorSetLayout,
|
||||||
|
compute_pipeline_layout: vk::PipelineLayout,
|
||||||
|
compute_pipeline: vk::Pipeline,
|
||||||
|
|
||||||
|
//vertex buffer for the triangle verticies
|
||||||
|
//i think this is the same as shaderStorageBuffers in C++ version
|
||||||
|
shader_storage_buffers: Vec<vk::Buffer>,
|
||||||
|
shader_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
|
||||||
|
uniform_buffers: Vec<vk::Buffer>,
|
||||||
|
uniform_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
uniform_buffers_mapped: Vec<*mut c_void>,
|
||||||
|
|
||||||
|
|
||||||
|
descriptor_pool: vk::DescriptorPool,
|
||||||
|
compute_descriptor_sets: Vec<vk::DescriptorSet>,
|
||||||
|
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
compute_command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
|
||||||
|
image_available_semaphores: Vec<vk::Semaphore>,
|
||||||
|
render_finished_semaphores: Vec<vk::Semaphore>,
|
||||||
|
in_flight_fences: Vec<vk::Fence>,
|
||||||
|
current_frame: usize,
|
||||||
|
|
||||||
|
is_framebuffer_resized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanApp {
|
||||||
|
//C++ code::
|
||||||
|
/*
|
||||||
|
createInstance();
|
||||||
|
setupDebugMessenger();
|
||||||
|
createSurface();
|
||||||
|
pickPhysicalDevice();
|
||||||
|
createLogicalDevice();
|
||||||
|
createSwapChain();
|
||||||
|
createImageViews();
|
||||||
|
createRenderPass();
|
||||||
|
createComputeDescriptorSetLayout();
|
||||||
|
createGraphicsPipeline();
|
||||||
|
createComputePipeline();
|
||||||
|
createFramebuffers();
|
||||||
|
createCommandPool();
|
||||||
|
createShaderStorageBuffers();
|
||||||
|
createUniformBuffers(); DONE
|
||||||
|
createDescriptorPool(); DONE
|
||||||
|
createComputeDescriptorSets(); DONE
|
||||||
|
createCommandBuffers(); DONE
|
||||||
|
createComputeCommandBuffers(); DONE
|
||||||
|
createSyncObjects(); DONE
|
||||||
|
*/
|
||||||
|
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> VulkanApp {
|
||||||
|
let window =
|
||||||
|
utility::window::init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
// init vulkan stuff
|
||||||
|
let entry = unsafe { Entry::load().unwrap() };
|
||||||
|
let instance = share::create_instance(
|
||||||
|
&entry,
|
||||||
|
WINDOW_TITLE,
|
||||||
|
VALIDATION.is_enable,
|
||||||
|
&VALIDATION.required_validation_layers.to_vec(),
|
||||||
|
);
|
||||||
|
let surface_stuff =
|
||||||
|
SurfaceStuff::new(&entry, &instance, &window, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
let (debug_utils_loader, debug_merssager) =
|
||||||
|
setup_debug_utils(VALIDATION.is_enable, &entry, &instance);
|
||||||
|
let physical_device =
|
||||||
|
share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
let (device, queue_family) = share::create_logical_device(
|
||||||
|
&instance,
|
||||||
|
physical_device,
|
||||||
|
&VALIDATION,
|
||||||
|
&DEVICE_EXTENSIONS,
|
||||||
|
&surface_stuff,
|
||||||
|
);
|
||||||
|
let graphics_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
let compute_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
&window,
|
||||||
|
&surface_stuff,
|
||||||
|
&queue_family,
|
||||||
|
);
|
||||||
|
let swapchain_imageviews = share::create_image_views(
|
||||||
|
&device,
|
||||||
|
swapchain_stuff.swapchain_format,
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compute_pipeline = compute_pipelines[0];
|
||||||
|
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
&swapchain_imageviews,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&device,
|
||||||
|
command_pool,
|
||||||
|
graphics_pipeline,
|
||||||
|
&swapchain_framebuffers,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
||||||
|
VulkanApp {
|
||||||
|
// winit stuff
|
||||||
|
window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: entry,
|
||||||
|
instance,
|
||||||
|
surface: surface_stuff.surface,
|
||||||
|
surface_loader: surface_stuff.surface_loader,
|
||||||
|
debug_utils_loader,
|
||||||
|
debug_merssager,
|
||||||
|
|
||||||
|
physical_device,
|
||||||
|
device,
|
||||||
|
|
||||||
|
queue_family,
|
||||||
|
graphics_queue,
|
||||||
|
present_queue,
|
||||||
|
compute_queue,
|
||||||
|
|
||||||
|
swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
swapchain: swapchain_stuff.swapchain,
|
||||||
|
swapchain_format: swapchain_stuff.swapchain_format,
|
||||||
|
swapchain_images: swapchain_stuff.swapchain_images,
|
||||||
|
swapchain_extent: swapchain_stuff.swapchain_extent,
|
||||||
|
swapchain_imageviews,
|
||||||
|
swapchain_framebuffers,
|
||||||
|
|
||||||
|
graphics_pipeline_layout,
|
||||||
|
render_pass,
|
||||||
|
graphics_pipeline,
|
||||||
|
|
||||||
|
|
||||||
|
compute_descriptor_sets,
|
||||||
|
compute_pipeline_layout,
|
||||||
|
compute_pipeline,
|
||||||
|
|
||||||
|
vertex_buffer,
|
||||||
|
vertex_buffer_memory,
|
||||||
|
|
||||||
|
command_pool,
|
||||||
|
command_buffers,
|
||||||
|
|
||||||
|
image_available_semaphores: sync_ojbects.image_available_semaphores,
|
||||||
|
render_finished_semaphores: sync_ojbects.render_finished_semaphores,
|
||||||
|
in_flight_fences: sync_ojbects.inflight_fences,
|
||||||
|
current_frame: 0,
|
||||||
|
|
||||||
|
is_framebuffer_resized: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_vertex_buffer(
|
||||||
|
instance: &ash::Instance,
|
||||||
|
device: &ash::Device,
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
) -> (vk::Buffer, vk::DeviceMemory) {
|
||||||
|
let vertex_buffer_create_info = vk::BufferCreateInfo {
|
||||||
|
s_type: vk::StructureType::BUFFER_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::BufferCreateFlags::empty(),
|
||||||
|
size: std::mem::size_of_val(&TRI_VERT_DATA) as u64,
|
||||||
|
usage: vk::BufferUsageFlags::VERTEX_BUFFER
|
||||||
|
| vk::BufferUsageFlags::STORAGE_BUFFER
|
||||||
|
| vk::BufferUsageFlags::TRANSFER_DST,
|
||||||
|
sharing_mode: vk::SharingMode::EXCLUSIVE,
|
||||||
|
queue_family_index_count: 0,
|
||||||
|
p_queue_family_indices: ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertex_buffer = unsafe {
|
||||||
|
device
|
||||||
|
.create_buffer(&vertex_buffer_create_info, None)
|
||||||
|
.expect("Failed to create Vertex Buffer")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mem_requirements = unsafe { device.get_buffer_memory_requirements(vertex_buffer) };
|
||||||
|
let mem_properties =
|
||||||
|
unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||||
|
let required_memory_flags: vk::MemoryPropertyFlags =
|
||||||
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT;
|
||||||
|
let memory_type = VulkanApp::find_memory_type(
|
||||||
|
mem_requirements.memory_type_bits,
|
||||||
|
required_memory_flags,
|
||||||
|
mem_properties,
|
||||||
|
);
|
||||||
|
|
||||||
|
let allocate_info = vk::MemoryAllocateInfo {
|
||||||
|
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
allocation_size: mem_requirements.size,
|
||||||
|
memory_type_index: memory_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertex_buffer_memory = unsafe {
|
||||||
|
device
|
||||||
|
.allocate_memory(&allocate_info, None)
|
||||||
|
.expect("Failed to allocate vertex buffer memory!")
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device
|
||||||
|
.bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0)
|
||||||
|
.expect("Failed to bind Buffer");
|
||||||
|
|
||||||
|
let data_ptr = device
|
||||||
|
.map_memory(
|
||||||
|
vertex_buffer_memory,
|
||||||
|
0,
|
||||||
|
vertex_buffer_create_info.size,
|
||||||
|
vk::MemoryMapFlags::empty(),
|
||||||
|
)
|
||||||
|
.expect("Failed to Map Memory") as *mut Vertex;
|
||||||
|
|
||||||
|
data_ptr.copy_from_nonoverlapping(TRI_VERT_DATA.as_ptr(), TRI_VERT_DATA.len());
|
||||||
|
|
||||||
|
device.unmap_memory(vertex_buffer_memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
(vertex_buffer, vertex_buffer_memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_memory_type(
|
||||||
|
type_filter: u32,
|
||||||
|
required_properties: vk::MemoryPropertyFlags,
|
||||||
|
mem_properties: vk::PhysicalDeviceMemoryProperties,
|
||||||
|
) -> u32 {
|
||||||
|
for (i, memory_type) in mem_properties.memory_types.iter().enumerate() {
|
||||||
|
//if (type_filter & (1 << i)) > 0 && (memory_type.property_flags & required_properties) == required_properties {
|
||||||
|
// return i as u32
|
||||||
|
// }
|
||||||
|
|
||||||
|
// same implementation
|
||||||
|
if (type_filter & (1 << i)) > 0
|
||||||
|
&& memory_type.property_flags.contains(required_properties)
|
||||||
|
{
|
||||||
|
return i as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Failed to find suitable memory type!")
|
||||||
|
share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
let (device, queue_family) = share::create_logical_device(
|
||||||
|
&instance,
|
||||||
|
physical_device,
|
||||||
|
&VALIDATION,
|
||||||
|
&DEVICE_EXTENSIONS,
|
||||||
|
&surface_stuff,
|
||||||
|
);
|
||||||
|
let graphics_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
let compute_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
&window,
|
||||||
|
&surface_stuff,
|
||||||
|
&queue_family,
|
||||||
|
);
|
||||||
|
let swapchain_imageviews = share::create_image_views(
|
||||||
|
&device,
|
||||||
|
swapchain_stuff.swapchain_format,
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compute_pipeline = compute_pipelines[0];
|
||||||
|
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
&swapchain_imageviews,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&device,
|
||||||
|
command_pool,
|
||||||
|
graphics_pipeline,
|
||||||
|
&swapchain_framebuffers,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
||||||
|
VulkanApp {
|
||||||
|
// winit stuff
|
||||||
|
window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: entry,
|
||||||
|
instance,
|
||||||
|
surface: surface_stuff.surface,
|
||||||
|
surface_loader: surface_stuff.surface_loader,
|
||||||
|
debug_utils_loader,
|
||||||
|
debug_merssager,
|
||||||
|
|
||||||
|
physical_device,
|
||||||
|
device,
|
||||||
|
|
||||||
|
queue_family,
|
||||||
|
graphics_queue,
|
||||||
|
present_queue,
|
||||||
|
compute_queue,
|
||||||
|
|
||||||
|
swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
swapchain: swapchain_stuff.swapchain,
|
||||||
|
swapchain_format: swapchain_stuff.swapchain_format,
|
||||||
|
swapchain_images: swapchain_stuff.swapchain_images,
|
||||||
|
swapchain_extent: swapchain_stuff.swapchain_extent,
|
||||||
|
swapchain_imageviews,
|
||||||
|
swapchain_framebuffers,
|
||||||
|
|
||||||
|
graphics_pipeline_layout,
|
||||||
|
render_pass,
|
||||||
|
graphics_pipeline,
|
||||||
|
|
||||||
|
|
||||||
|
compute_descriptor_set,
|
||||||
|
compute_pipeline_layout,
|
||||||
|
compute_pipeline,
|
||||||
|
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
framebuffers: &Vec<vk::Framebuffer>,
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
surface_extent: vk::Extent2D,
|
||||||
|
vertex_buffer: vk::Buffer,
|
||||||
|
) -> Vec<vk::CommandBuffer> {
|
||||||
|
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo {
|
||||||
|
s_type: vk::StructureType::COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
command_buffer_count: framebuffers.len() as u32,
|
||||||
|
command_pool,
|
||||||
|
level: vk::CommandBufferLevel::PRIMARY,
|
||||||
|
};
|
||||||
|
|
||||||
|
let command_buffers = unsafe {
|
||||||
|
device
|
||||||
|
.allocate_command_buffers(&command_buffer_allocate_info)
|
||||||
|
.expect("Failed to allocate Command Buffers!")
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i, &command_buffer) in command_buffers.iter().enumerate() {
|
||||||
|
let command_buffer_begin_info = vk::CommandBufferBeginInfo {
|
||||||
|
s_type: vk::StructureType::COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::CommandBufferUsageFlags::SIMULTANEOUS_USE,
|
||||||
|
p_inheritance_info: ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device
|
||||||
|
.begin_command_buffer(command_buffer, &command_buffer_begin_info)
|
||||||
|
.expect("Failed to begin recording Command Buffer at beginning!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let clear_values = [vk::ClearValue {
|
||||||
|
color: vk::ClearColorValue {
|
||||||
|
float32: [0.0, 0.0, 0.0, 1.0],
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
|
||||||
|
let render_pass_begin_info = vk::RenderPassBeginInfo {
|
||||||
|
s_type: vk::StructureType::RENDER_PASS_BEGIN_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
framebuffer: framebuffers[i],
|
||||||
|
render_pass,
|
||||||
|
clear_value_count: clear_values.len() as u32,
|
||||||
|
p_clear_values: clear_values.as_ptr(),
|
||||||
|
render_area: vk::Rect2D {
|
||||||
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
|
extent: surface_extent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device.cmd_begin_render_pass(
|
||||||
|
command_buffer,
|
||||||
|
&render_pass_begin_info,
|
||||||
|
vk::SubpassContents::INLINE,
|
||||||
|
);
|
||||||
|
device.cmd_bind_pipeline(
|
||||||
|
command_buffer,
|
||||||
|
vk::PipelineBindPoint::GRAPHICS,
|
||||||
|
graphics_pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
let vertex_buffers = [vertex_buffer];
|
||||||
|
let offsets = [0_u64];
|
||||||
|
|
||||||
|
device.cmd_bind_vertex_buffers(command_buffer, 0, &vertex_buffers, &offsets);
|
||||||
|
|
||||||
|
device.cmd_draw(command_buffer, TRI_VERT_DATA.len() as u32, 1, 0, 0);
|
||||||
|
|
||||||
|
device.cmd_end_render_pass(command_buffer);
|
||||||
|
|
||||||
|
device
|
||||||
|
.end_command_buffer(command_buffer)
|
||||||
|
.expect("Failed to record Command Buffer at Ending!");
|
||||||
|
}
|
||||||
|
shader_modules.push(vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
});
|
||||||
|
} else if stage_flag == vk::ShaderStageFlags::FRAGMENT {
|
||||||
|
shader_modules.push(
|
||||||
|
vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if stage_flag == vk::ShaderStageFlags::VERTEX {
|
||||||
|
shader_modules.push(
|
||||||
|
vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let binding_description = Vertex::get_binding_description();
|
||||||
|
let attribute_description = Vertex::get_attribute_descriptions();
|
||||||
|
|
||||||
|
let vertex_input_state_create_info = vk::PipelineVertexInputStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineVertexInputStateCreateFlags::empty(),
|
||||||
|
vertex_attribute_description_count: attribute_description.len() as u32,
|
||||||
|
p_vertex_attribute_descriptions: attribute_description.as_ptr(),
|
||||||
|
vertex_binding_description_count: binding_description.len() as u32,
|
||||||
|
p_vertex_binding_descriptions: binding_description.as_ptr(),
|
||||||
|
};
|
||||||
|
let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
flags: vk::PipelineInputAssemblyStateCreateFlags::empty(),
|
||||||
|
p_next: ptr::null(),
|
||||||
|
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
|
||||||
|
primitive_restart_enable: vk::FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let viewports = [vk::Viewport {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: swapchain_extent.width as f32,
|
||||||
|
height: swapchain_extent.height as f32,
|
||||||
|
min_depth: 0.0,
|
||||||
|
max_depth: 1.0,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let scissors = [vk::Rect2D {
|
||||||
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
|
extent: swapchain_extent,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let viewport_state_create_info = vk::PipelineViewportStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineViewportStateCreateFlags::empty(),
|
||||||
|
scissor_count: scissors.len() as u32,
|
||||||
|
p_scissors: scissors.as_ptr(),
|
||||||
|
viewport_count: viewports.len() as u32,
|
||||||
|
p_viewports: viewports.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
p_viewports: viewports.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineRasterizationStateCreateFlags::empty(),
|
||||||
|
cull_mode: vk::CullModeFlags::BACK,
|
||||||
|
front_face: vk::FrontFace::CLOCKWISE,
|
||||||
|
line_width: 1.0,
|
||||||
|
polygon_mode: vk::PolygonMode::FILL,
|
||||||
|
rasterizer_discard_enable: vk::FALSE,
|
||||||
|
depth_clamp_enable: vk::FALSE,
|
||||||
|
depth_bias_clamp: 0.0,
|
||||||
|
depth_bias_constant_factor: 0.0,
|
||||||
|
depth_bias_enable: vk::FALSE,
|
||||||
|
depth_bias_slope_factor: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let multisample_state_create_info = vk::PipelineMultisampleStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
flags: vk::PipelineMultisampleStateCreateFlags::empty(),
|
||||||
|
p_next: ptr::null(),
|
||||||
|
rasterization_samples: vk::SampleCountFlags::TYPE_1,
|
||||||
|
sample_shading_enable: vk::FALSE,
|
||||||
|
min_sample_shading: 0.0,
|
||||||
|
p_sample_mask: ptr::null(),
|
||||||
|
alpha_to_one_enable: vk::FALSE,
|
||||||
|
alpha_to_coverage_enable: vk::FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let stencil_state = vk::StencilOpState {
|
||||||
|
fail_op: vk::StencilOp::KEEP,
|
||||||
|
pass_op: vk::StencilOp::KEEP,
|
||||||
|
depth_fail_op: vk::StencilOp::KEEP,
|
||||||
|
compare_op: vk::CompareOp::ALWAYS,
|
||||||
|
compare_mask: 0,
|
||||||
|
write_mask: 0,
|
||||||
|
reference: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let depth_state_create_info = vk::PipelineDepthStencilStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineDepthStencilStateCreateFlags::empty(),
|
||||||
|
depth_test_enable: vk::FALSE,
|
||||||
|
depth_write_enable: vk::FALSE,
|
||||||
|
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
||||||
|
depth_bounds_test_enable: vk::FALSE,
|
||||||
|
stencil_test_enable: vk::FALSE,
|
||||||
|
front: stencil_state,
|
||||||
|
back: stencil_state,
|
||||||
|
max_depth_bounds: 1.0,
|
||||||
|
min_depth_bounds: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
|
||||||
|
blend_enable: vk::FALSE,
|
||||||
|
color_write_mask: vk::ColorComponentFlags::RGBA,
|
||||||
|
src_color_blend_factor: vk::BlendFactor::ONE,
|
||||||
|
dst_color_blend_factor: vk::BlendFactor::ZERO,
|
||||||
|
color_blend_op: vk::BlendOp::ADD,
|
||||||
|
src_alpha_blend_factor: vk::BlendFactor::ONE,
|
||||||
|
dst_alpha_blend_factor: vk::BlendFactor::ZERO,
|
||||||
|
alpha_blend_op: vk::BlendOp::ADD,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let color_blend_state = vk::PipelineColorBlendStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineColorBlendStateCreateFlags::empty(),
|
||||||
|
logic_op_enable: vk::FALSE,
|
||||||
|
logic_op: vk::LogicOp::COPY,
|
||||||
|
attachment_count: color_blend_attachment_states.len() as u32,
|
||||||
|
p_attachments: color_blend_attachment_states.as_ptr(),
|
||||||
|
blend_constants: [0.0, 0.0, 0.0, 0.0],
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("shader module count: {}", shader_modules.len());
|
||||||
|
|
||||||
|
let graphic_pipeline_create_infos = [vk::GraphicsPipelineCreateInfo {
|
||||||
|
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineCreateFlags::empty(),
|
||||||
|
stage_count: shader_modules.len() as u32,
|
||||||
|
p_stages: shader_modules.as_ptr(),
|
||||||
|
p_vertex_input_state: &vertex_input_state_create_info,
|
||||||
|
p_input_assembly_state: &vertex_input_assembly_state_info,
|
||||||
|
p_tessellation_state: ptr::null(),
|
||||||
|
p_viewport_state: &viewport_state_create_info,
|
||||||
|
p_rasterization_state: &rasterization_statue_create_info,
|
||||||
|
p_multisample_state: &multisample_state_create_info,
|
||||||
|
s_type: vk::StructureType::COMPUTE_PIPELINE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
layout: pipeline_layout,
|
||||||
|
flags: vk::PipelineCreateFlags::empty(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
let compute_pipelines = unsafe {
|
||||||
|
device
|
||||||
|
.create_compute_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
&compute_infos,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}.unwrap();
|
||||||
|
|
||||||
|
(compute_pipelines, pipeline_layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_frame(&mut self) {
|
||||||
|
let wait_fences = [self.in_flight_fences[self.current_frame]];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.wait_for_fences(&wait_fences, true, std::u64::MAX)
|
||||||
|
.expect("Failed to wait for Fence!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (image_index, _is_sub_optimal) = unsafe {
|
||||||
|
let result = self.swapchain_loader.acquire_next_image(
|
||||||
|
self.swapchain,
|
||||||
|
std::u64::MAX,
|
||||||
|
self.image_available_semaphores[self.current_frame],
|
||||||
|
vk::Fence::null(),
|
||||||
|
);
|
||||||
|
match result {
|
||||||
|
Ok(image_index) => image_index,
|
||||||
|
Err(vk_result) => match vk_result {
|
||||||
|
vk::Result::ERROR_OUT_OF_DATE_KHR => {
|
||||||
|
self.recreate_swapchain();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => panic!("Failed to acquire Swap Chain Image!"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let wait_semaphores = [self.image_available_semaphores[self.current_frame]];
|
||||||
|
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
||||||
|
let signal_semaphores = [self.render_finished_semaphores[self.current_frame]];
|
||||||
|
|
||||||
|
let submit_infos = [vk::SubmitInfo {
|
||||||
|
s_type: vk::StructureType::SUBMIT_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
wait_semaphore_count: wait_semaphores.len() as u32,
|
||||||
|
p_wait_semaphores: wait_semaphores.as_ptr(),
|
||||||
|
p_wait_dst_stage_mask: wait_stages.as_ptr(),
|
||||||
|
command_buffer_count: 1,
|
||||||
|
p_command_buffers: &self.command_buffers[image_index as usize],
|
||||||
|
signal_semaphore_count: signal_semaphores.len() as u32,
|
||||||
|
p_signal_semaphores: signal_semaphores.as_ptr(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.reset_fences(&wait_fences)
|
||||||
|
.expect("Failed to reset Fence!");
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.queue_submit(
|
||||||
|
self.graphics_queue,
|
||||||
|
&submit_infos,
|
||||||
|
self.in_flight_fences[self.current_frame],
|
||||||
|
)
|
||||||
|
.expect("Failed to execute queue submit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let swapchains = [self.swapchain];
|
||||||
|
|
||||||
|
let present_info = vk::PresentInfoKHR {
|
||||||
|
s_type: vk::StructureType::PRESENT_INFO_KHR,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
wait_semaphore_count: 1,
|
||||||
|
p_wait_semaphores: signal_semaphores.as_ptr(),
|
||||||
|
swapchain_count: 1,
|
||||||
|
p_swapchains: swapchains.as_ptr(),
|
||||||
|
p_image_indices: &image_index,
|
||||||
|
p_results: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
self.swapchain_loader
|
||||||
|
.queue_present(self.present_queue, &present_info)
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_resized = match result {
|
||||||
|
Ok(_) => self.is_framebuffer_resized,
|
||||||
|
Err(vk_result) => match vk_result {
|
||||||
|
vk::Result::ERROR_OUT_OF_DATE_KHR | vk::Result::SUBOPTIMAL_KHR => true,
|
||||||
|
_ => panic!("Failed to execute queue present."),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if is_resized {
|
||||||
|
self.is_framebuffer_resized = false;
|
||||||
|
self.recreate_swapchain();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_frame = (self.current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recreate_swapchain(&mut self) {
|
||||||
|
// parameters -------------
|
||||||
|
let surface_suff = SurfaceStuff {
|
||||||
|
surface_loader: self.surface_loader.clone(),
|
||||||
|
surface: self.surface,
|
||||||
|
screen_width: WINDOW_WIDTH,
|
||||||
|
screen_height: WINDOW_HEIGHT,
|
||||||
|
};
|
||||||
|
// ------------------------
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.device_wait_idle()
|
||||||
|
.expect("Failed to wait device idle!")
|
||||||
|
};
|
||||||
|
self.cleanup_swapchain();
|
||||||
|
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&self.instance,
|
||||||
|
&self.device,
|
||||||
|
self.physical_device,
|
||||||
|
&self.window,
|
||||||
|
&surface_suff,
|
||||||
|
&self.queue_family,
|
||||||
|
);
|
||||||
|
self.swapchain_loader = swapchain_stuff.swapchain_loader;
|
||||||
|
self.swapchain = swapchain_stuff.swapchain;
|
||||||
|
self.swapchain_images = swapchain_stuff.swapchain_images;
|
||||||
|
self.swapchain_format = swapchain_stuff.swapchain_format;
|
||||||
|
self.swapchain_extent = swapchain_stuff.swapchain_extent;
|
||||||
|
|
||||||
|
self.swapchain_imageviews =
|
||||||
|
share::create_image_views(&self.device, self.swapchain_format, &self.swapchain_images);
|
||||||
|
self.render_pass = share::create_render_pass(&self.device, self.swapchain_format);
|
||||||
|
let (graphics_pipeline, pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&self.device,
|
||||||
|
self.render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
self.graphics_pipeline = graphics_pipeline;
|
||||||
|
self.graphics_pipeline_layout = pipeline_layout;
|
||||||
|
|
||||||
|
self.swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&self.device,
|
||||||
|
self.render_pass,
|
||||||
|
&self.swapchain_imageviews,
|
||||||
|
self.swapchain_extent,
|
||||||
|
);
|
||||||
|
self.command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&self.device,
|
||||||
|
self.command_pool,
|
||||||
|
self.graphics_pipeline,
|
||||||
|
&self.swapchain_framebuffers,
|
||||||
|
self.render_pass,
|
||||||
|
self.swapchain_extent,
|
||||||
|
self.vertex_buffer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cleanup_swapchain(&self) {
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.free_command_buffers(self.command_pool, &self.command_buffers);
|
||||||
|
for &framebuffer in self.swapchain_framebuffers.iter() {
|
||||||
|
self.device.destroy_framebuffer(framebuffer, None);
|
||||||
|
}
|
||||||
|
self.device.destroy_pipeline(self.graphics_pipeline, None);
|
||||||
|
self.device
|
||||||
|
.destroy_pipeline_layout(self.graphics_pipeline_layout, None);
|
||||||
|
self.device.destroy_render_pass(self.render_pass, None);
|
||||||
|
for &image_view in self.swapchain_imageviews.iter() {
|
||||||
|
self.device.destroy_image_view(image_view, None);
|
||||||
|
}
|
||||||
|
self.swapchain_loader
|
||||||
|
.destroy_swapchain(self.swapchain, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VulkanApp {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..MAX_FRAMES_IN_FLIGHT {
|
||||||
|
self.device
|
||||||
|
.destroy_semaphore(self.image_available_semaphores[i], None);
|
||||||
|
self.device
|
||||||
|
.destroy_semaphore(self.render_finished_semaphores[i], None);
|
||||||
|
self.device.destroy_fence(self.in_flight_fences[i], None);
|
||||||
|
}
|
||||||
|
|
||||||
|
share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
let (device, queue_family) = share::create_logical_device(
|
||||||
|
&instance,
|
||||||
|
physical_device,
|
||||||
|
&VALIDATION,
|
||||||
|
&DEVICE_EXTENSIONS,
|
||||||
|
&surface_stuff,
|
||||||
|
);
|
||||||
|
let graphics_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
let compute_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
&window,
|
||||||
|
&surface_stuff,
|
||||||
|
&queue_family,
|
||||||
|
);
|
||||||
|
let swapchain_imageviews = share::create_image_views(
|
||||||
|
&device,
|
||||||
|
swapchain_stuff.swapchain_format,
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compute_pipeline = compute_pipelines[0];
|
||||||
|
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
&swapchain_imageviews,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&device,
|
||||||
|
command_pool,
|
||||||
|
graphics_pipeline,
|
||||||
|
&swapchain_framebuffers,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,979 @@
|
|||||||
|
use crate::{
|
||||||
|
entities::*, shaders::*, utility, utility::constants::*, utility::debug::*, utility::share,
|
||||||
|
utility::structures::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use ash::{vk, Entry};
|
||||||
|
|
||||||
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const WINDOW_TITLE: &'static str = "Template";
|
||||||
|
|
||||||
|
const IS_PAINT_FPS_COUNTER: bool = true;
|
||||||
|
|
||||||
|
pub fn init_window(
|
||||||
|
event_loop: &EventLoop<()>,
|
||||||
|
title: &str,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> winit::window::Window {
|
||||||
|
winit::window::WindowBuilder::new()
|
||||||
|
.with_title(title)
|
||||||
|
.with_inner_size(winit::dpi::LogicalSize::new(width, height))
|
||||||
|
.build(event_loop)
|
||||||
|
.expect("Failed to create window.")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct VulkanApp {
|
||||||
|
window: winit::window::Window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: ash::Entry,
|
||||||
|
instance: ash::Instance,
|
||||||
|
surface_loader: ash::extensions::khr::Surface,
|
||||||
|
surface: vk::SurfaceKHR,
|
||||||
|
debug_utils_loader: ash::extensions::ext::DebugUtils,
|
||||||
|
debug_merssager: vk::DebugUtilsMessengerEXT,
|
||||||
|
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
device: ash::Device,
|
||||||
|
|
||||||
|
queue_family: QueueFamilyIndices,
|
||||||
|
graphics_queue: vk::Queue,
|
||||||
|
present_queue: vk::Queue,
|
||||||
|
//new from C++
|
||||||
|
compute_queue: vk::Queue,
|
||||||
|
|
||||||
|
//not in C++
|
||||||
|
swapchain_loader: ash::extensions::khr::Swapchain,
|
||||||
|
swapchain: vk::SwapchainKHR,
|
||||||
|
swapchain_images: Vec<vk::Image>,
|
||||||
|
swapchain_format: vk::Format,
|
||||||
|
swapchain_extent: vk::Extent2D,
|
||||||
|
swapchain_imageviews: Vec<vk::ImageView>,
|
||||||
|
swapchain_framebuffers: Vec<vk::Framebuffer>,
|
||||||
|
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
|
||||||
|
graphics_pipeline_layout: vk::PipelineLayout,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
|
||||||
|
//new from C++
|
||||||
|
compute_descriptor_set_layout: vk::DescriptorSetLayout,
|
||||||
|
compute_pipeline_layout: vk::PipelineLayout,
|
||||||
|
compute_pipeline: vk::Pipeline,
|
||||||
|
|
||||||
|
//vertex buffer for the triangle verticies
|
||||||
|
//i think this is the same as shaderStorageBuffers in C++ version
|
||||||
|
shader_storage_buffers: Vec<vk::Buffer>,
|
||||||
|
shader_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
|
||||||
|
uniform_buffers: Vec<vk::Buffer>,
|
||||||
|
uniform_buffers_memory: Vec<vk::DeviceMemory>,
|
||||||
|
uniform_buffers_mapped: Vec<*mut c_void>,
|
||||||
|
|
||||||
|
|
||||||
|
descriptor_pool: vk::DescriptorPool,
|
||||||
|
compute_descriptor_sets: Vec<vk::DescriptorSet>,
|
||||||
|
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
compute_command_buffers: Vec<vk::CommandBuffer>,
|
||||||
|
|
||||||
|
image_available_semaphores: Vec<vk::Semaphore>,
|
||||||
|
render_finished_semaphores: Vec<vk::Semaphore>,
|
||||||
|
in_flight_fences: Vec<vk::Fence>,
|
||||||
|
current_frame: usize,
|
||||||
|
|
||||||
|
is_framebuffer_resized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanApp {
|
||||||
|
//C++ code::
|
||||||
|
/*
|
||||||
|
### cleanup();
|
||||||
|
createInstance(); DONE
|
||||||
|
setupDebugMessenger(); DONE
|
||||||
|
createSurface(); SurfaceStuff::new DONE
|
||||||
|
pickPhysicalDevice(); DONE
|
||||||
|
createLogicalDevice();
|
||||||
|
createSwapChain();
|
||||||
|
createImageViews();
|
||||||
|
createRenderPass();
|
||||||
|
createComputeDescriptorSetLayout();
|
||||||
|
createGraphicsPipeline();
|
||||||
|
createComputePipeline();
|
||||||
|
createFramebuffers(); DONE
|
||||||
|
createCommandPool(); DONE
|
||||||
|
createShaderStorageBuffers(); DONE
|
||||||
|
createUniformBuffers(); DONE
|
||||||
|
createDescriptorPool(); DONE
|
||||||
|
createComputeDescriptorSets(); DONE
|
||||||
|
createCommandBuffers(); DONE
|
||||||
|
createComputeCommandBuffers(); DONE
|
||||||
|
createSyncObjects(); DONE
|
||||||
|
*/
|
||||||
|
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> VulkanApp {
|
||||||
|
let window =
|
||||||
|
init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
|
||||||
|
// init vulkan stuff
|
||||||
|
let entry = unsafe { Entry::load().unwrap() };
|
||||||
|
let instance = share::create_instance(
|
||||||
|
&entry,
|
||||||
|
WINDOW_TITLE,
|
||||||
|
VALIDATION.is_enable,
|
||||||
|
&VALIDATION.required_validation_layers.to_vec(),
|
||||||
|
);
|
||||||
|
let surface_stuff =
|
||||||
|
SurfaceStuff::new(&entry, &instance, &window, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
let (debug_utils_loader, debug_merssager) =
|
||||||
|
setup_debug_utils(VALIDATION.is_enable, &entry, &instance);
|
||||||
|
let physical_device =
|
||||||
|
share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
let (device, queue_family) = share::create_logical_device(
|
||||||
|
&instance,
|
||||||
|
physical_device,
|
||||||
|
&VALIDATION,
|
||||||
|
&DEVICE_EXTENSIONS,
|
||||||
|
&surface_stuff,
|
||||||
|
);
|
||||||
|
let graphics_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
let compute_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
&window,
|
||||||
|
&surface_stuff,
|
||||||
|
&queue_family,
|
||||||
|
);
|
||||||
|
let swapchain_imageviews = share::create_image_views(
|
||||||
|
&device,
|
||||||
|
swapchain_stuff.swapchain_format,
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compute_pipeline = compute_pipelines[0];
|
||||||
|
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
&swapchain_imageviews,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&device,
|
||||||
|
command_pool,
|
||||||
|
graphics_pipeline,
|
||||||
|
&swapchain_framebuffers,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
||||||
|
VulkanApp {
|
||||||
|
// winit stuff
|
||||||
|
window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: entry,
|
||||||
|
instance,
|
||||||
|
surface: surface_stuff.surface,
|
||||||
|
surface_loader: surface_stuff.surface_loader,
|
||||||
|
debug_utils_loader,
|
||||||
|
debug_merssager,
|
||||||
|
|
||||||
|
physical_device,
|
||||||
|
device,
|
||||||
|
|
||||||
|
queue_family,
|
||||||
|
graphics_queue,
|
||||||
|
present_queue,
|
||||||
|
compute_queue,
|
||||||
|
|
||||||
|
swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
swapchain: swapchain_stuff.swapchain,
|
||||||
|
swapchain_format: swapchain_stuff.swapchain_format,
|
||||||
|
swapchain_images: swapchain_stuff.swapchain_images,
|
||||||
|
swapchain_extent: swapchain_stuff.swapchain_extent,
|
||||||
|
swapchain_imageviews,
|
||||||
|
swapchain_framebuffers,
|
||||||
|
|
||||||
|
graphics_pipeline_layout,
|
||||||
|
render_pass,
|
||||||
|
graphics_pipeline,
|
||||||
|
|
||||||
|
|
||||||
|
compute_descriptor_sets,
|
||||||
|
compute_pipeline_layout,
|
||||||
|
compute_pipeline,
|
||||||
|
|
||||||
|
vertex_buffer,
|
||||||
|
vertex_buffer_memory,
|
||||||
|
|
||||||
|
command_pool,
|
||||||
|
command_buffers,
|
||||||
|
|
||||||
|
image_available_semaphores: sync_ojbects.image_available_semaphores,
|
||||||
|
render_finished_semaphores: sync_ojbects.render_finished_semaphores,
|
||||||
|
in_flight_fences: sync_ojbects.inflight_fences,
|
||||||
|
current_frame: 0,
|
||||||
|
|
||||||
|
is_framebuffer_resized: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main_loop(self) {
|
||||||
|
let mut tick_counter = super::fps_limiter::FPSLimiter::new();
|
||||||
|
|
||||||
|
self.event_loop
|
||||||
|
.run(move |event, _, control_flow| match event {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
|
WindowEvent::CloseRequested => {
|
||||||
|
vulkan_app.wait_device_idle();
|
||||||
|
*control_flow = ControlFlow::Exit
|
||||||
|
}
|
||||||
|
WindowEvent::KeyboardInput { input, .. } => match input {
|
||||||
|
KeyboardInput {
|
||||||
|
virtual_keycode,
|
||||||
|
state,
|
||||||
|
..
|
||||||
|
} => match (virtual_keycode, state) {
|
||||||
|
(Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
||||||
|
vulkan_app.wait_device_idle();
|
||||||
|
*control_flow = ControlFlow::Exit
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WindowEvent::Resized(_new_size) => {
|
||||||
|
vulkan_app.wait_device_idle();
|
||||||
|
vulkan_app.resize_framebuffer();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Event::MainEventsCleared => {
|
||||||
|
vulkan_app.window_ref().request_redraw();
|
||||||
|
}
|
||||||
|
Event::RedrawRequested(_window_id) => {
|
||||||
|
let delta_time = tick_counter.delta_time();
|
||||||
|
vulkan_app.draw_frame(delta_time);
|
||||||
|
|
||||||
|
if IS_PAINT_FPS_COUNTER {
|
||||||
|
print!("FPS: {}\r", tick_counter.fps());
|
||||||
|
}
|
||||||
|
|
||||||
|
tick_counter.tick_frame();
|
||||||
|
}
|
||||||
|
Event::LoopDestroyed => {
|
||||||
|
vulkan_app.wait_device_idle();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_vertex_buffer(
|
||||||
|
instance: &ash::Instance,
|
||||||
|
device: &ash::Device,
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
) -> (vk::Buffer, vk::DeviceMemory) {
|
||||||
|
let vertex_buffer_create_info = vk::BufferCreateInfo {
|
||||||
|
s_type: vk::StructureType::BUFFER_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::BufferCreateFlags::empty(),
|
||||||
|
size: std::mem::size_of_val(&TRI_VERT_DATA) as u64,
|
||||||
|
usage: vk::BufferUsageFlags::VERTEX_BUFFER
|
||||||
|
| vk::BufferUsageFlags::STORAGE_BUFFER
|
||||||
|
| vk::BufferUsageFlags::TRANSFER_DST,
|
||||||
|
sharing_mode: vk::SharingMode::EXCLUSIVE,
|
||||||
|
queue_family_index_count: 0,
|
||||||
|
p_queue_family_indices: ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertex_buffer = unsafe {
|
||||||
|
device
|
||||||
|
.create_buffer(&vertex_buffer_create_info, None)
|
||||||
|
.expect("Failed to create Vertex Buffer")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mem_requirements = unsafe { device.get_buffer_memory_requirements(vertex_buffer) };
|
||||||
|
let mem_properties =
|
||||||
|
unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||||
|
let required_memory_flags: vk::MemoryPropertyFlags =
|
||||||
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT;
|
||||||
|
let memory_type = VulkanApp::find_memory_type(
|
||||||
|
mem_requirements.memory_type_bits,
|
||||||
|
required_memory_flags,
|
||||||
|
mem_properties,
|
||||||
|
);
|
||||||
|
|
||||||
|
let allocate_info = vk::MemoryAllocateInfo {
|
||||||
|
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
allocation_size: mem_requirements.size,
|
||||||
|
memory_type_index: memory_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertex_buffer_memory = unsafe {
|
||||||
|
device
|
||||||
|
.allocate_memory(&allocate_info, None)
|
||||||
|
.expect("Failed to allocate vertex buffer memory!")
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device
|
||||||
|
.bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0)
|
||||||
|
.expect("Failed to bind Buffer");
|
||||||
|
|
||||||
|
let data_ptr = device
|
||||||
|
.map_memory(
|
||||||
|
vertex_buffer_memory,
|
||||||
|
0,
|
||||||
|
vertex_buffer_create_info.size,
|
||||||
|
vk::MemoryMapFlags::empty(),
|
||||||
|
)
|
||||||
|
.expect("Failed to Map Memory") as *mut Vertex;
|
||||||
|
|
||||||
|
data_ptr.copy_from_nonoverlapping(TRI_VERT_DATA.as_ptr(), TRI_VERT_DATA.len());
|
||||||
|
|
||||||
|
device.unmap_memory(vertex_buffer_memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
(vertex_buffer, vertex_buffer_memory)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_memory_type(
|
||||||
|
type_filter: u32,
|
||||||
|
required_properties: vk::MemoryPropertyFlags,
|
||||||
|
mem_properties: vk::PhysicalDeviceMemoryProperties,
|
||||||
|
) -> u32 {
|
||||||
|
for (i, memory_type) in mem_properties.memory_types.iter().enumerate() {
|
||||||
|
//if (type_filter & (1 << i)) > 0 && (memory_type.property_flags & required_properties) == required_properties {
|
||||||
|
// return i as u32
|
||||||
|
// }
|
||||||
|
|
||||||
|
// same implementation
|
||||||
|
if (type_filter & (1 << i)) > 0
|
||||||
|
&& memory_type.property_flags.contains(required_properties)
|
||||||
|
{
|
||||||
|
return i as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Failed to find suitable memory type!")
|
||||||
|
share::pick_physical_device(&instance, &surface_stuff, &DEVICE_EXTENSIONS);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* IDEK WHERE THIS CAME FROM I FUCKED UP THIS FILE, SHITS WHACK
|
||||||
|
* let (device, queue_family) = share::create_logical_device(
|
||||||
|
&instance,
|
||||||
|
physical_device,
|
||||||
|
&VALIDATION,
|
||||||
|
&DEVICE_EXTENSIONS,
|
||||||
|
&surface_stuff,
|
||||||
|
);
|
||||||
|
let graphics_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.graphics_family.unwrap(), 0) };
|
||||||
|
let present_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.present_family.unwrap(), 0) };
|
||||||
|
let compute_queue =
|
||||||
|
unsafe { device.get_device_queue(queue_family.compute_family.unwrap(), 0) };
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
physical_device,
|
||||||
|
&window,
|
||||||
|
&surface_stuff,
|
||||||
|
&queue_family,
|
||||||
|
);
|
||||||
|
let swapchain_imageviews = share::create_image_views(
|
||||||
|
&device,
|
||||||
|
swapchain_stuff.swapchain_format,
|
||||||
|
&swapchain_stuff.swapchain_images,
|
||||||
|
);
|
||||||
|
let render_pass = share::create_render_pass(&device, swapchain_stuff.swapchain_format);
|
||||||
|
let (graphics_pipeline, graphics_pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let (compute_pipelines, compute_pipeline_layout) = VulkanApp::create_compute_pipelines(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compute_pipeline = compute_pipelines[0];
|
||||||
|
|
||||||
|
let swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&device,
|
||||||
|
render_pass,
|
||||||
|
&swapchain_imageviews,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
let command_pool = share::create_command_pool(&device, &queue_family);
|
||||||
|
let (vertex_buffer, vertex_buffer_memory) =
|
||||||
|
VulkanApp::create_vertex_buffer(&instance, &device, physical_device);
|
||||||
|
let command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&device,
|
||||||
|
command_pool,
|
||||||
|
graphics_pipeline,
|
||||||
|
&swapchain_framebuffers,
|
||||||
|
render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
vertex_buffer,
|
||||||
|
);
|
||||||
|
let sync_ojbects = SyncObjects::new(&device, MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
|
// cleanup(); the 'drop' function will take care of it.
|
||||||
|
VulkanApp {
|
||||||
|
// winit stuff
|
||||||
|
window,
|
||||||
|
|
||||||
|
// vulkan stuff
|
||||||
|
_entry: entry,
|
||||||
|
instance,
|
||||||
|
surface: surface_stuff.surface,
|
||||||
|
surface_loader: surface_stuff.surface_loader,
|
||||||
|
debug_utils_loader,
|
||||||
|
debug_merssager,
|
||||||
|
|
||||||
|
physical_device,
|
||||||
|
device,
|
||||||
|
|
||||||
|
queue_family,
|
||||||
|
graphics_queue,
|
||||||
|
present_queue,
|
||||||
|
compute_queue,
|
||||||
|
|
||||||
|
swapchain_loader: swapchain_stuff.swapchain_loader,
|
||||||
|
swapchain: swapchain_stuff.swapchain,
|
||||||
|
swapchain_format: swapchain_stuff.swapchain_format,
|
||||||
|
swapchain_images: swapchain_stuff.swapchain_images,
|
||||||
|
swapchain_extent: swapchain_stuff.swapchain_extent,
|
||||||
|
swapchain_imageviews,
|
||||||
|
swapchain_framebuffers,
|
||||||
|
|
||||||
|
graphics_pipeline_layout,
|
||||||
|
render_pass,
|
||||||
|
graphics_pipeline,
|
||||||
|
|
||||||
|
|
||||||
|
compute_descriptor_set,
|
||||||
|
compute_pipeline_layout,
|
||||||
|
compute_pipeline,*/
|
||||||
|
|
||||||
|
|
||||||
|
/* FUCKED UP GRAPHICS PIPELINE CREATION FUNCTION WITH INTEGRATED COMPUTE PIPELINE CCREATION, THIS
|
||||||
|
* IS SUPER FUCKED
|
||||||
|
command_pool: vk::CommandPool,
|
||||||
|
graphics_pipeline: vk::Pipeline,
|
||||||
|
framebuffers: &Vec<vk::Framebuffer>,
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
surface_extent: vk::Extent2D,
|
||||||
|
vertex_buffer: vk::Buffer,
|
||||||
|
) -> Vec<vk::CommandBuffer> {
|
||||||
|
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo {
|
||||||
|
s_type: vk::StructureType::COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
command_buffer_count: framebuffers.len() as u32,
|
||||||
|
command_pool,
|
||||||
|
level: vk::CommandBufferLevel::PRIMARY,
|
||||||
|
};
|
||||||
|
|
||||||
|
let command_buffers = unsafe {
|
||||||
|
device
|
||||||
|
.allocate_command_buffers(&command_buffer_allocate_info)
|
||||||
|
.expect("Failed to allocate Command Buffers!")
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i, &command_buffer) in command_buffers.iter().enumerate() {
|
||||||
|
let command_buffer_begin_info = vk::CommandBufferBeginInfo {
|
||||||
|
s_type: vk::StructureType::COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::CommandBufferUsageFlags::SIMULTANEOUS_USE,
|
||||||
|
p_inheritance_info: ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device
|
||||||
|
.begin_command_buffer(command_buffer, &command_buffer_begin_info)
|
||||||
|
.expect("Failed to begin recording Command Buffer at beginning!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let clear_values = [vk::ClearValue {
|
||||||
|
color: vk::ClearColorValue {
|
||||||
|
float32: [0.0, 0.0, 0.0, 1.0],
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
|
||||||
|
let render_pass_begin_info = vk::RenderPassBeginInfo {
|
||||||
|
s_type: vk::StructureType::RENDER_PASS_BEGIN_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
framebuffer: framebuffers[i],
|
||||||
|
render_pass,
|
||||||
|
clear_value_count: clear_values.len() as u32,
|
||||||
|
p_clear_values: clear_values.as_ptr(),
|
||||||
|
render_area: vk::Rect2D {
|
||||||
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
|
extent: surface_extent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device.cmd_begin_render_pass(
|
||||||
|
command_buffer,
|
||||||
|
&render_pass_begin_info,
|
||||||
|
vk::SubpassContents::INLINE,
|
||||||
|
);
|
||||||
|
device.cmd_bind_pipeline(
|
||||||
|
command_buffer,
|
||||||
|
vk::PipelineBindPoint::GRAPHICS,
|
||||||
|
graphics_pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
|
let vertex_buffers = [vertex_buffer];
|
||||||
|
let offsets = [0_u64];
|
||||||
|
|
||||||
|
device.cmd_bind_vertex_buffers(command_buffer, 0, &vertex_buffers, &offsets);
|
||||||
|
|
||||||
|
device.cmd_draw(command_buffer, TRI_VERT_DATA.len() as u32, 1, 0, 0);
|
||||||
|
|
||||||
|
device.cmd_end_render_pass(command_buffer);
|
||||||
|
|
||||||
|
device
|
||||||
|
.end_command_buffer(command_buffer)
|
||||||
|
.expect("Failed to record Command Buffer at Ending!");
|
||||||
|
}
|
||||||
|
shader_modules.push(vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
});
|
||||||
|
} else if stage_flag == vk::ShaderStageFlags::FRAGMENT {
|
||||||
|
shader_modules.push(
|
||||||
|
vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if stage_flag == vk::ShaderStageFlags::VERTEX {
|
||||||
|
shader_modules.push(
|
||||||
|
vk::PipelineShaderStageCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
|
module: share::create_shader_module(device, shader),
|
||||||
|
p_name: main_function.as_ptr(),
|
||||||
|
stage: stage_flag,
|
||||||
|
p_specialization_info: ptr::null(),
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let binding_description = Vertex::get_binding_description();
|
||||||
|
let attribute_description = Vertex::get_attribute_descriptions();
|
||||||
|
|
||||||
|
let vertex_input_state_create_info = vk::PipelineVertexInputStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineVertexInputStateCreateFlags::empty(),
|
||||||
|
vertex_attribute_description_count: attribute_description.len() as u32,
|
||||||
|
p_vertex_attribute_descriptions: attribute_description.as_ptr(),
|
||||||
|
vertex_binding_description_count: binding_description.len() as u32,
|
||||||
|
p_vertex_binding_descriptions: binding_description.as_ptr(),
|
||||||
|
};
|
||||||
|
let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
flags: vk::PipelineInputAssemblyStateCreateFlags::empty(),
|
||||||
|
p_next: ptr::null(),
|
||||||
|
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
|
||||||
|
primitive_restart_enable: vk::FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let viewports = [vk::Viewport {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: swapchain_extent.width as f32,
|
||||||
|
height: swapchain_extent.height as f32,
|
||||||
|
min_depth: 0.0,
|
||||||
|
max_depth: 1.0,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let scissors = [vk::Rect2D {
|
||||||
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
|
extent: swapchain_extent,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let viewport_state_create_info = vk::PipelineViewportStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineViewportStateCreateFlags::empty(),
|
||||||
|
scissor_count: scissors.len() as u32,
|
||||||
|
p_scissors: scissors.as_ptr(),
|
||||||
|
viewport_count: viewports.len() as u32,
|
||||||
|
p_viewports: viewports.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
p_viewports: viewports.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rasterization_statue_create_info = vk::PipelineRasterizationStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineRasterizationStateCreateFlags::empty(),
|
||||||
|
cull_mode: vk::CullModeFlags::BACK,
|
||||||
|
front_face: vk::FrontFace::CLOCKWISE,
|
||||||
|
line_width: 1.0,
|
||||||
|
polygon_mode: vk::PolygonMode::FILL,
|
||||||
|
rasterizer_discard_enable: vk::FALSE,
|
||||||
|
depth_clamp_enable: vk::FALSE,
|
||||||
|
depth_bias_clamp: 0.0,
|
||||||
|
depth_bias_constant_factor: 0.0,
|
||||||
|
depth_bias_enable: vk::FALSE,
|
||||||
|
depth_bias_slope_factor: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let multisample_state_create_info = vk::PipelineMultisampleStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
flags: vk::PipelineMultisampleStateCreateFlags::empty(),
|
||||||
|
p_next: ptr::null(),
|
||||||
|
rasterization_samples: vk::SampleCountFlags::TYPE_1,
|
||||||
|
sample_shading_enable: vk::FALSE,
|
||||||
|
min_sample_shading: 0.0,
|
||||||
|
p_sample_mask: ptr::null(),
|
||||||
|
alpha_to_one_enable: vk::FALSE,
|
||||||
|
alpha_to_coverage_enable: vk::FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
let stencil_state = vk::StencilOpState {
|
||||||
|
fail_op: vk::StencilOp::KEEP,
|
||||||
|
pass_op: vk::StencilOp::KEEP,
|
||||||
|
depth_fail_op: vk::StencilOp::KEEP,
|
||||||
|
compare_op: vk::CompareOp::ALWAYS,
|
||||||
|
compare_mask: 0,
|
||||||
|
write_mask: 0,
|
||||||
|
reference: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let depth_state_create_info = vk::PipelineDepthStencilStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineDepthStencilStateCreateFlags::empty(),
|
||||||
|
depth_test_enable: vk::FALSE,
|
||||||
|
depth_write_enable: vk::FALSE,
|
||||||
|
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
||||||
|
depth_bounds_test_enable: vk::FALSE,
|
||||||
|
stencil_test_enable: vk::FALSE,
|
||||||
|
front: stencil_state,
|
||||||
|
back: stencil_state,
|
||||||
|
max_depth_bounds: 1.0,
|
||||||
|
min_depth_bounds: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
|
||||||
|
blend_enable: vk::FALSE,
|
||||||
|
color_write_mask: vk::ColorComponentFlags::RGBA,
|
||||||
|
src_color_blend_factor: vk::BlendFactor::ONE,
|
||||||
|
dst_color_blend_factor: vk::BlendFactor::ZERO,
|
||||||
|
color_blend_op: vk::BlendOp::ADD,
|
||||||
|
src_alpha_blend_factor: vk::BlendFactor::ONE,
|
||||||
|
dst_alpha_blend_factor: vk::BlendFactor::ZERO,
|
||||||
|
alpha_blend_op: vk::BlendOp::ADD,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let color_blend_state = vk::PipelineColorBlendStateCreateInfo {
|
||||||
|
s_type: vk::StructureType::PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineColorBlendStateCreateFlags::empty(),
|
||||||
|
logic_op_enable: vk::FALSE,
|
||||||
|
logic_op: vk::LogicOp::COPY,
|
||||||
|
attachment_count: color_blend_attachment_states.len() as u32,
|
||||||
|
p_attachments: color_blend_attachment_states.as_ptr(),
|
||||||
|
blend_constants: [0.0, 0.0, 0.0, 0.0],
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("shader module count: {}", shader_modules.len());
|
||||||
|
|
||||||
|
let graphic_pipeline_create_infos = [vk::GraphicsPipelineCreateInfo {
|
||||||
|
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
flags: vk::PipelineCreateFlags::empty(),
|
||||||
|
stage_count: shader_modules.len() as u32,
|
||||||
|
p_stages: shader_modules.as_ptr(),
|
||||||
|
p_vertex_input_state: &vertex_input_state_create_info,
|
||||||
|
p_input_assembly_state: &vertex_input_assembly_state_info,
|
||||||
|
p_tessellation_state: ptr::null(),
|
||||||
|
p_viewport_state: &viewport_state_create_info,
|
||||||
|
p_rasterization_state: &rasterization_statue_create_info,
|
||||||
|
p_multisample_state: &multisample_state_create_info,
|
||||||
|
s_type: vk::StructureType::COMPUTE_PIPELINE_CREATE_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
layout: pipeline_layout,
|
||||||
|
flags: vk::PipelineCreateFlags::empty(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
let compute_pipelines = unsafe {
|
||||||
|
device
|
||||||
|
.create_compute_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
&compute_infos,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}.unwrap();
|
||||||
|
|
||||||
|
(compute_pipelines, pipeline_layout)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fn draw_frame(&mut self) {
|
||||||
|
let wait_fences = [self.in_flight_fences[self.current_frame]];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.wait_for_fences(&wait_fences, true, std::u64::MAX)
|
||||||
|
.expect("Failed to wait for Fence!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (image_index, _is_sub_optimal) = unsafe {
|
||||||
|
let result = self.swapchain_loader.acquire_next_image(
|
||||||
|
self.swapchain,
|
||||||
|
std::u64::MAX,
|
||||||
|
self.image_available_semaphores[self.current_frame],
|
||||||
|
vk::Fence::null(),
|
||||||
|
);
|
||||||
|
match result {
|
||||||
|
Ok(image_index) => image_index,
|
||||||
|
Err(vk_result) => match vk_result {
|
||||||
|
vk::Result::ERROR_OUT_OF_DATE_KHR => {
|
||||||
|
self.recreate_swapchain();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => panic!("Failed to acquire Swap Chain Image!"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let wait_semaphores = [self.image_available_semaphores[self.current_frame]];
|
||||||
|
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
||||||
|
let signal_semaphores = [self.render_finished_semaphores[self.current_frame]];
|
||||||
|
|
||||||
|
let submit_infos = [vk::SubmitInfo {
|
||||||
|
s_type: vk::StructureType::SUBMIT_INFO,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
wait_semaphore_count: wait_semaphores.len() as u32,
|
||||||
|
p_wait_semaphores: wait_semaphores.as_ptr(),
|
||||||
|
p_wait_dst_stage_mask: wait_stages.as_ptr(),
|
||||||
|
command_buffer_count: 1,
|
||||||
|
p_command_buffers: &self.command_buffers[image_index as usize],
|
||||||
|
signal_semaphore_count: signal_semaphores.len() as u32,
|
||||||
|
p_signal_semaphores: signal_semaphores.as_ptr(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.reset_fences(&wait_fences)
|
||||||
|
.expect("Failed to reset Fence!");
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.queue_submit(
|
||||||
|
self.graphics_queue,
|
||||||
|
&submit_infos,
|
||||||
|
self.in_flight_fences[self.current_frame],
|
||||||
|
)
|
||||||
|
.expect("Failed to execute queue submit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
let swapchains = [self.swapchain];
|
||||||
|
|
||||||
|
let present_info = vk::PresentInfoKHR {
|
||||||
|
s_type: vk::StructureType::PRESENT_INFO_KHR,
|
||||||
|
p_next: ptr::null(),
|
||||||
|
wait_semaphore_count: 1,
|
||||||
|
p_wait_semaphores: signal_semaphores.as_ptr(),
|
||||||
|
swapchain_count: 1,
|
||||||
|
p_swapchains: swapchains.as_ptr(),
|
||||||
|
p_image_indices: &image_index,
|
||||||
|
p_results: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
self.swapchain_loader
|
||||||
|
.queue_present(self.present_queue, &present_info)
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_resized = match result {
|
||||||
|
Ok(_) => self.is_framebuffer_resized,
|
||||||
|
Err(vk_result) => match vk_result {
|
||||||
|
vk::Result::ERROR_OUT_OF_DATE_KHR | vk::Result::SUBOPTIMAL_KHR => true,
|
||||||
|
_ => panic!("Failed to execute queue present."),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if is_resized {
|
||||||
|
self.is_framebuffer_resized = false;
|
||||||
|
self.recreate_swapchain();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_frame = (self.current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recreate_swapchain(&mut self) {
|
||||||
|
// parameters -------------
|
||||||
|
let surface_suff = SurfaceStuff {
|
||||||
|
surface_loader: self.surface_loader.clone(),
|
||||||
|
surface: self.surface,
|
||||||
|
screen_width: WINDOW_WIDTH,
|
||||||
|
screen_height: WINDOW_HEIGHT,
|
||||||
|
};
|
||||||
|
// ------------------------
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.device_wait_idle()
|
||||||
|
.expect("Failed to wait device idle!")
|
||||||
|
};
|
||||||
|
self.cleanup_swapchain();
|
||||||
|
|
||||||
|
let swapchain_stuff = SwapChainStuff::new(
|
||||||
|
&self.instance,
|
||||||
|
&self.device,
|
||||||
|
self.physical_device,
|
||||||
|
&self.window,
|
||||||
|
&surface_suff,
|
||||||
|
&self.queue_family,
|
||||||
|
);
|
||||||
|
self.swapchain_loader = swapchain_stuff.swapchain_loader;
|
||||||
|
self.swapchain = swapchain_stuff.swapchain;
|
||||||
|
self.swapchain_images = swapchain_stuff.swapchain_images;
|
||||||
|
self.swapchain_format = swapchain_stuff.swapchain_format;
|
||||||
|
self.swapchain_extent = swapchain_stuff.swapchain_extent;
|
||||||
|
|
||||||
|
self.swapchain_imageviews =
|
||||||
|
share::create_image_views(&self.device, self.swapchain_format, &self.swapchain_images);
|
||||||
|
self.render_pass = share::create_render_pass(&self.device, self.swapchain_format);
|
||||||
|
let (graphics_pipeline, pipeline_layout) = VulkanApp::create_graphics_pipeline(
|
||||||
|
&self.device,
|
||||||
|
self.render_pass,
|
||||||
|
swapchain_stuff.swapchain_extent,
|
||||||
|
);
|
||||||
|
self.graphics_pipeline = graphics_pipeline;
|
||||||
|
self.graphics_pipeline_layout = pipeline_layout;
|
||||||
|
|
||||||
|
self.swapchain_framebuffers = share::create_framebuffers(
|
||||||
|
&self.device,
|
||||||
|
self.render_pass,
|
||||||
|
&self.swapchain_imageviews,
|
||||||
|
self.swapchain_extent,
|
||||||
|
);
|
||||||
|
self.command_buffers = VulkanApp::create_command_buffers(
|
||||||
|
&self.device,
|
||||||
|
self.command_pool,
|
||||||
|
self.graphics_pipeline,
|
||||||
|
&self.swapchain_framebuffers,
|
||||||
|
self.render_pass,
|
||||||
|
self.swapchain_extent,
|
||||||
|
self.vertex_buffer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cleanup_swapchain(&self) {
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.free_command_buffers(self.command_pool, &self.command_buffers);
|
||||||
|
for &framebuffer in self.swapchain_framebuffers.iter() {
|
||||||
|
self.device.destroy_framebuffer(framebuffer, None);
|
||||||
|
}
|
||||||
|
self.device.destroy_pipeline(self.graphics_pipeline, None);
|
||||||
|
self.device
|
||||||
|
.destroy_pipeline_layout(self.graphics_pipeline_layout, None);
|
||||||
|
self.device.destroy_render_pass(self.render_pass, None);
|
||||||
|
for &image_view in self.swapchain_imageviews.iter() {
|
||||||
|
self.device.destroy_image_view(image_view, None);
|
||||||
|
}
|
||||||
|
self.swapchain_loader
|
||||||
|
.destroy_swapchain(self.swapchain, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl Drop for VulkanApp {
|
||||||
|
//cleanup in C++
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
for i in 0..MAX_FRAMES_IN_FLIGHT {
|
||||||
|
self.device
|
||||||
|
.destroy_semaphore(self.image_available_semaphores[i], None);
|
||||||
|
self.device
|
||||||
|
.destroy_semaphore(self.render_finished_semaphores[i], None);
|
||||||
|
self.device.destroy_fence(self.in_flight_fences[i], None);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cleanup_swapchain();
|
||||||
|
|
||||||
|
self.device
|
||||||
|
.destory
|
||||||
|
|
||||||
|
self.device.destroy_buffer(self.vertex_buffer, None);
|
||||||
|
self.device.free_memory(self.vertex_buffer_memory, None);
|
||||||
|
|
||||||
|
self.device.destroy_command_pool(self.command_pool, None);
|
||||||
|
|
||||||
|
self.device.destroy_device(None);
|
||||||
|
self.surface_loader.destroy_surface(self.surface, None);
|
||||||
|
|
||||||
|
if VALIDATION.is_enable {
|
||||||
|
self.debug_utils_loader
|
||||||
|
.destroy_debug_utils_messenger(self.debug_merssager, None);
|
||||||
|
}
|
||||||
|
self.instance.destroy_instance(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,40 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#extension GL_ARB_separate_shader_objects: enable
|
|
||||||
|
|
||||||
struct Particle {
|
struct Particle {
|
||||||
vec2 position;
|
vec2 position;
|
||||||
vec2 velocity;
|
vec2 velocity;
|
||||||
vec4 color;
|
vec4 color;
|
||||||
}
|
};
|
||||||
|
|
||||||
layout (std140, binding = 1) readonly buffer ParticleSSBOIn {
|
layout (binding = 0) uniform ParameterUBO {
|
||||||
|
float deltaTime;
|
||||||
|
} ubo;
|
||||||
|
|
||||||
|
layout(std140, binding = 1) readonly buffer ParticleSSBOIn {
|
||||||
Particle particlesIn[ ];
|
Particle particlesIn[ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (std140, binding = 2) buffer ParticleSSBOOut {
|
layout(std140, binding = 2) buffer ParticleSSBOOut {
|
||||||
Particle particlesOut[ ];
|
Particle particlesOut[ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||||
particlesOut[index].position = particlesIn[index].position + particlesIn[index].velocity.xy * ubo.deltaTime;
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint index = gl_GlobalInvocationID.x;
|
||||||
|
|
||||||
|
Particle particleIn = particlesIn[index];
|
||||||
|
|
||||||
|
particlesOut[index].position = particleIn.position + particleIn.velocity.xy * ubo.deltaTime;
|
||||||
|
particlesOut[index].velocity = particleIn.velocity;
|
||||||
|
|
||||||
|
// Flip movement at window border
|
||||||
|
if ((particlesOut[index].position.x <= -1.0) || (particlesOut[index].position.x >= 1.0)) {
|
||||||
|
particlesOut[index].velocity.x = -particlesOut[index].velocity.x;
|
||||||
|
}
|
||||||
|
if ((particlesOut[index].position.y <= -1.0) || (particlesOut[index].position.y >= 1.0)) {
|
||||||
|
particlesOut[index].velocity.y = -particlesOut[index].velocity.y;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,88 +0,0 @@
|
|||||||
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
|
||||||
|
|
||||||
const IS_PAINT_FPS_COUNTER: bool = true;
|
|
||||||
|
|
||||||
pub fn init_window(
|
|
||||||
event_loop: &EventLoop<()>,
|
|
||||||
title: &str,
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
) -> winit::window::Window {
|
|
||||||
winit::window::WindowBuilder::new()
|
|
||||||
.with_title(title)
|
|
||||||
.with_inner_size(winit::dpi::LogicalSize::new(width, height))
|
|
||||||
.build(event_loop)
|
|
||||||
.expect("Failed to create window.")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait VulkanApp {
|
|
||||||
fn draw_frame(&mut self, delta_time: f32);
|
|
||||||
fn recreate_swapchain(&mut self);
|
|
||||||
fn cleanup_swapchain(&self);
|
|
||||||
fn wait_device_idle(&self);
|
|
||||||
fn resize_framebuffer(&mut self);
|
|
||||||
fn window_ref(&self) -> &winit::window::Window;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ProgramProc {
|
|
||||||
pub event_loop: EventLoop<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ProgramProc {
|
|
||||||
pub fn new() -> ProgramProc {
|
|
||||||
// init window stuff
|
|
||||||
let event_loop = EventLoop::new();
|
|
||||||
|
|
||||||
ProgramProc { event_loop }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main_loop<A: 'static + VulkanApp>(self, mut vulkan_app: A) {
|
|
||||||
let mut tick_counter = super::fps_limiter::FPSLimiter::new();
|
|
||||||
|
|
||||||
self.event_loop
|
|
||||||
.run(move |event, _, control_flow| match event {
|
|
||||||
Event::WindowEvent { event, .. } => match event {
|
|
||||||
WindowEvent::CloseRequested => {
|
|
||||||
vulkan_app.wait_device_idle();
|
|
||||||
*control_flow = ControlFlow::Exit
|
|
||||||
}
|
|
||||||
WindowEvent::KeyboardInput { input, .. } => match input {
|
|
||||||
KeyboardInput {
|
|
||||||
virtual_keycode,
|
|
||||||
state,
|
|
||||||
..
|
|
||||||
} => match (virtual_keycode, state) {
|
|
||||||
(Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
|
||||||
vulkan_app.wait_device_idle();
|
|
||||||
*control_flow = ControlFlow::Exit
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
WindowEvent::Resized(_new_size) => {
|
|
||||||
vulkan_app.wait_device_idle();
|
|
||||||
vulkan_app.resize_framebuffer();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
Event::MainEventsCleared => {
|
|
||||||
vulkan_app.window_ref().request_redraw();
|
|
||||||
}
|
|
||||||
Event::RedrawRequested(_window_id) => {
|
|
||||||
let delta_time = tick_counter.delta_time();
|
|
||||||
vulkan_app.draw_frame(delta_time);
|
|
||||||
|
|
||||||
if IS_PAINT_FPS_COUNTER {
|
|
||||||
print!("FPS: {}\r", tick_counter.fps());
|
|
||||||
}
|
|
||||||
|
|
||||||
tick_counter.tick_frame();
|
|
||||||
}
|
|
||||||
Event::LoopDestroyed => {
|
|
||||||
vulkan_app.wait_device_idle();
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue