Compare commits
2 Commits
1d23169dcc
...
0029f39840
Author | SHA1 | Date | |
---|---|---|---|
0029f39840 | |||
a6caf232d9 |
@ -5,7 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
winit = "0.20.0"
|
winit = "0.20.0"
|
||||||
ash = "0.29.0"
|
ash = "0.37.3"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
cgmath = "0.17.0"
|
cgmath = "0.17.0"
|
||||||
image = "0.22"
|
image = "0.22"
|
||||||
|
53
build.rs
53
build.rs
@ -1,48 +1,65 @@
|
|||||||
use std::process::Command;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
println!("building shaders...");
|
println!("building shaders...");
|
||||||
//shaders path
|
//shaders path
|
||||||
let shaders = Path::new("./src/shaders");
|
let shaders = Path::new("./src/shaders");
|
||||||
//shader target path
|
//shader target path
|
||||||
let out = Command::new("mkdir")
|
let out = Command::new("mkdir").arg("target/shaders/").output();
|
||||||
.arg("target/shaders/")
|
|
||||||
.output();
|
|
||||||
|
|
||||||
let shader_target = Path::new("./target/shaders/");
|
let shader_target = Path::new("./target/shaders/");
|
||||||
//compile all glsl shaders
|
//compile all glsl shaders
|
||||||
for entry in shaders.read_dir().expect("reading shader directory failed") {
|
for entry in shaders.read_dir().expect("reading shader directory failed") {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
let shader_path = entry.path();
|
let shader_path = entry.path();
|
||||||
println!("compiling shader: {:?}", shader_path);
|
println!("compiling shader: {:?}", shader_path);
|
||||||
let shader_path_string: String = "./target/shaders/".to_string() + shader_path.file_name().unwrap().to_str().unwrap() + ".spv";
|
let shader_path_string: String = "./target/shaders/".to_string()
|
||||||
let shader_file: &OsStr = OsStr::new::<str>(shader_path_string.as_str());
|
+ shader_path.file_name().unwrap().to_str().unwrap()
|
||||||
let out = Command::new("glslc")
|
+ ".spv";
|
||||||
|
let shader_file: &OsStr = OsStr::new::<str>(shader_path_string.as_str());
|
||||||
|
Command::new("glslc")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(shader_path)
|
.arg(shader_path)
|
||||||
.arg("-o")
|
.arg("-o")
|
||||||
.arg(shader_file)
|
.arg(shader_file)
|
||||||
.output();
|
.status();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//include all compiled shaders in shaders.rs file in src dir
|
//include all compiled shaders in shaders.rs file in src dir
|
||||||
let mut txt: String = String::new();
|
let mut txt = "use ash::vk::ShaderStageFlags;\n\n".to_string()
|
||||||
for entry in shader_target.read_dir().expect("reading compiled shader target directory failed") {
|
+ "pub fn shaders() -> Vec<(Vec<u8>, ShaderStageFlags)> {\nvec![\n";
|
||||||
|
for entry in shader_target
|
||||||
|
.read_dir()
|
||||||
|
.expect("reading compiled shader target directory failed")
|
||||||
|
{
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
let bin_path = entry.path();
|
let bin_path = entry.path();
|
||||||
let bin_path_string = bin_path.file_name().unwrap().to_str().unwrap().to_string();
|
let bin_path_string = bin_path.file_name().unwrap().to_str().unwrap().to_string();
|
||||||
txt += &("const ".to_owned() +
|
|
||||||
&bin_path_string.replace(".spv", "").replace(".", "_").to_uppercase() +
|
let shader_type = (
|
||||||
" = include_bytes!(\"../target/shaders/" +
|
match bin_path_string.split(".").nth(1).unwrap() {
|
||||||
&bin_path_string +
|
"vert" => "VERTEX",
|
||||||
"\");\n");
|
"frag" => "FRAGMENT",
|
||||||
|
"comp" => "COMPUTE",
|
||||||
|
"tesc" => "TESSELLATION_CONTROL",
|
||||||
|
"tese" => "TESSELLATION_EVALUATION",
|
||||||
|
"geom" => "GEOMETRY",
|
||||||
|
_ => panic!("unknown shader type"),
|
||||||
|
}
|
||||||
|
).to_string();
|
||||||
|
txt += &("(include_bytes!(\"../target/shaders/".to_owned()
|
||||||
|
+ &bin_path_string
|
||||||
|
+ "\").to_vec(), ShaderStageFlags::"
|
||||||
|
+ &shader_type
|
||||||
|
+ "),\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
txt += "]}";
|
||||||
let mut file = File::create("./src/shaders.rs")?;
|
let mut file = File::create("./src/shaders.rs")?;
|
||||||
file.write_all(txt.as_bytes())?;
|
file.write_all(txt.as_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
154
src/main.rs
154
src/main.rs
@ -1,24 +1,21 @@
|
|||||||
|
pub mod shaders;
|
||||||
pub mod utility;
|
pub mod utility;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
utility::constants::*,
|
shaders::*, utility::constants::*, utility::debug::*, utility::share, utility::structures::*,
|
||||||
utility::debug::*,
|
|
||||||
utility::share,
|
|
||||||
utility::structures::*,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use ash::version::DeviceV1_0;
|
use ash::{vk, Entry};
|
||||||
use ash::version::InstanceV1_0;
|
|
||||||
use ash::vk;
|
|
||||||
use memoffset::offset_of;
|
use memoffset::offset_of;
|
||||||
use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent};
|
use vk::*;
|
||||||
use winit::event_loop::{EventLoop, ControlFlow};
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const WINDOW_TITLE: &'static str = "18.Vertex Buffer";
|
const WINDOW_TITLE: &'static str = "Template";
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Debug, Copy)]
|
#[derive(Clone, Debug, Copy)]
|
||||||
@ -114,11 +111,11 @@ struct VulkanApp {
|
|||||||
|
|
||||||
impl VulkanApp {
|
impl VulkanApp {
|
||||||
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> VulkanApp {
|
pub fn new(event_loop: &winit::event_loop::EventLoop<()>) -> VulkanApp {
|
||||||
|
let window =
|
||||||
let window = utility::window::init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
utility::window::init_window(event_loop, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
|
||||||
// init vulkan stuff
|
// init vulkan stuff
|
||||||
let entry = ash::Entry::new().unwrap();
|
let entry = unsafe { Entry::load().unwrap() };
|
||||||
let instance = share::create_instance(
|
let instance = share::create_instance(
|
||||||
&entry,
|
&entry,
|
||||||
WINDOW_TITLE,
|
WINDOW_TITLE,
|
||||||
@ -238,7 +235,9 @@ impl VulkanApp {
|
|||||||
p_next: ptr::null(),
|
p_next: ptr::null(),
|
||||||
flags: vk::BufferCreateFlags::empty(),
|
flags: vk::BufferCreateFlags::empty(),
|
||||||
size: std::mem::size_of_val(&VERTICES_DATA) as u64,
|
size: std::mem::size_of_val(&VERTICES_DATA) as u64,
|
||||||
usage: vk::BufferUsageFlags::VERTEX_BUFFER,
|
usage: vk::BufferUsageFlags::VERTEX_BUFFER
|
||||||
|
| vk::BufferUsageFlags::STORAGE_BUFFER
|
||||||
|
| vk::BufferUsageFlags::TRANSFER_DST,
|
||||||
sharing_mode: vk::SharingMode::EXCLUSIVE,
|
sharing_mode: vk::SharingMode::EXCLUSIVE,
|
||||||
queue_family_index_count: 0,
|
queue_family_index_count: 0,
|
||||||
p_queue_family_indices: ptr::null(),
|
p_queue_family_indices: ptr::null(),
|
||||||
@ -411,39 +410,22 @@ impl VulkanApp {
|
|||||||
render_pass: vk::RenderPass,
|
render_pass: vk::RenderPass,
|
||||||
swapchain_extent: vk::Extent2D,
|
swapchain_extent: vk::Extent2D,
|
||||||
) -> (vk::Pipeline, vk::PipelineLayout) {
|
) -> (vk::Pipeline, vk::PipelineLayout) {
|
||||||
let vert_shader_module = share::create_shader_module(
|
let mut shader_modules: Vec<vk::PipelineShaderStageCreateInfo> = vec![];
|
||||||
device,
|
let main_function = CString::new("main").unwrap();
|
||||||
include_bytes!("../target/shaders/tri.vert.spv").to_vec(),
|
for (shader, stage_i) in shaders() {
|
||||||
);
|
shader_modules.push(
|
||||||
let frag_shader_module = share::create_shader_module(
|
vk::PipelineShaderStageCreateInfo {
|
||||||
device,
|
|
||||||
include_bytes!("../target/shaders/tri.frag.spv").to_vec(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let main_function_name = CString::new("main").unwrap(); // the beginning function name in shader code.
|
|
||||||
|
|
||||||
let shader_stages = [
|
|
||||||
vk::PipelineShaderStageCreateInfo {
|
|
||||||
// Vertex Shader
|
|
||||||
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
p_next: ptr::null(),
|
p_next: ptr::null(),
|
||||||
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
||||||
module: vert_shader_module,
|
module: share::create_shader_module(device, shader),
|
||||||
p_name: main_function_name.as_ptr(),
|
p_name: main_function.as_ptr(),
|
||||||
stage: vk::ShaderStageFlags::VERTEX,
|
stage: stage_i,
|
||||||
p_specialization_info: ptr::null(),
|
p_specialization_info: ptr::null(),
|
||||||
},
|
|
||||||
vk::PipelineShaderStageCreateInfo {
|
}
|
||||||
// Fragment Shader
|
)
|
||||||
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
}
|
||||||
p_next: ptr::null(),
|
|
||||||
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
|
||||||
module: frag_shader_module,
|
|
||||||
p_name: main_function_name.as_ptr(),
|
|
||||||
stage: vk::ShaderStageFlags::FRAGMENT,
|
|
||||||
p_specialization_info: ptr::null(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let binding_description = Vertex::get_binding_description();
|
let binding_description = Vertex::get_binding_description();
|
||||||
let attribute_description = Vertex::get_attribute_descriptions();
|
let attribute_description = Vertex::get_attribute_descriptions();
|
||||||
@ -544,7 +526,7 @@ impl VulkanApp {
|
|||||||
|
|
||||||
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
|
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
|
||||||
blend_enable: vk::FALSE,
|
blend_enable: vk::FALSE,
|
||||||
color_write_mask: vk::ColorComponentFlags::all(),
|
color_write_mask: vk::ColorComponentFlags::RGBA,
|
||||||
src_color_blend_factor: vk::BlendFactor::ONE,
|
src_color_blend_factor: vk::BlendFactor::ONE,
|
||||||
dst_color_blend_factor: vk::BlendFactor::ZERO,
|
dst_color_blend_factor: vk::BlendFactor::ZERO,
|
||||||
color_blend_op: vk::BlendOp::ADD,
|
color_blend_op: vk::BlendOp::ADD,
|
||||||
@ -584,8 +566,8 @@ impl VulkanApp {
|
|||||||
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
|
s_type: vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
p_next: ptr::null(),
|
p_next: ptr::null(),
|
||||||
flags: vk::PipelineCreateFlags::empty(),
|
flags: vk::PipelineCreateFlags::empty(),
|
||||||
stage_count: shader_stages.len() as u32,
|
stage_count: shader_modules.len() as u32,
|
||||||
p_stages: shader_stages.as_ptr(),
|
p_stages: shader_modules.as_ptr(),
|
||||||
p_vertex_input_state: &vertex_input_state_create_info,
|
p_vertex_input_state: &vertex_input_state_create_info,
|
||||||
p_input_assembly_state: &vertex_input_assembly_state_info,
|
p_input_assembly_state: &vertex_input_assembly_state_info,
|
||||||
p_tessellation_state: ptr::null(),
|
p_tessellation_state: ptr::null(),
|
||||||
@ -613,8 +595,9 @@ impl VulkanApp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
device.destroy_shader_module(vert_shader_module, None);
|
for shader in shader_modules {
|
||||||
device.destroy_shader_module(frag_shader_module, None);
|
device.destroy_shader_module(shader.module, None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(graphics_pipelines[0], pipeline_layout)
|
(graphics_pipelines[0], pipeline_layout)
|
||||||
@ -823,62 +806,51 @@ impl Drop for VulkanApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl VulkanApp {
|
impl VulkanApp {
|
||||||
|
|
||||||
pub fn main_loop(mut self, event_loop: EventLoop<()>) {
|
pub fn main_loop(mut self, event_loop: EventLoop<()>) {
|
||||||
|
|
||||||
let mut tick_counter = utility::fps_limiter::FPSLimiter::new();
|
let mut tick_counter = utility::fps_limiter::FPSLimiter::new();
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop.run(move |event, _, control_flow| match event {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
match event {
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||||
| Event::WindowEvent { event, .. } => {
|
WindowEvent::KeyboardInput { input, .. } => match input {
|
||||||
match event {
|
KeyboardInput {
|
||||||
| WindowEvent::CloseRequested => {
|
virtual_keycode,
|
||||||
|
state,
|
||||||
|
..
|
||||||
|
} => match (virtual_keycode, state) {
|
||||||
|
(Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
||||||
*control_flow = ControlFlow::Exit
|
*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::MainEventsCleared => {
|
||||||
| Event::RedrawRequested(_window_id) => {
|
self.window.request_redraw();
|
||||||
self.draw_frame();
|
|
||||||
|
|
||||||
tick_counter.tick_frame();
|
|
||||||
if IS_PAINT_FPS_COUNTER {
|
|
||||||
print!("FPS: {}\r", tick_counter.fps());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
| Event::LoopDestroyed => {
|
|
||||||
unsafe {
|
|
||||||
self.device.device_wait_idle()
|
|
||||||
.expect("Failed to wait device idle!")
|
|
||||||
};
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
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!")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
|
|
||||||
let vulkan_app = VulkanApp::new(&event_loop);
|
let vulkan_app = VulkanApp::new(&event_loop);
|
||||||
|
@ -1,2 +1,7 @@
|
|||||||
const TRI_FRAG = include_bytes!("../target/shaders/tri.frag.spv");
|
use ash::vk::ShaderStageFlags;
|
||||||
const TRI_VERT = include_bytes!("../target/shaders/tri.vert.spv");
|
|
||||||
|
pub fn shaders() -> Vec<(Vec<u8>, ShaderStageFlags)> {
|
||||||
|
vec![
|
||||||
|
(include_bytes!("../target/shaders/tri.frag.spv").to_vec(), ShaderStageFlags::FRAGMENT),
|
||||||
|
(include_bytes!("../target/shaders/tri.vert.spv").to_vec(), ShaderStageFlags::VERTEX),
|
||||||
|
]}
|
21
src/shaders/tri.comp
Normal file
21
src/shaders/tri.comp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
#extension GL_ARB_separate_shader_objects: enable
|
||||||
|
|
||||||
|
struct Particle {
|
||||||
|
vec2 position;
|
||||||
|
vec2 velocity;
|
||||||
|
vec4 color;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout (std140, binding = 1) readonly buffer ParticleSSBOIn {
|
||||||
|
Particle particlesIn[ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (std140, binding = 2) buffer ParticleSSBOOut {
|
||||||
|
Particle particlesOut[ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
particlesOut[index].position = particlesIn[index].position + particlesIn[index].velocity.xy * ubo.deltaTime;
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
use crate::utility::debug::ValidationInfo;
|
use crate::utility::debug::ValidationInfo;
|
||||||
use crate::utility::structures::DeviceExtension;
|
use crate::utility::structures::DeviceExtension;
|
||||||
use ash::vk_make_version;
|
use ash::vk::make_api_version;
|
||||||
|
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
pub const APPLICATION_VERSION: u32 = vk_make_version!(1, 0, 0);
|
pub const APPLICATION_VERSION: u32 = make_api_version(1, 0, 0, 0);
|
||||||
pub const ENGINE_VERSION: u32 = vk_make_version!(1, 0, 0);
|
pub const ENGINE_VERSION: u32 = make_api_version(1, 0, 0, 0);
|
||||||
pub const API_VERSION: u32 = vk_make_version!(1, 0, 92);
|
pub const API_VERSION: u32 = make_api_version(1, 3, 251, 0);
|
||||||
|
|
||||||
pub const WINDOW_WIDTH: u32 = 800;
|
pub const WINDOW_WIDTH: u32 = 800;
|
||||||
pub const WINDOW_HEIGHT: u32 = 600;
|
pub const WINDOW_HEIGHT: u32 = 600;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use ash::version::EntryV1_0;
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use vk::*;
|
||||||
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use ash::version::{EntryV1_0, InstanceV1_0};
|
use ash::{vk, Entry, Instance};
|
||||||
use ash::vk;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use ash::extensions::khr::Win32Surface;
|
use ash::extensions::khr::Win32Surface;
|
||||||
@ -51,9 +50,9 @@ pub fn required_extension_names() -> Vec<*const i8> {
|
|||||||
|
|
||||||
// create surface ---------------------------------------------------------
|
// create surface ---------------------------------------------------------
|
||||||
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
|
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
|
||||||
pub unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
pub unsafe fn create_surface(
|
||||||
entry: &E,
|
entry: &Entry,
|
||||||
instance: &I,
|
instance: &Instance,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
) -> Result<vk::SurfaceKHR, vk::Result> {
|
) -> Result<vk::SurfaceKHR, vk::Result> {
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@ -73,9 +72,9 @@ pub unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
pub unsafe fn create_surface(
|
||||||
entry: &E,
|
entry: &Entry,
|
||||||
instance: &I,
|
instance: &Instance,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
) -> Result<vk::SurfaceKHR, vk::Result> {
|
) -> Result<vk::SurfaceKHR, vk::Result> {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -109,9 +108,9 @@ pub unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
pub unsafe fn create_surface(
|
||||||
entry: &E,
|
entry: &Entry,
|
||||||
instance: &I,
|
instance: &Instance,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
) -> Result<vk::SurfaceKHR, vk::Result> {
|
) -> Result<vk::SurfaceKHR, vk::Result> {
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
@ -72,216 +72,6 @@ pub mod v1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_graphics_pipeline(
|
|
||||||
device: &ash::Device,
|
|
||||||
render_pass: vk::RenderPass,
|
|
||||||
swapchain_extent: vk::Extent2D,
|
|
||||||
) -> (vk::Pipeline, vk::PipelineLayout) {
|
|
||||||
let vert_shader_module = create_shader_module(
|
|
||||||
device,
|
|
||||||
include_bytes!("../../target/shaders/tri.vert.spv").to_vec(),
|
|
||||||
);
|
|
||||||
let frag_shader_module = create_shader_module(
|
|
||||||
device,
|
|
||||||
include_bytes!("../../target/shaders/tri.frag.spv").to_vec(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let main_function_name = CString::new("main").unwrap(); // the beginning function name in shader code.
|
|
||||||
|
|
||||||
let shader_stages = [
|
|
||||||
vk::PipelineShaderStageCreateInfo {
|
|
||||||
// Vertex Shader
|
|
||||||
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
p_next: ptr::null(),
|
|
||||||
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
|
||||||
module: vert_shader_module,
|
|
||||||
p_name: main_function_name.as_ptr(),
|
|
||||||
p_specialization_info: ptr::null(),
|
|
||||||
stage: vk::ShaderStageFlags::VERTEX,
|
|
||||||
},
|
|
||||||
vk::PipelineShaderStageCreateInfo {
|
|
||||||
// Fragment Shader
|
|
||||||
s_type: vk::StructureType::PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
p_next: ptr::null(),
|
|
||||||
flags: vk::PipelineShaderStageCreateFlags::empty(),
|
|
||||||
module: frag_shader_module,
|
|
||||||
p_name: main_function_name.as_ptr(),
|
|
||||||
p_specialization_info: ptr::null(),
|
|
||||||
stage: vk::ShaderStageFlags::FRAGMENT,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
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: 0,
|
|
||||||
p_vertex_attribute_descriptions: ptr::null(),
|
|
||||||
vertex_binding_description_count: 0,
|
|
||||||
p_vertex_binding_descriptions: ptr::null(),
|
|
||||||
};
|
|
||||||
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(),
|
|
||||||
primitive_restart_enable: vk::FALSE,
|
|
||||||
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
|
|
||||||
};
|
|
||||||
|
|
||||||
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(),
|
|
||||||
flags: vk::PipelineRasterizationStateCreateFlags::empty(),
|
|
||||||
depth_clamp_enable: vk::FALSE,
|
|
||||||
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_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::all(),
|
|
||||||
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],
|
|
||||||
};
|
|
||||||
|
|
||||||
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!")
|
|
||||||
};
|
|
||||||
|
|
||||||
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_stages.len() as u32,
|
|
||||||
p_stages: shader_stages.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,
|
|
||||||
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,
|
|
||||||
}];
|
|
||||||
|
|
||||||
let graphics_pipelines = unsafe {
|
|
||||||
device
|
|
||||||
.create_graphics_pipelines(
|
|
||||||
vk::PipelineCache::null(),
|
|
||||||
&graphic_pipeline_create_infos,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.expect("Failed to create Graphics Pipeline!.")
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
device.destroy_shader_module(vert_shader_module, None);
|
|
||||||
device.destroy_shader_module(frag_shader_module, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
(graphics_pipelines[0], pipeline_layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_framebuffers(
|
pub fn create_framebuffers(
|
||||||
device: &ash::Device,
|
device: &ash::Device,
|
||||||
render_pass: vk::RenderPass,
|
render_pass: vk::RenderPass,
|
||||||
@ -740,7 +530,8 @@ pub mod v1 {
|
|||||||
.expect("Failed to create Texture Image!")
|
.expect("Failed to create Texture Image!")
|
||||||
};
|
};
|
||||||
|
|
||||||
let image_memory_requirement = unsafe { device.get_image_memory_requirements(texture_image) };
|
let image_memory_requirement =
|
||||||
|
unsafe { device.get_image_memory_requirements(texture_image) };
|
||||||
let memory_allocate_info = vk::MemoryAllocateInfo {
|
let memory_allocate_info = vk::MemoryAllocateInfo {
|
||||||
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
|
s_type: vk::StructureType::MEMORY_ALLOCATE_INFO,
|
||||||
p_next: ptr::null(),
|
p_next: ptr::null(),
|
||||||
@ -1371,9 +1162,6 @@ pub mod v2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use ash::version::DeviceV1_0;
|
|
||||||
use ash::version::EntryV1_0;
|
|
||||||
use ash::version::InstanceV1_0;
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
@ -1382,7 +1170,6 @@ use std::os::raw::c_void;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
|
|
||||||
use crate::utility::constants::*;
|
use crate::utility::constants::*;
|
||||||
use crate::utility::debug;
|
use crate::utility::debug;
|
||||||
use crate::utility::platforms;
|
use crate::utility::platforms;
|
||||||
@ -1430,8 +1217,7 @@ pub fn create_instance(
|
|||||||
let create_info = vk::InstanceCreateInfo {
|
let create_info = vk::InstanceCreateInfo {
|
||||||
s_type: vk::StructureType::INSTANCE_CREATE_INFO,
|
s_type: vk::StructureType::INSTANCE_CREATE_INFO,
|
||||||
p_next: if VALIDATION.is_enable {
|
p_next: if VALIDATION.is_enable {
|
||||||
&debug_utils_create_info as *const vk::DebugUtilsMessengerCreateInfoEXT
|
&debug_utils_create_info as *const vk::DebugUtilsMessengerCreateInfoEXT as *const c_void
|
||||||
as *const c_void
|
|
||||||
} else {
|
} else {
|
||||||
ptr::null()
|
ptr::null()
|
||||||
},
|
},
|
||||||
@ -1642,6 +1428,7 @@ pub fn find_queue_family(
|
|||||||
index as u32,
|
index as u32,
|
||||||
surface_stuff.surface,
|
surface_stuff.surface,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
if queue_family.queue_count > 0 && is_present_support {
|
if queue_family.queue_count > 0 && is_present_support {
|
||||||
queue_family_indices.present_family = Some(index);
|
queue_family_indices.present_family = Some(index);
|
||||||
@ -1796,7 +1583,6 @@ pub fn create_swapchain(
|
|||||||
pub fn choose_swapchain_format(
|
pub fn choose_swapchain_format(
|
||||||
available_formats: &Vec<vk::SurfaceFormatKHR>,
|
available_formats: &Vec<vk::SurfaceFormatKHR>,
|
||||||
) -> vk::SurfaceFormatKHR {
|
) -> vk::SurfaceFormatKHR {
|
||||||
|
|
||||||
for available_format in available_formats {
|
for available_format in available_formats {
|
||||||
if available_format.format == vk::Format::B8G8R8A8_SRGB
|
if available_format.format == vk::Format::B8G8R8A8_SRGB
|
||||||
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
||||||
@ -1829,8 +1615,7 @@ pub fn choose_swapchain_extent(
|
|||||||
} else {
|
} else {
|
||||||
use num::clamp;
|
use num::clamp;
|
||||||
|
|
||||||
let window_size = window
|
let window_size = window.inner_size();
|
||||||
.inner_size();
|
|
||||||
println!(
|
println!(
|
||||||
"\t\tInner Window Size: ({}, {})",
|
"\t\tInner Window Size: ({}, {})",
|
||||||
window_size.width, window_size.height
|
window_size.width, window_size.height
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent};
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
use winit::event_loop::{EventLoop, ControlFlow};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
|
||||||
|
|
||||||
const IS_PAINT_FPS_COUNTER: bool = true;
|
const IS_PAINT_FPS_COUNTER: bool = true;
|
||||||
|
|
||||||
@ -31,7 +30,6 @@ pub struct ProgramProc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProgramProc {
|
impl ProgramProc {
|
||||||
|
|
||||||
pub fn new() -> ProgramProc {
|
pub fn new() -> ProgramProc {
|
||||||
// init window stuff
|
// init window stuff
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
@ -40,42 +38,38 @@ impl ProgramProc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_loop<A: 'static + VulkanApp>(self, mut vulkan_app: A) {
|
pub fn main_loop<A: 'static + VulkanApp>(self, mut vulkan_app: A) {
|
||||||
|
|
||||||
let mut tick_counter = super::fps_limiter::FPSLimiter::new();
|
let mut tick_counter = super::fps_limiter::FPSLimiter::new();
|
||||||
|
|
||||||
self.event_loop.run(move |event, _, control_flow| {
|
self.event_loop
|
||||||
|
.run(move |event, _, control_flow| match event {
|
||||||
match event {
|
Event::WindowEvent { event, .. } => match event {
|
||||||
| Event::WindowEvent { event, .. } => {
|
WindowEvent::CloseRequested => {
|
||||||
match event {
|
vulkan_app.wait_device_idle();
|
||||||
| WindowEvent::CloseRequested => {
|
*control_flow = ControlFlow::Exit
|
||||||
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();
|
|
||||||
},
|
|
||||||
| _ => {},
|
|
||||||
}
|
}
|
||||||
|
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 => {
|
Event::MainEventsCleared => {
|
||||||
vulkan_app.window_ref().request_redraw();
|
vulkan_app.window_ref().request_redraw();
|
||||||
},
|
}
|
||||||
| Event::RedrawRequested(_window_id) => {
|
Event::RedrawRequested(_window_id) => {
|
||||||
let delta_time = tick_counter.delta_time();
|
let delta_time = tick_counter.delta_time();
|
||||||
vulkan_app.draw_frame(delta_time);
|
vulkan_app.draw_frame(delta_time);
|
||||||
|
|
||||||
@ -84,14 +78,11 @@ impl ProgramProc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tick_counter.tick_frame();
|
tick_counter.tick_frame();
|
||||||
},
|
}
|
||||||
| Event::LoopDestroyed => {
|
Event::LoopDestroyed => {
|
||||||
vulkan_app.wait_device_idle();
|
vulkan_app.wait_device_idle();
|
||||||
},
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
})
|
||||||
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user