Compare commits

...

4 Commits

@ -11,3 +11,4 @@ cgmath = "0.17.0"
image = "0.22"
memoffset = "0.5.1"
tobj = "0.1.10"
rand = "0.8.5"

@ -1,6 +1,5 @@
use std::ffi::OsStr;
use std::fs::File;
use std::io::prelude::*;
use std::io::Write;
use std::path::Path;
use std::process::Command;
@ -10,24 +9,25 @@ fn main() -> std::io::Result<()> {
//shaders path
let shaders = Path::new("./src/shaders");
//shader target path
let out = Command::new("mkdir").arg("target/shaders/").output();
Command::new("mkdir").arg("target/shaders/").status()?;
let shader_target = Path::new("./target/shaders/");
//compile all glsl shaders
for entry in shaders.read_dir().expect("reading shader directory failed") {
if let Ok(entry) = entry {
let shader_path = entry.path();
println!("compiling shader: {:?}", shader_path);
println!("cargo:warning=compiling shader: {:?}", shader_path);
let shader_path_string: String = "./target/shaders/".to_string()
+ shader_path.file_name().unwrap().to_str().unwrap()
+ ".spv";
println!("cargo:warning=compiling destination: {:?}", shader_path_string);
let shader_file: &OsStr = OsStr::new::<str>(shader_path_string.as_str());
Command::new("glslc")
.arg("-c")
.arg(shader_path)
.arg("-o")
.arg(shader_file)
.status();
.status()?;
}
}
//include all compiled shaders in shaders.rs file in src dir

@ -0,0 +1,90 @@
use memoffset::offset_of;
use ash::vk;
use rand::{thread_rng, distributions::{Distribution, Uniform}};
use cgmath::{InnerSpace, Vector2, Vector4};
use crate::utility::constants::*;
use std::f32::consts::PI;
const PARTICLE_COUNT: i32 = 1000;
#[repr(C)]
#[derive(Clone, Debug, Copy)]
pub struct Particle {
pos: Vector2<f32>,
vel: Vector2<f32>,
color: Vector4<f32>,
}
impl Particle {
pub fn gen() -> Vec<Self> {
let mut res = vec![];
let between = Uniform::from(0.0..1.0);
let mut rng = thread_rng();
for _i in 0..PARTICLE_COUNT {
let r = (between.sample(&mut rng) as f32).sqrt();
let theta = between.sample(&mut rng) * 2.0 * PI;
let x = r * theta.cos() * WINDOW_HEIGHT as f32 * WINDOW_WIDTH as f32;
let y = r * theta.sin();
res.push(
Particle {
pos: Vector2::new(x, y),
vel: Vector2::new(x, y).normalize() * 0.00025,
color: Vector4::new(between.sample(&mut rng), between.sample(&mut rng), between.sample(&mut rng), 1.0),
}
)
}
res
}
}
#[repr(C)]
#[derive(Clone, Debug, Copy)]
pub struct Vertex {
pos: [f32; 2],
color: [f32; 3],
}
impl Vertex {
pub fn get_binding_description() -> [vk::VertexInputBindingDescription; 1] {
[vk::VertexInputBindingDescription {
binding: 0,
stride: std::mem::size_of::<Vertex>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}]
}
pub fn get_attribute_descriptions() -> [vk::VertexInputAttributeDescription; 2] {
[
vk::VertexInputAttributeDescription {
binding: 0,
location: 0,
format: vk::Format::R32G32_SFLOAT,
offset: offset_of!(Vertex, pos) as u32,
},
vk::VertexInputAttributeDescription {
binding: 0,
location: 1,
format: vk::Format::R32G32B32_SFLOAT,
offset: offset_of!(Vertex, color) as u32,
},
]
}
}
pub const TRI_VERT_DATA: [Vertex; 3] = [
Vertex {
pos: [0.0, -0.5],
color: [1.0, 1.0, 1.0],
},
Vertex {
pos: [0.5, 0.5],
color: [0.0, 1.0, 0.0],
},
Vertex {
pos: [-0.5, 0.5],
color: [0.0, 0.0, 1.0],
},
];

@ -1,854 +1,10 @@
pub mod shaders;
pub mod utility;
pub mod render;
pub mod entities;
use crate::{
shaders::*, utility::constants::*, utility::debug::*, utility::share, utility::structures::*,
};
use ash::{vk, Entry};
use memoffset::offset_of;
use vk::*;
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";
#[repr(C)]
#[derive(Clone, Debug, Copy)]
struct Vertex {
pos: [f32; 2],
color: [f32; 3],
}
impl Vertex {
fn get_binding_description() -> [vk::VertexInputBindingDescription; 1] {
[vk::VertexInputBindingDescription {
binding: 0,
stride: std::mem::size_of::<Vertex>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}]
}
fn get_attribute_descriptions() -> [vk::VertexInputAttributeDescription; 2] {
[
vk::VertexInputAttributeDescription {
binding: 0,
location: 0,
format: vk::Format::R32G32_SFLOAT,
offset: offset_of!(Vertex, pos) as u32,
},
vk::VertexInputAttributeDescription {
binding: 0,
location: 1,
format: vk::Format::R32G32B32_SFLOAT,
offset: offset_of!(Vertex, color) as u32,
},
]
}
}
const VERTICES_DATA: [Vertex; 3] = [
Vertex {
pos: [0.0, -0.5],
color: [1.0, 1.0, 1.0],
},
Vertex {
pos: [0.5, 0.5],
color: [0.0, 1.0, 0.0],
},
Vertex {
pos: [-0.5, 0.5],
color: [0.0, 0.0, 1.0],
},
];
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,
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,
pipeline_layout: vk::PipelineLayout,
graphics_pipeline: vk::Pipeline,
vertex_buffer: vk::Buffer,
vertex_buffer_memory: vk::DeviceMemory,
command_pool: vk::CommandPool,
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 {
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 =
share::create_surface(&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 swapchain_stuff = share::create_swapchain(
&instance,
&device,
physical_device,
&window,
&surface_stuff,
&queue_family,
);
let swapchain_imageviews = share::v1::create_image_views(
&device,
swapchain_stuff.swapchain_format,
&swapchain_stuff.swapchain_images,
);
let render_pass = share::v1::create_render_pass(&device, swapchain_stuff.swapchain_format);
let (graphics_pipeline, pipeline_layout) = VulkanApp::create_graphics_pipeline(
&device,
render_pass,
swapchain_stuff.swapchain_extent,
);
let swapchain_framebuffers = share::v1::create_framebuffers(
&device,
render_pass,
&swapchain_imageviews,
swapchain_stuff.swapchain_extent,
);
let command_pool = share::v1::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 = share::v1::create_sync_objects(&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,
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,
pipeline_layout,
render_pass,
graphics_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(&VERTICES_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(VERTICES_DATA.as_ptr(), VERTICES_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!")
}
fn create_command_buffers(
device: &ash::Device,
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, VERTICES_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!");
}
}
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(),
}
)
}
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(),
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],
};
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_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,
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 {
for shader in shader_modules {
device.destroy_shader_module(shader.module, None)
}
}
(graphics_pipelines[0], 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 = share::create_swapchain(
&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::v1::create_image_views(
&self.device,
self.swapchain_format,
&self.swapchain_images,
);
self.render_pass = share::v1::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.pipeline_layout = pipeline_layout;
self.swapchain_framebuffers = share::v1::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.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);
}
self.cleanup_swapchain();
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);
}
}
}
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!")
};
}
_ => (),
})
}
}
use winit::event_loop::EventLoop;
use render::VulkanApp;
fn main() {
let event_loop = EventLoop::new();

@ -0,0 +1,801 @@
use crate::{
shaders::*, entities::*, 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,
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,
pipeline_layout: vk::PipelineLayout,
graphics_pipeline: vk::Pipeline,
vertex_buffer: vk::Buffer,
vertex_buffer_memory: vk::DeviceMemory,
command_pool: vk::CommandPool,
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 {
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 =
share::create_surface(&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 swapchain_stuff = share::create_swapchain(
&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, pipeline_layout) = VulkanApp::create_graphics_pipeline(
&device,
render_pass,
swapchain_stuff.swapchain_extent,
);
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 = share::create_sync_objects(&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,
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,
pipeline_layout,
render_pass,
graphics_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!")
}
fn create_command_buffers(
device: &ash::Device,
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!");
}
}
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(),
}
)
}
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(),
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],
};
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_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,
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 {
for shader in shader_modules {
device.destroy_shader_module(shader.module, None)
}
}
(graphics_pipelines[0], 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 = share::create_swapchain(
&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.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.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);
}
self.cleanup_swapchain();
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);
}
}
}
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!")
};
}
_ => (),
})
}
}

@ -17,8 +17,8 @@ pub const VALIDATION: ValidationInfo = ValidationInfo {
pub const DEVICE_EXTENSIONS: DeviceExtension = DeviceExtension {
names: ["VK_KHR_swapchain"],
};
pub const MAX_FRAMES_IN_FLIGHT: usize = 2;
pub const IS_PAINT_FPS_COUNTER: bool = false;
pub const MAX_FRAMES_IN_FLIGHT: usize = 4;
pub const IS_PAINT_FPS_COUNTER: bool = true;
impl DeviceExtension {
pub fn get_extensions_raw_names(&self) -> [*const c_char; 1] {

@ -1,5 +1,5 @@
use ash::vk;
use vk::*;
use std::ffi::CStr;
use std::os::raw::c_void;

@ -1,16 +1,19 @@
pub mod v1 {
use ash::vk;
use image;
use image::GenericImageView;
use ash::vk;
use image;
use image::GenericImageView;
use std::cmp::max;
use std::ffi::CString;
use std::path::Path;
use std::ptr;
use std::os::raw::{c_char, c_void};
use crate::utility::constants::*;
use crate::utility::{debug, platforms};
use crate::utility::structures::*;
use std::cmp::max;
use std::ffi::CString;
use std::path::Path;
use std::ptr;
use super::*;
pub fn create_render_pass(device: &ash::Device, surface_format: vk::Format) -> vk::RenderPass {
pub fn create_render_pass(device: &ash::Device, surface_format: vk::Format) -> vk::RenderPass {
let color_attachment = vk::AttachmentDescription {
format: surface_format,
flags: vk::AttachmentDescriptionFlags::empty(),
@ -70,14 +73,14 @@ pub mod v1 {
.create_render_pass(&renderpass_create_info, None)
.expect("Failed to create render pass!")
}
}
}
pub fn create_framebuffers(
pub fn create_framebuffers(
device: &ash::Device,
render_pass: vk::RenderPass,
image_views: &Vec<vk::ImageView>,
swapchain_extent: vk::Extent2D,
) -> Vec<vk::Framebuffer> {
) -> Vec<vk::Framebuffer> {
let mut framebuffers = vec![];
for &image_view in image_views.iter() {
@ -105,12 +108,12 @@ pub mod v1 {
}
framebuffers
}
}
pub fn create_command_pool(
pub fn create_command_pool(
device: &ash::Device,
queue_families: &QueueFamilyIndices,
) -> vk::CommandPool {
) -> vk::CommandPool {
let command_pool_create_info = vk::CommandPoolCreateInfo {
s_type: vk::StructureType::COMMAND_POOL_CREATE_INFO,
p_next: ptr::null(),
@ -123,16 +126,16 @@ pub mod v1 {
.create_command_pool(&command_pool_create_info, None)
.expect("Failed to create Command Pool!")
}
}
}
pub fn create_command_buffers(
pub fn create_command_buffers(
device: &ash::Device,
command_pool: vk::CommandPool,
graphics_pipeline: vk::Pipeline,
framebuffers: &Vec<vk::Framebuffer>,
render_pass: vk::RenderPass,
surface_extent: vk::Extent2D,
) -> Vec<vk::CommandBuffer> {
) -> Vec<vk::CommandBuffer> {
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo {
s_type: vk::StructureType::COMMAND_BUFFER_ALLOCATE_INFO,
p_next: ptr::null(),
@ -202,9 +205,9 @@ pub mod v1 {
}
command_buffers
}
}
pub fn create_sync_objects(device: &ash::Device, max_frame_in_flight: usize) -> SyncObjects {
pub fn create_sync_objects(device: &ash::Device, max_frame_in_flight: usize) -> SyncObjects {
let mut sync_objects = SyncObjects {
image_available_semaphores: vec![],
render_finished_semaphores: vec![],
@ -246,15 +249,15 @@ pub mod v1 {
}
sync_objects
}
}
pub fn create_vertex_buffer<T>(
pub fn create_vertex_buffer<T>(
device: &ash::Device,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
command_pool: vk::CommandPool,
submit_queue: vk::Queue,
data: &[T],
) -> (vk::Buffer, vk::DeviceMemory) {
) -> (vk::Buffer, vk::DeviceMemory) {
let buffer_size = ::std::mem::size_of_val(data) as vk::DeviceSize;
let (staging_buffer, staging_buffer_memory) = create_buffer(
@ -303,69 +306,12 @@ pub mod v1 {
}
(vertex_buffer, vertex_buffer_memory)
}
pub fn create_index_buffer(
device: &ash::Device,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
command_pool: vk::CommandPool,
submit_queue: vk::Queue,
data: &[u32],
) -> (vk::Buffer, vk::DeviceMemory) {
let buffer_size = ::std::mem::size_of_val(data) as vk::DeviceSize;
let (staging_buffer, staging_buffer_memory) = create_buffer(
device,
buffer_size,
vk::BufferUsageFlags::TRANSFER_SRC,
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
&device_memory_properties,
);
unsafe {
let data_ptr = device
.map_memory(
staging_buffer_memory,
0,
buffer_size,
vk::MemoryMapFlags::empty(),
)
.expect("Failed to Map Memory") as *mut u32;
data_ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
device.unmap_memory(staging_buffer_memory);
}
let (index_buffer, index_buffer_memory) = create_buffer(
device,
buffer_size,
vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::INDEX_BUFFER,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
&device_memory_properties,
);
copy_buffer(
device,
submit_queue,
command_pool,
staging_buffer,
index_buffer,
buffer_size,
);
unsafe {
device.destroy_buffer(staging_buffer, None);
device.free_memory(staging_buffer_memory, None);
}
(index_buffer, index_buffer_memory)
}
}
pub fn create_descriptor_pool(
pub fn create_descriptor_pool(
device: &ash::Device,
swapchain_images_size: usize,
) -> vk::DescriptorPool {
) -> vk::DescriptorPool {
let pool_sizes = [vk::DescriptorPoolSize {
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: swapchain_images_size as u32,
@ -385,15 +331,15 @@ pub mod v1 {
.create_descriptor_pool(&descriptor_pool_create_info, None)
.expect("Failed to create Descriptor Pool!")
}
}
}
pub fn create_descriptor_sets(
pub fn create_descriptor_sets(
device: &ash::Device,
descriptor_pool: vk::DescriptorPool,
descriptor_set_layout: vk::DescriptorSetLayout,
uniforms_buffers: &Vec<vk::Buffer>,
swapchain_images_size: usize,
) -> Vec<vk::DescriptorSet> {
) -> Vec<vk::DescriptorSet> {
let mut layouts: Vec<vk::DescriptorSetLayout> = vec![];
for _ in 0..swapchain_images_size {
layouts.push(descriptor_set_layout);
@ -439,9 +385,9 @@ pub mod v1 {
}
descriptor_sets
}
}
pub fn create_descriptor_set_layout(device: &ash::Device) -> vk::DescriptorSetLayout {
pub fn create_descriptor_set_layout(device: &ash::Device) -> vk::DescriptorSetLayout {
let ubo_layout_bindings = [vk::DescriptorSetLayoutBinding {
binding: 0,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
@ -463,13 +409,13 @@ pub mod v1 {
.create_descriptor_set_layout(&ubo_layout_create_info, None)
.expect("Failed to create Descriptor Set Layout!")
}
}
}
pub fn create_uniform_buffers(
pub fn create_uniform_buffers(
device: &ash::Device,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
swapchain_image_count: usize,
) -> (Vec<vk::Buffer>, Vec<vk::DeviceMemory>) {
) -> (Vec<vk::Buffer>, Vec<vk::DeviceMemory>) {
let buffer_size = ::std::mem::size_of::<UniformBufferObject>();
let mut uniform_buffers = vec![];
@ -488,9 +434,9 @@ pub mod v1 {
}
(uniform_buffers, uniform_buffers_memory)
}
}
pub fn create_image(
pub fn create_image(
device: &ash::Device,
width: u32,
height: u32,
@ -501,7 +447,7 @@ pub mod v1 {
usage: vk::ImageUsageFlags,
required_memory_properties: vk::MemoryPropertyFlags,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
) -> (vk::Image, vk::DeviceMemory) {
) -> (vk::Image, vk::DeviceMemory) {
let image_create_info = vk::ImageCreateInfo {
s_type: vk::StructureType::IMAGE_CREATE_INFO,
p_next: ptr::null(),
@ -556,9 +502,9 @@ pub mod v1 {
}
(texture_image, texture_image_memory)
}
}
pub fn transition_image_layout(
pub fn transition_image_layout(
device: &ash::Device,
command_pool: vk::CommandPool,
submit_queue: vk::Queue,
@ -567,7 +513,7 @@ pub mod v1 {
old_layout: vk::ImageLayout,
new_layout: vk::ImageLayout,
mip_levels: u32,
) {
) {
let command_buffer = begin_single_time_command(device, command_pool);
let src_access_mask;
@ -633,13 +579,13 @@ pub mod v1 {
}
end_single_time_command(device, command_pool, submit_queue, command_buffer);
}
}
pub fn create_image_views(
pub fn create_image_views(
device: &ash::Device,
surface_format: vk::Format,
images: &Vec<vk::Image>,
) -> Vec<vk::ImageView> {
) -> Vec<vk::ImageView> {
let swapchain_imageviews: Vec<vk::ImageView> = images
.iter()
.map(|&image| {
@ -654,15 +600,15 @@ pub mod v1 {
.collect();
swapchain_imageviews
}
}
pub fn create_image_view(
pub fn create_image_view(
device: &ash::Device,
image: vk::Image,
format: vk::Format,
aspect_flags: vk::ImageAspectFlags,
mip_levels: u32,
) -> vk::ImageView {
) -> vk::ImageView {
let imageview_create_info = vk::ImageViewCreateInfo {
s_type: vk::StructureType::IMAGE_VIEW_CREATE_INFO,
p_next: ptr::null(),
@ -690,13 +636,13 @@ pub mod v1 {
.create_image_view(&imageview_create_info, None)
.expect("Failed to create Image View!")
}
}
}
pub fn create_texture_image_view(
pub fn create_texture_image_view(
device: &ash::Device,
texture_image: vk::Image,
mip_levels: u32,
) -> vk::ImageView {
) -> vk::ImageView {
create_image_view(
device,
texture_image,
@ -704,9 +650,9 @@ pub mod v1 {
vk::ImageAspectFlags::COLOR,
mip_levels,
)
}
}
pub fn create_texture_sampler(device: &ash::Device) -> vk::Sampler {
pub fn create_texture_sampler(device: &ash::Device) -> vk::Sampler {
let sampler_create_info = vk::SamplerCreateInfo {
s_type: vk::StructureType::SAMPLER_CREATE_INFO,
p_next: ptr::null(),
@ -733,15 +679,15 @@ pub mod v1 {
.create_sampler(&sampler_create_info, None)
.expect("Failed to create Sampler!")
}
}
}
pub fn create_texture_image(
pub fn create_texture_image(
device: &ash::Device,
command_pool: vk::CommandPool,
submit_queue: vk::Queue,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
image_path: &Path,
) -> (vk::Image, vk::DeviceMemory) {
) -> (vk::Image, vk::DeviceMemory) {
let mut image_object = image::open(image_path).unwrap(); // this function is slow in debug mode.
image_object = image_object.flipv();
let (image_width, image_height) = (image_object.width(), image_object.height());
@ -834,9 +780,9 @@ pub mod v1 {
}
(texture_image, texture_image_memory)
}
}
pub fn create_depth_resources(
pub fn create_depth_resources(
instance: &ash::Instance,
device: &ash::Device,
physical_device: vk::PhysicalDevice,
@ -845,7 +791,7 @@ pub mod v1 {
swapchain_extent: vk::Extent2D,
device_memory_properties: &vk::PhysicalDeviceMemoryProperties,
msaa_samples: vk::SampleCountFlags,
) -> (vk::Image, vk::ImageView, vk::DeviceMemory) {
) -> (vk::Image, vk::ImageView, vk::DeviceMemory) {
let depth_format = find_depth_format(instance, physical_device);
let (depth_image, depth_image_memory) = create_image(
device,
@ -868,9 +814,9 @@ pub mod v1 {
);
(depth_image, depth_image_view, depth_image_memory)
}
}
pub fn generate_mipmaps(
pub fn generate_mipmaps(
device: &ash::Device,
command_pool: vk::CommandPool,
submit_queue: vk::Queue,
@ -878,7 +824,7 @@ pub mod v1 {
tex_width: u32,
tex_height: u32,
mip_levels: u32,
) {
) {
let command_buffer = begin_single_time_command(device, command_pool);
let mut image_barrier = vk::ImageMemoryBarrier {
@ -1005,176 +951,8 @@ pub mod v1 {
}
end_single_time_command(device, command_pool, submit_queue, command_buffer);
}
}
pub mod v2 {
use ash::vk;
use std::ptr;
use super::*;
pub fn create_descriptor_pool(
device: &ash::Device,
swapchain_images_size: usize,
) -> vk::DescriptorPool {
let pool_sizes = [
vk::DescriptorPoolSize {
// transform descriptor pool
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: swapchain_images_size as u32,
},
vk::DescriptorPoolSize {
// sampler descriptor pool
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: swapchain_images_size as u32,
},
];
let descriptor_pool_create_info = vk::DescriptorPoolCreateInfo {
s_type: vk::StructureType::DESCRIPTOR_POOL_CREATE_INFO,
p_next: ptr::null(),
flags: vk::DescriptorPoolCreateFlags::empty(),
max_sets: swapchain_images_size as u32,
pool_size_count: pool_sizes.len() as u32,
p_pool_sizes: pool_sizes.as_ptr(),
};
unsafe {
device
.create_descriptor_pool(&descriptor_pool_create_info, None)
.expect("Failed to create Descriptor Pool!")
}
}
pub fn create_descriptor_sets(
device: &ash::Device,
descriptor_pool: vk::DescriptorPool,
descriptor_set_layout: vk::DescriptorSetLayout,
uniforms_buffers: &Vec<vk::Buffer>,
texture_image_view: vk::ImageView,
texture_sampler: vk::Sampler,
swapchain_images_size: usize,
) -> Vec<vk::DescriptorSet> {
let mut layouts: Vec<vk::DescriptorSetLayout> = vec![];
for _ in 0..swapchain_images_size {
layouts.push(descriptor_set_layout);
}
let descriptor_set_allocate_info = vk::DescriptorSetAllocateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
p_next: ptr::null(),
descriptor_pool,
descriptor_set_count: swapchain_images_size as u32,
p_set_layouts: layouts.as_ptr(),
};
let descriptor_sets = unsafe {
device
.allocate_descriptor_sets(&descriptor_set_allocate_info)
.expect("Failed to allocate descriptor sets!")
};
for (i, &descritptor_set) in descriptor_sets.iter().enumerate() {
let descriptor_buffer_infos = [vk::DescriptorBufferInfo {
buffer: uniforms_buffers[i],
offset: 0,
range: ::std::mem::size_of::<UniformBufferObject>() as u64,
}];
let descriptor_image_infos = [vk::DescriptorImageInfo {
sampler: texture_sampler,
image_view: texture_image_view,
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
}];
let descriptor_write_sets = [
vk::WriteDescriptorSet {
// transform uniform
s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
p_next: ptr::null(),
dst_set: descritptor_set,
dst_binding: 0,
dst_array_element: 0,
descriptor_count: 1,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
p_image_info: ptr::null(),
p_buffer_info: descriptor_buffer_infos.as_ptr(),
p_texel_buffer_view: ptr::null(),
},
vk::WriteDescriptorSet {
// sampler uniform
s_type: vk::StructureType::WRITE_DESCRIPTOR_SET,
p_next: ptr::null(),
dst_set: descritptor_set,
dst_binding: 1,
dst_array_element: 0,
descriptor_count: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
p_image_info: descriptor_image_infos.as_ptr(),
p_buffer_info: ptr::null(),
p_texel_buffer_view: ptr::null(),
},
];
unsafe {
device.update_descriptor_sets(&descriptor_write_sets, &[]);
}
}
descriptor_sets
}
pub fn create_descriptor_set_layout(device: &ash::Device) -> vk::DescriptorSetLayout {
let ubo_layout_bindings = [
vk::DescriptorSetLayoutBinding {
// transform uniform
binding: 0,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::VERTEX,
p_immutable_samplers: ptr::null(),
},
vk::DescriptorSetLayoutBinding {
// sampler uniform
binding: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
p_immutable_samplers: ptr::null(),
},
];
let ubo_layout_create_info = vk::DescriptorSetLayoutCreateInfo {
s_type: vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
p_next: ptr::null(),
flags: vk::DescriptorSetLayoutCreateFlags::empty(),
binding_count: ubo_layout_bindings.len() as u32,
p_bindings: ubo_layout_bindings.as_ptr(),
};
unsafe {
device
.create_descriptor_set_layout(&ubo_layout_create_info, None)
.expect("Failed to create Descriptor Set Layout!")
}
}
}
use ash::vk;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::path::Path;
use std::ptr;
use crate::utility::constants::*;
use crate::utility::debug;
use crate::utility::platforms;
use crate::utility::structures::*;
pub fn create_instance(
entry: &ash::Entry,
window_title: &str,
@ -1365,7 +1143,7 @@ pub fn create_logical_device(
.iter()
.map(|layer_name| CString::new(*layer_name).unwrap())
.collect();
let enable_layer_names: Vec<*const c_char> = requred_validation_layer_raw_names
let _enable_layer_names: Vec<*const c_char> = requred_validation_layer_raw_names
.iter()
.map(|layer_name| layer_name.as_ptr())
.collect();
@ -1378,19 +1156,10 @@ pub fn create_logical_device(
flags: vk::DeviceCreateFlags::empty(),
queue_create_info_count: queue_create_infos.len() as u32,
p_queue_create_infos: queue_create_infos.as_ptr(),
enabled_layer_count: if validation.is_enable {
enable_layer_names.len()
} else {
0
} as u32,
pp_enabled_layer_names: if validation.is_enable {
enable_layer_names.as_ptr()
} else {
ptr::null()
},
enabled_extension_count: enable_extension_names.len() as u32,
pp_enabled_extension_names: enable_extension_names.as_ptr(),
p_enabled_features: &physical_device_features,
..Default::default()
};
let device: ash::Device = unsafe {

@ -133,23 +133,3 @@ impl VertexV3 {
]
}
}
pub const RECT_VERTICES_DATA: [VertexV1; 4] = [
VertexV1 {
pos: [-0.5, -0.5],
color: [1.0, 0.0, 0.0],
},
VertexV1 {
pos: [0.5, -0.5],
color: [0.0, 1.0, 0.0],
},
VertexV1 {
pos: [0.5, 0.5],
color: [0.0, 0.0, 1.0],
},
VertexV1 {
pos: [-0.5, 0.5],
color: [1.0, 1.0, 1.0],
},
];
pub const RECT_INDICES_DATA: [u32; 6] = [0, 1, 2, 2, 3, 0];

Loading…
Cancel
Save