Last active
November 17, 2021 21:30
-
-
Save kulicuu/745f6253585a4e2c3fefbe01edee5332 to your computer and use it in GitHub Desktop.
Erupt Vulkan Scratchpad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use memoffset::offset_of; | |
use simple_logger::SimpleLogger; | |
use winit::{ | |
event::{ | |
Event, KeyboardInput, WindowEvent, | |
ElementState, StartCause, VirtualKeyCode, | |
DeviceEvent, | |
}, | |
event_loop::{ControlFlow, EventLoop}, | |
window::WindowBuilder, | |
window::Window | |
}; | |
// use winit::event::{ElementState, StartCause, VirtualKeyCode}; | |
use structopt::StructOpt; | |
use erupt::{ | |
cstr, | |
utils::{self, surface}, | |
vk, DeviceLoader, EntryLoader, InstanceLoader, | |
vk::{Device}, | |
}; | |
use std::{ | |
ffi::{c_void, CStr, CString}, | |
fs, | |
fs::{write, OpenOptions}, | |
io::prelude::*, | |
mem::*, | |
os::raw::c_char, | |
ptr, | |
result::Result, | |
result::Result::*, | |
string::String, | |
thread, | |
time, | |
}; | |
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; | |
const TITLE: &str = "Peregrine Ray-Trace"; | |
const FRAMES_IN_FLIGHT: usize = 2; | |
const LAYER_KHRONOS_VALIDATION: *const c_char = cstr!("VK_LAYER_KHRONOS_validation"); | |
const SHADER_VERT: &[u8] = include_bytes!("../spv/s1.vert.spv"); | |
const SHADER_FRAG: &[u8] = include_bytes!("../spv/s1.frag.spv"); | |
#[derive(Debug, StructOpt)] | |
struct Opt { | |
/// Use validation layers | |
#[structopt(short, long)] | |
validation_layers: bool, | |
} | |
unsafe extern "system" fn debug_callback( | |
_message_severity: vk::DebugUtilsMessageSeverityFlagBitsEXT, | |
_message_types: vk::DebugUtilsMessageTypeFlagsEXT, | |
p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT, | |
_p_user_data: *mut c_void, | |
) -> vk::Bool32 { | |
let mut file = OpenOptions::new() | |
.create(true) | |
.write(true) | |
.append(true) | |
.open("./logs/log_main.txt") | |
.unwrap(); | |
let data = CStr::from_ptr((*p_callback_data).p_message).to_string_lossy(); | |
// writeln!(file, &*data); | |
file.write(&*data.as_bytes()).expect("Unable to write to file."); | |
file.write(b"\n").expect("Unable to write newline to file."); | |
eprintln!( | |
"Vulkan: {}", | |
CStr::from_ptr((*p_callback_data).p_message).to_string_lossy() | |
); | |
vk::FALSE | |
} | |
#[repr(C)] | |
#[derive(Debug, Clone, Copy)] | |
struct VertexV3 { | |
pos: [f32; 4], | |
color: [f32; 4], | |
} | |
impl VertexV3 { | |
fn get_binding_descriptions() -> [vk::VertexInputBindingDescription; 1] { | |
[vk::VertexInputBindingDescription { | |
binding: 0, | |
stride: std::mem::size_of::<Self>() as u32, | |
input_rate: vk::VertexInputRate::VERTEX, | |
}] | |
} | |
pub fn get_attribute_descriptions() -> [vk::VertexInputAttributeDescription; 1] { | |
[ | |
vk::VertexInputAttributeDescription { | |
binding: 0, | |
location: 0, | |
format: vk::Format::R32G32B32A32_SFLOAT, | |
offset: offset_of!(Self, pos) as u32, | |
}, | |
// vk::VertexInputAttributeDescription { | |
// binding: 0, | |
// location: 1, | |
// format: vk::Format::R32G32B32A32_SFLOAT, | |
// offset: offset_of!(Self, color) as u32, | |
// }, | |
] | |
} | |
} | |
fn main() { | |
println!("Ray-trace Peregrine"); | |
// flush logs | |
fs::remove_file("./logs/log_main.txt").unwrap(); | |
let event_loop = EventLoop::new(); | |
let window = WindowBuilder::new() | |
.with_title("Peregrine Ray-Trace") | |
.build(&event_loop) | |
.unwrap(); | |
let entry = EntryLoader::new().unwrap(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance | |
let application_name = CString::new("Peregrine Ray-Trace").unwrap(); | |
let engine_name = CString::new("Vulkan Engine").unwrap(); | |
let app_info = vk::ApplicationInfoBuilder::new() | |
.application_name(&application_name) | |
.application_version(vk::make_api_version(0, 1, 0, 0)) | |
.engine_name(&engine_name) | |
.engine_version(vk::make_api_version(0, 1, 0, 0)) | |
.api_version(vk::make_api_version(0, 1, 0, 0)); | |
let mut instance_extensions = surface::enumerate_required_extensions(&window).unwrap(); | |
instance_extensions.push(vk::EXT_DEBUG_UTILS_EXTENSION_NAME); | |
let mut instance_layers = Vec::new(); | |
instance_layers.push(LAYER_KHRONOS_VALIDATION); | |
let device_extensions = vec![ | |
vk::KHR_SWAPCHAIN_EXTENSION_NAME, | |
vk::KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, | |
vk::KHR_RAY_QUERY_EXTENSION_NAME, | |
vk::KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, | |
vk::KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, | |
vk::KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, | |
vk::KHR_SPIRV_1_4_EXTENSION_NAME, | |
vk::KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, | |
vk::EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, | |
]; | |
let mut device_layers = Vec::new(); | |
device_layers.push(LAYER_KHRONOS_VALIDATION); | |
let instance_info = vk::InstanceCreateInfoBuilder::new() | |
.application_info(&app_info) | |
.enabled_extension_names(&instance_extensions) | |
.enabled_layer_names(&instance_layers); | |
let instance = unsafe { InstanceLoader::new(&entry, &instance_info, None) }.unwrap(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers | |
// if opt.validation_layers ... | |
let messenger = { | |
let messenger_info = vk::DebugUtilsMessengerCreateInfoEXTBuilder::new() | |
.message_severity( | |
vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE_EXT | |
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING_EXT | |
| vk::DebugUtilsMessageSeverityFlagsEXT::ERROR_EXT, | |
) | |
.message_type( | |
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL_EXT | |
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION_EXT | |
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE_EXT, | |
) | |
.pfn_user_callback(Some(debug_callback)); | |
unsafe { instance.create_debug_utils_messenger_ext(&messenger_info, None) }.unwrap() | |
}; | |
let surface = unsafe { surface::create_surface(&instance, &window, None) }.unwrap(); | |
let (physical_device, queue_family, format, present_mode, device_properties) = | |
unsafe { instance.enumerate_physical_devices(None) } | |
.unwrap() | |
.into_iter() | |
.filter_map(|physical_device| unsafe { | |
// println!("Physical Device: {:?}", physical_device); | |
// println!("Phyisical Device Queue Family Properties: {:?}", instance.get_physical_device_properties(physical_device)); | |
let queue_family = match instance | |
.get_physical_device_queue_family_properties(physical_device, None) | |
.into_iter() | |
.enumerate() | |
.position(|(i, queue_family_properties)| { | |
queue_family_properties | |
.queue_flags | |
.contains(vk::QueueFlags::GRAPHICS) | |
&& instance | |
.get_physical_device_surface_support_khr( | |
physical_device, | |
i as u32, | |
surface, | |
) | |
.unwrap() | |
}) { | |
Some(queue_family) => queue_family as u32, | |
None => return None, | |
}; | |
let formats = instance | |
.get_physical_device_surface_formats_khr(physical_device, surface, None) | |
.unwrap(); | |
let format = match formats | |
.iter() | |
.find(|surface_format| { | |
surface_format.format == vk::Format::B8G8R8A8_SRGB | |
&& surface_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR_KHR | |
}) | |
.or_else(|| formats.get(0)) | |
{ | |
Some(surface_format) => *surface_format, | |
None => return None, | |
}; | |
let present_mode = instance | |
.get_physical_device_surface_present_modes_khr(physical_device, surface, None) | |
.unwrap() | |
.into_iter() | |
.find(|present_mode| present_mode == &vk::PresentModeKHR::MAILBOX_KHR) | |
.unwrap_or(vk::PresentModeKHR::FIFO_KHR); | |
let supported_device_extensions = instance | |
.enumerate_device_extension_properties(physical_device, None, None) | |
.unwrap(); | |
let device_extensions_supported = | |
device_extensions.iter().all(|device_extension| { | |
let device_extension = CStr::from_ptr(*device_extension); | |
supported_device_extensions.iter().any(|properties| { | |
CStr::from_ptr(properties.extension_name.as_ptr()) == device_extension | |
}) | |
}); | |
if !device_extensions_supported { | |
return None; | |
} | |
let device_properties = instance.get_physical_device_properties(physical_device); | |
Some(( | |
physical_device, | |
queue_family, | |
format, | |
present_mode, | |
device_properties, | |
)) | |
}) | |
.max_by_key(|(_, _, _, _, properties)| match properties.device_type { | |
vk::PhysicalDeviceType::DISCRETE_GPU => 2, | |
vk::PhysicalDeviceType::INTEGRATED_GPU => 1, | |
_ => 0, | |
}) | |
.expect("No suitable physical device found"); | |
//end of declaration of enum (physical_device, queue_family, format, present_mode, device_properties) | |
println!("\n Using physical device: {:?} \n", unsafe { | |
CStr::from_ptr(device_properties.device_name.as_ptr()) | |
}); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Logical_device_and_queues | |
let queue_info = vec![vk::DeviceQueueCreateInfoBuilder::new() | |
.queue_family_index(queue_family) | |
.queue_priorities(&[1.0])]; | |
let features = vk::PhysicalDeviceFeaturesBuilder::new(); | |
let device_info = vk::DeviceCreateInfoBuilder::new() | |
.queue_create_infos(&queue_info) | |
.enabled_features(&features) | |
.enabled_extension_names(&device_extensions) | |
.enabled_layer_names(&device_layers); | |
let device = | |
unsafe { DeviceLoader::new(&instance, physical_device, &device_info, None) }.unwrap(); | |
// let queue2 = unsafe { device2.get_device_queue(queue_family, 0) }; | |
let queue = unsafe { device.get_device_queue(queue_family, 0) }; | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain | |
let surface_caps = | |
unsafe { instance.get_physical_device_surface_capabilities_khr(physical_device, surface) } | |
.unwrap(); | |
let mut image_count = surface_caps.min_image_count + 1; | |
if surface_caps.max_image_count > 0 && image_count > surface_caps.max_image_count { | |
image_count = surface_caps.max_image_count; | |
} | |
let (swapchain, swapchain_images, swapchain_image_views) = create_swapchain_etc( | |
&surface, | |
format, | |
image_count, | |
surface_caps, | |
present_mode, | |
&device | |
); | |
let entry_point = CString::new("main").unwrap(); | |
println!("\n \n"); | |
let model_path: &'static str = "assets/terrain__002__.obj"; | |
let (models, materials) = tobj::load_obj(&model_path, &tobj::LoadOptions::default()).expect("Failed to load model object!"); | |
let model = models[0].clone(); | |
let materials = materials.unwrap(); | |
let material = materials.clone().into_iter().nth(0).unwrap(); | |
let mut vertices = vec![]; | |
let mut indices = vec![]; | |
let mesh = model.mesh; | |
let total_vertices_count = mesh.positions.len() / 3; | |
for i in 0..total_vertices_count { | |
let vertex = VertexV3 { | |
pos: [ | |
mesh.positions[i * 3], | |
mesh.positions[i * 3 + 1], | |
mesh.positions[i * 3 + 2], | |
1.0, | |
], | |
color: [1.0, 1.0, 1.0, 1.0], | |
}; | |
vertices.push(vertex); | |
}; | |
indices = mesh.indices.clone(); | |
println!("Starting buffer and memory allocation/mapping processes... \n"); | |
let vertex_buffer_size = ::std::mem::size_of_val(&vertices) as vk::DeviceSize; | |
println!("vertex_buffer_size: {:?}", vertex_buffer_size); | |
let physical_device_memory_properties = unsafe { instance.get_physical_device_memory_properties(physical_device) }; | |
println!("\n physical_device_memory_properties: {:?}", physical_device_memory_properties); | |
pretty_print(physical_device_memory_properties); | |
let vertex_buffer_create_info = vk::BufferCreateInfoBuilder::new() | |
.size(vertex_buffer_size * 200) | |
.usage(vk::BufferUsageFlags::VERTEX_BUFFER) | |
.sharing_mode(vk::SharingMode::EXCLUSIVE); | |
println!("\n vertex_buffer_create_info: {:?}", vertex_buffer_create_info); | |
let vertex_buffer = unsafe { | |
device | |
.create_buffer(&vertex_buffer_create_info, None) | |
.expect("Failed to create vertex buffer.") | |
}; | |
let vertex_buffer_memory_reqs = unsafe { | |
device | |
.get_buffer_memory_requirements(vertex_buffer) | |
}; | |
println!("\n vertex_buffer_memory_reqs: {:?}", vertex_buffer_memory_reqs); | |
let vertex_buffer_memory_allocate_info = | |
vk::MemoryAllocateInfoBuilder::new() | |
.allocation_size(vertex_buffer_memory_reqs.size) | |
.memory_type_index(2); | |
// .build(); | |
println!("\n vertex_buffer_memory_allocate_info, {:?} \n", vertex_buffer_memory_allocate_info); | |
let vertex_buffer_memory = unsafe { | |
device | |
.allocate_memory(&vertex_buffer_memory_allocate_info, None) | |
.expect("Failed to allocate vertex buffer memory.") | |
}; | |
println!("\n vertex_buffer_memory: {:?} \n", &vertex_buffer_memory); | |
unsafe { device.bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0) } | |
.expect("Error on bind buffer memory"); | |
unsafe { | |
let mut pointer: *mut std::ffi::c_void = std::ptr::null_mut(); | |
let mut ref1 = &mut pointer; | |
device | |
.map_memory( | |
vertex_buffer_memory, | |
256, | |
vk::WHOLE_SIZE, | |
None, | |
ref1, | |
) | |
.expect("failed to map 333memory."); | |
} | |
let vert_decoded = utils::decode_spv(SHADER_VERT).unwrap(); | |
let module_info = vk::ShaderModuleCreateInfoBuilder::new().code(&vert_decoded); | |
let shader_vert = unsafe { device.create_shader_module(&module_info, None) }.unwrap(); | |
let frag_decoded = utils::decode_spv(SHADER_FRAG).unwrap(); | |
let module_info = vk::ShaderModuleCreateInfoBuilder::new().code(&frag_decoded); | |
let shader_frag = unsafe { device.create_shader_module(&module_info, None) }.unwrap(); | |
let shader_stages = vec![ | |
vk::PipelineShaderStageCreateInfoBuilder::new() | |
.stage(vk::ShaderStageFlagBits::VERTEX) | |
.module(shader_vert) | |
.name(&entry_point), | |
vk::PipelineShaderStageCreateInfoBuilder::new() | |
.stage(vk::ShaderStageFlagBits::FRAGMENT) | |
.module(shader_frag) | |
.name(&entry_point), | |
]; | |
// let binding_description = VertexV3::get_binding_descriptions(); | |
// let attribute_description = VertexV3::get_attribute_descriptions(); | |
let binding_description = vk::VertexInputBindingDescriptionBuilder::new() | |
.binding(0) | |
.stride(std::mem::size_of::<VertexV3>() as u32,) | |
.input_rate(vk::VertexInputRate::VERTEX); | |
let binding_descriptions = &[binding_description][..]; | |
let attribute_description = vk::VertexInputAttributeDescriptionBuilder::new() | |
.location(0) | |
.binding(0) | |
.format(vk::Format::R32G32B32A32_SFLOAT) | |
.offset(offset_of!(VertexV3, pos) as u32); | |
let attribute_descriptions = &[attribute_description][..]; | |
let vertex_input = vk::PipelineVertexInputStateCreateInfoBuilder::new() | |
.vertex_binding_descriptions(binding_descriptions) | |
.vertex_attribute_descriptions(attribute_descriptions); | |
let input_assembly = vk::PipelineInputAssemblyStateCreateInfoBuilder::new() | |
.topology(vk::PrimitiveTopology::TRIANGLE_LIST) | |
.primitive_restart_enable(false); | |
let viewports = vec![vk::ViewportBuilder::new() | |
.x(0.0) | |
.y(0.0) | |
.width(surface_caps.current_extent.width as f32) | |
.height(surface_caps.current_extent.height as f32) | |
.min_depth(0.0) | |
.max_depth(1.0)]; | |
let scissors = vec![vk::Rect2DBuilder::new() | |
.offset(vk::Offset2D { x: 0, y: 0 }) | |
.extent(surface_caps.current_extent)]; | |
let viewport_state = vk::PipelineViewportStateCreateInfoBuilder::new() | |
.viewports(&viewports) | |
.scissors(&scissors); | |
let rasterizer = vk::PipelineRasterizationStateCreateInfoBuilder::new() | |
.depth_clamp_enable(false) | |
.rasterizer_discard_enable(false) | |
.polygon_mode(vk::PolygonMode::FILL) | |
.line_width(1.0) | |
.cull_mode(vk::CullModeFlags::BACK) | |
.front_face(vk::FrontFace::CLOCKWISE) | |
.depth_clamp_enable(false); | |
let multisampling = vk::PipelineMultisampleStateCreateInfoBuilder::new() | |
.sample_shading_enable(false) | |
.rasterization_samples(vk::SampleCountFlagBits::_1); | |
let color_blend_attachments = vec![vk::PipelineColorBlendAttachmentStateBuilder::new() | |
.color_write_mask( | |
vk::ColorComponentFlags::R | |
| vk::ColorComponentFlags::G | |
| vk::ColorComponentFlags::B | |
| vk::ColorComponentFlags::A, | |
) | |
.blend_enable(false)]; | |
let color_blending = vk::PipelineColorBlendStateCreateInfoBuilder::new() | |
.logic_op_enable(false) | |
.attachments(&color_blend_attachments); | |
let pipeline_layout_info = vk::PipelineLayoutCreateInfoBuilder::new(); | |
let pipeline_layout = | |
unsafe { device.create_pipeline_layout(&pipeline_layout_info, None) }.unwrap(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Render_passes | |
let attachments = vec![vk::AttachmentDescriptionBuilder::new() | |
.format(format.format) | |
.samples(vk::SampleCountFlagBits::_1) | |
.load_op(vk::AttachmentLoadOp::CLEAR) | |
.store_op(vk::AttachmentStoreOp::STORE) | |
.stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) | |
.stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) | |
.initial_layout(vk::ImageLayout::UNDEFINED) | |
.final_layout(vk::ImageLayout::PRESENT_SRC_KHR)]; | |
let color_attachment_refs = vec![vk::AttachmentReferenceBuilder::new() | |
.attachment(0) | |
.layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)]; | |
let subpasses = vec![vk::SubpassDescriptionBuilder::new() | |
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) | |
.color_attachments(&color_attachment_refs)]; | |
let dependencies = vec![vk::SubpassDependencyBuilder::new() | |
.src_subpass(vk::SUBPASS_EXTERNAL) | |
.dst_subpass(0) | |
.src_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) | |
.src_access_mask(vk::AccessFlags::empty()) | |
.dst_stage_mask(vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT) | |
.dst_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)]; | |
let render_pass_info = vk::RenderPassCreateInfoBuilder::new() | |
.attachments(&attachments) | |
.subpasses(&subpasses) | |
.dependencies(&dependencies); | |
let render_pass = unsafe { device.create_render_pass(&render_pass_info, None) }.unwrap(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Conclusion | |
let pipeline_info = vk::GraphicsPipelineCreateInfoBuilder::new() | |
.stages(&shader_stages) | |
.vertex_input_state(&vertex_input) | |
.input_assembly_state(&input_assembly) | |
.viewport_state(&viewport_state) | |
.rasterization_state(&rasterizer) | |
.multisample_state(&multisampling) | |
.color_blend_state(&color_blending) | |
.layout(pipeline_layout) | |
.render_pass(render_pass) | |
.subpass(0); | |
let pipeline = unsafe { | |
device.create_graphics_pipelines(vk::PipelineCache::null(), &[pipeline_info], None) | |
} | |
.unwrap()[0]; | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Framebuffers | |
let swapchain_framebuffers: Vec<_> = swapchain_image_views | |
.iter() | |
.map(|image_view| { | |
let attachments = vec![*image_view]; | |
let framebuffer_info = vk::FramebufferCreateInfoBuilder::new() | |
.render_pass(render_pass) | |
.attachments(&attachments) | |
.width(surface_caps.current_extent.width) | |
.height(surface_caps.current_extent.height) | |
.layers(1); | |
unsafe { device.create_framebuffer(&framebuffer_info, None) }.unwrap() | |
}) | |
.collect(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Command_buffers | |
let command_pool_info = | |
vk::CommandPoolCreateInfoBuilder::new().queue_family_index(queue_family); | |
let command_pool = unsafe { device.create_command_pool(&command_pool_info, None) }.unwrap(); | |
let cmd_buf_allocate_info = vk::CommandBufferAllocateInfoBuilder::new() | |
.command_pool(command_pool) | |
.level(vk::CommandBufferLevel::PRIMARY) | |
.command_buffer_count(swapchain_framebuffers.len() as _); | |
let cmd_bufs = unsafe { device.allocate_command_buffers(&cmd_buf_allocate_info) }.unwrap(); | |
for (&cmd_buf, &framebuffer) in cmd_bufs.iter().zip(swapchain_framebuffers.iter()) { | |
let cmd_buf_begin_info = vk::CommandBufferBeginInfoBuilder::new(); | |
unsafe { device.begin_command_buffer(cmd_buf, &cmd_buf_begin_info) }.unwrap(); | |
let clear_values = vec![vk::ClearValue { | |
color: vk::ClearColorValue { | |
float32: [0.0, 0.0, 0.0, 1.0], | |
}, | |
}]; | |
let render_pass_begin_info = vk::RenderPassBeginInfoBuilder::new() | |
.render_pass(render_pass) | |
.framebuffer(framebuffer) | |
.render_area(vk::Rect2D { | |
offset: vk::Offset2D { x: 0, y: 0 }, | |
extent: surface_caps.current_extent, | |
}) | |
.clear_values(&clear_values); | |
unsafe { | |
device.cmd_begin_render_pass( | |
cmd_buf, | |
&render_pass_begin_info, | |
vk::SubpassContents::INLINE, | |
); | |
device.cmd_bind_pipeline(cmd_buf, vk::PipelineBindPoint::GRAPHICS, pipeline); | |
device.cmd_bind_vertex_buffers(cmd_buf, 0, &[vertex_buffer], &[256]); | |
device.cmd_draw(cmd_buf, indices.len() as u32, 1, 0, 0); | |
device.cmd_end_render_pass(cmd_buf); | |
device.end_command_buffer(cmd_buf).unwrap(); | |
} | |
} | |
// https://vulkan-tutorial.com/en/Drawing_a_triangle/Drawing/Rendering_and_presentation | |
let semaphore_info = vk::SemaphoreCreateInfoBuilder::new(); | |
let image_available_semaphores: Vec<_> = (0..FRAMES_IN_FLIGHT) | |
.map(|_| unsafe { device.create_semaphore(&semaphore_info, None) }.unwrap()) | |
.collect(); | |
let render_finished_semaphores: Vec<_> = (0..FRAMES_IN_FLIGHT) | |
.map(|_| unsafe { device.create_semaphore(&semaphore_info, None) }.unwrap()) | |
.collect(); | |
let fence_info = vk::FenceCreateInfoBuilder::new().flags(vk::FenceCreateFlags::SIGNALED); | |
let in_flight_fences: Vec<_> = (0..FRAMES_IN_FLIGHT) | |
.map(|_| unsafe { device.create_fence(&fence_info, None) }.unwrap()) | |
.collect(); | |
let mut images_in_flight: Vec<_> = swapchain_images.iter().map(|_| vk::Fence::null()).collect(); | |
// println!("\n \n"); | |
// let model_path: &'static str = "assets/terrain__002__.obj"; | |
// let (models, materials) = tobj::load_obj(&model_path, &tobj::LoadOptions::default()).expect("Failed to load model object!"); | |
// let model = models[0].clone(); | |
// let materials = materials.unwrap(); | |
// let material = materials.clone().into_iter().nth(0).unwrap(); | |
// let mut vertices = vec![]; | |
// let mut indices = vec![]; | |
// let mesh = model.mesh; | |
// let total_vertices_count = mesh.positions.len() / 3; | |
// for i in 0..total_vertices_count { | |
// let vertex = VertexV3 { | |
// pos: [ | |
// mesh.positions[i * 3], | |
// mesh.positions[i * 3 + 1], | |
// mesh.positions[i * 3 + 2], | |
// 1.0, | |
// ], | |
// color: [1.0, 1.0, 1.0, 1.0], | |
// }; | |
// vertices.push(vertex); | |
// }; | |
// indices = mesh.indices.clone(); | |
// println!("Starting buffer and memory allocation/mapping processes... \n"); | |
// let vertex_buffer_size = ::std::mem::size_of_val(&vertices) as vk::DeviceSize; | |
// println!("vertex_buffer_size: {:?}", vertex_buffer_size); | |
// let physical_device_memory_properties = unsafe { instance.get_physical_device_memory_properties(physical_device) }; | |
// println!("\n physical_device_memory_properties: {:?}", physical_device_memory_properties); | |
// pretty_print(physical_device_memory_properties); | |
// let vertex_buffer_create_info = vk::BufferCreateInfoBuilder::new() | |
// .size(vertex_buffer_size * 200) | |
// .usage(vk::BufferUsageFlags::VERTEX_BUFFER) | |
// .sharing_mode(vk::SharingMode::EXCLUSIVE); | |
// println!("\n vertex_buffer_create_info: {:?}", vertex_buffer_create_info); | |
// let vertex_buffer = unsafe { | |
// device | |
// .create_buffer(&vertex_buffer_create_info, None) | |
// .expect("Failed to create vertex buffer.") | |
// }; | |
// let vertex_buffer_memory_reqs = unsafe { | |
// device | |
// .get_buffer_memory_requirements(vertex_buffer) | |
// }; | |
// println!("\n vertex_buffer_memory_reqs: {:?}", vertex_buffer_memory_reqs); | |
// let vertex_buffer_memory_allocate_info = | |
// vk::MemoryAllocateInfoBuilder::new() | |
// .allocation_size(vertex_buffer_memory_reqs.size) | |
// .memory_type_index(2) | |
// .build(); | |
// println!("\n vertex_buffer_memory_allocate_info, {:?} \n", vertex_buffer_memory_allocate_info); | |
// let vertex_buffer_memory = unsafe { | |
// device | |
// .allocate_memory(&vertex_buffer_memory_allocate_info, None) | |
// .expect("Failed to allocate vertex buffer memory.") | |
// }; | |
// println!("\n vertex_buffer_memory: {:?} \n", &vertex_buffer_memory); | |
// unsafe { device.bind_buffer_memory(vertex_buffer, vertex_buffer_memory, 0) } | |
// .expect("Error on bind buffer memory"); | |
// unsafe { | |
// let mut pointer: *mut std::ffi::c_void = std::ptr::null_mut(); | |
// let mut ref1 = &mut pointer; | |
// device | |
// .map_memory( | |
// vertex_buffer_memory, | |
// 256, | |
// vk::WHOLE_SIZE, | |
// None, | |
// ref1, | |
// ) | |
// .expect("failed to map 333memory."); | |
// } | |
let mut frame = 0; | |
#[allow(clippy::collapsible_match, clippy::single_match)] | |
event_loop.run(move |event, _, control_flow| match event { | |
Event::NewEvents(StartCause::Init) => { | |
*control_flow = ControlFlow::Poll; | |
} | |
Event::WindowEvent { event, .. } => match event { | |
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, | |
_ => (), | |
}, | |
Event::DeviceEvent { event, .. } => match event { | |
DeviceEvent::Key(KeyboardInput { | |
virtual_keycode: Some(keycode), | |
state, | |
.. | |
}) => match (keycode, state) { | |
(VirtualKeyCode::Escape, ElementState::Released) => { | |
*control_flow = ControlFlow::Exit | |
} | |
_ => (), | |
}, | |
_ => (), | |
}, | |
Event::MainEventsCleared => { | |
unsafe { | |
device | |
.wait_for_fences(&[in_flight_fences[frame]], true, u64::MAX) | |
.unwrap(); | |
} | |
let image_index = unsafe { | |
device.acquire_next_image_khr( | |
swapchain, | |
u64::MAX, | |
image_available_semaphores[frame], | |
vk::Fence::null(), | |
) | |
} | |
.unwrap(); | |
let image_in_flight = images_in_flight[image_index as usize]; | |
if !image_in_flight.is_null() { | |
unsafe { device.wait_for_fences(&[image_in_flight], true, u64::MAX) }.unwrap(); | |
} | |
images_in_flight[image_index as usize] = in_flight_fences[frame]; | |
let wait_semaphores = vec![image_available_semaphores[frame]]; | |
let command_buffers = vec![cmd_bufs[image_index as usize]]; | |
let signal_semaphores = vec![render_finished_semaphores[frame]]; | |
let submit_info = vk::SubmitInfoBuilder::new() | |
.wait_semaphores(&wait_semaphores) | |
.wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]) | |
.command_buffers(&command_buffers) | |
.signal_semaphores(&signal_semaphores); | |
unsafe { | |
let in_flight_fence = in_flight_fences[frame]; | |
device.reset_fences(&[in_flight_fence]).unwrap(); | |
device | |
.queue_submit(queue, &[submit_info], in_flight_fence) | |
.unwrap() | |
} | |
let swapchains = vec![swapchain]; | |
let image_indices = vec![image_index]; | |
let present_info = vk::PresentInfoKHRBuilder::new() | |
.wait_semaphores(&signal_semaphores) | |
.swapchains(&swapchains) | |
.image_indices(&image_indices); | |
unsafe { device.queue_present_khr(queue, &present_info) }.unwrap(); | |
frame = (frame + 1) % FRAMES_IN_FLIGHT; | |
} | |
Event::LoopDestroyed => unsafe { | |
device.device_wait_idle().unwrap(); | |
for &semaphore in image_available_semaphores | |
.iter() | |
.chain(render_finished_semaphores.iter()) | |
{ | |
device.destroy_semaphore(semaphore, None); | |
} | |
for &fence in &in_flight_fences { | |
device.destroy_fence(fence, None); | |
} | |
device.destroy_command_pool(command_pool, None); | |
for &framebuffer in &swapchain_framebuffers { | |
device.destroy_framebuffer(framebuffer, None); | |
} | |
device.destroy_pipeline(pipeline, None); | |
device.destroy_render_pass(render_pass, None); | |
device.destroy_pipeline_layout(pipeline_layout, None); | |
device.destroy_shader_module(shader_vert, None); | |
device.destroy_shader_module(shader_frag, None); | |
for &image_view in &swapchain_image_views { | |
device.destroy_image_view(image_view, None); | |
} | |
device.destroy_swapchain_khr(swapchain, None); | |
device.destroy_device(None); | |
instance.destroy_surface_khr(surface, None); | |
if !messenger.is_null() { | |
instance.destroy_debug_utils_messenger_ext(messenger, None); | |
} | |
instance.destroy_instance(None); | |
println!("Exited cleanly"); | |
}, | |
_ => (), | |
}) | |
} | |
// this is a hacked together, partially complete attempt | |
// to separate out swapchain etc creation in preparation for the | |
// recreate_swapchain fn to be called when e.g. window is resized. | |
fn create_swapchain_etc( | |
surface: & erupt::extensions::khr_surface::SurfaceKHR, | |
format: vk::SurfaceFormatKHR, | |
image_count: u32, | |
surface_caps: erupt::extensions::khr_surface::SurfaceCapabilitiesKHR, | |
present_mode: erupt::extensions::khr_surface::PresentModeKHR, | |
device: & DeviceLoader, | |
) -> ( | |
erupt::extensions::khr_swapchain::SwapchainKHR, | |
erupt::SmallVec<erupt::vk::Image>, | |
Vec<erupt::vk::ImageView> | |
) { | |
let swapchain_info = vk::SwapchainCreateInfoKHRBuilder::new() | |
.surface(*surface) | |
.min_image_count(image_count) | |
.image_format(format.format) | |
.image_color_space(format.color_space) | |
.image_extent(surface_caps.current_extent) | |
.image_array_layers(1) | |
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) | |
.image_sharing_mode(vk::SharingMode::EXCLUSIVE) | |
.pre_transform(surface_caps.current_transform) | |
.composite_alpha(vk::CompositeAlphaFlagBitsKHR::OPAQUE_KHR) | |
.present_mode(present_mode) | |
.clipped(true) | |
.old_swapchain(vk::SwapchainKHR::null()); | |
let swapchain = unsafe { device.create_swapchain_khr(&swapchain_info, None) }.unwrap(); | |
let swapchain_images = unsafe { device.get_swapchain_images_khr(swapchain, None) }.unwrap(); | |
// https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Image_views | |
let swapchain_image_views: Vec<_> = swapchain_images | |
.iter() | |
.map(|swapchain_image| { | |
let image_view_info = vk::ImageViewCreateInfoBuilder::new() | |
.image(*swapchain_image) | |
.view_type(vk::ImageViewType::_2D) | |
.format(format.format) | |
.components(vk::ComponentMapping { | |
r: vk::ComponentSwizzle::IDENTITY, | |
g: vk::ComponentSwizzle::IDENTITY, | |
b: vk::ComponentSwizzle::IDENTITY, | |
a: vk::ComponentSwizzle::IDENTITY, | |
}) | |
.subresource_range( | |
vk::ImageSubresourceRangeBuilder::new() | |
.aspect_mask(vk::ImageAspectFlags::COLOR) | |
.base_mip_level(0) | |
.level_count(1) | |
.base_array_layer(0) | |
.layer_count(1) | |
.build(), | |
); | |
unsafe { device.create_image_view(&image_view_info, None) }.unwrap() | |
}) | |
.collect(); | |
(swapchain, swapchain_images, swapchain_image_views) | |
} | |
fn recreate_swapchain(device: & DeviceLoader) { | |
unsafe { device.device_wait_idle(); } | |
// create swap chain | |
// create image views | |
// create render pass | |
// create graphics pipeline | |
// create framebuffers | |
// create command buffers | |
} | |
fn pretty_print(stuff: vk::PhysicalDeviceMemoryProperties) { | |
println!("\n pretty_print physical_device_memory_properties: \n"); | |
for memory_type in stuff.memory_types { | |
println!("memory type: {:?}", memory_type); | |
} | |
for heap in stuff.memory_heaps { | |
println!("memory heap: {:?}", heap); | |
} | |
} | |
// let swapchain_info = vk::SwapchainCreateInfoKHRBuilder::new() | |
// .surface(surface) | |
// .min_image_count(image_count) | |
// .image_format(format.format) | |
// .image_color_space(format.color_space) | |
// .image_extent(surface_caps.current_extent) | |
// .image_array_layers(1) | |
// .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) | |
// .image_sharing_mode(vk::SharingMode::EXCLUSIVE) | |
// .pre_transform(surface_caps.current_transform) | |
// .composite_alpha(vk::CompositeAlphaFlagBitsKHR::OPAQUE_KHR) | |
// .present_mode(present_mode) | |
// .clipped(true) | |
// .old_swapchain(vk::SwapchainKHR::null()); | |
// let swapchain = unsafe { device.create_swapchain_khr(&swapchain_info, None) }.unwrap(); | |
// let swapchain_images = unsafe { device.get_swapchain_images_khr(swapchain, None) }.unwrap(); | |
// // https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Image_views | |
// let swapchain_image_views: Vec<_> = swapchain_images | |
// .iter() | |
// .map(|swapchain_image| { | |
// let image_view_info = vk::ImageViewCreateInfoBuilder::new() | |
// .image(*swapchain_image) | |
// .view_type(vk::ImageViewType::_2D) | |
// .format(format.format) | |
// .components(vk::ComponentMapping { | |
// r: vk::ComponentSwizzle::IDENTITY, | |
// g: vk::ComponentSwizzle::IDENTITY, | |
// b: vk::ComponentSwizzle::IDENTITY, | |
// a: vk::ComponentSwizzle::IDENTITY, | |
// }) | |
// .subresource_range( | |
// vk::ImageSubresourceRangeBuilder::new() | |
// .aspect_mask(vk::ImageAspectFlags::COLOR) | |
// .base_mip_level(0) | |
// .level_count(1) | |
// .base_array_layer(0) | |
// .layer_count(1) | |
// .build(), | |
// ); | |
// unsafe { device.create_image_view(&image_view_info, None) }.unwrap() | |
// }) | |
// .collect(); | |
// ... let entry = |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment