|
|
|
@ -1,5 +1,4 @@
|
|
|
|
|
#![feature(inherent_str_constructors)]
|
|
|
|
|
#![allow(unused_variables, unused_mut)]
|
|
|
|
|
#![allow(unused_variables, unused_mut, clippy::too_many_arguments)]
|
|
|
|
|
|
|
|
|
|
use ash::Device;
|
|
|
|
|
use ash::Entry;
|
|
|
|
@ -82,60 +81,66 @@ fn create_instance(window: &Window, entry: &Entry) -> Instance {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_pdev_dgpu(instance: &Instance) -> vk::PhysicalDevice {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mut pdevs = instance
|
|
|
|
|
let mut pdevs = unsafe {
|
|
|
|
|
instance
|
|
|
|
|
.enumerate_physical_devices()
|
|
|
|
|
.expect("Failed to enumerate devices");
|
|
|
|
|
for (i, d) in pdevs.iter().enumerate() {
|
|
|
|
|
let props = instance.get_physical_device_properties(*d);
|
|
|
|
|
.expect("Failed to enumerate devices")
|
|
|
|
|
};
|
|
|
|
|
*pdevs
|
|
|
|
|
.iter()
|
|
|
|
|
.find_map(|d| {
|
|
|
|
|
let props = unsafe { instance.get_physical_device_properties(*d) };
|
|
|
|
|
if props.device_type == vk::PhysicalDeviceType::DISCRETE_GPU {
|
|
|
|
|
// TODO this assumes that the first discrete GPU will have an RCS queue family
|
|
|
|
|
// This is not guaranteed by the spec (example, a compute-only GPU)
|
|
|
|
|
// Fix.
|
|
|
|
|
println!(
|
|
|
|
|
"Found discrete GPU: {}",
|
|
|
|
|
str::from_utf8(std::mem::transmute(props.device_name.as_slice())).unwrap()
|
|
|
|
|
std::str::from_utf8(unsafe {
|
|
|
|
|
std::mem::transmute::<&[i8], &[u8]>(props.device_name.as_slice())
|
|
|
|
|
})
|
|
|
|
|
.unwrap()
|
|
|
|
|
);
|
|
|
|
|
return pdevs.remove(i);
|
|
|
|
|
Some(d)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
println!("No discrete GPU found");
|
|
|
|
|
assert!(pdevs.len() > 0, "No GPU found");
|
|
|
|
|
return pdevs.remove(0);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
|
println!("No discrete GPU found");
|
|
|
|
|
pdevs.first().expect("No GPU found")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_surface(entry: &Entry, instance: &Instance, window: &Window) -> vk::SurfaceKHR {
|
|
|
|
|
unsafe {
|
|
|
|
|
let surface = ash_window::create_surface(
|
|
|
|
|
&entry,
|
|
|
|
|
&instance,
|
|
|
|
|
(&window).display_handle().unwrap().as_raw(),
|
|
|
|
|
(&window).window_handle().unwrap().as_raw(),
|
|
|
|
|
let surface = unsafe {
|
|
|
|
|
ash_window::create_surface(
|
|
|
|
|
entry,
|
|
|
|
|
instance,
|
|
|
|
|
window.display_handle().unwrap().as_raw(),
|
|
|
|
|
window.window_handle().unwrap().as_raw(),
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
.expect("Failed to create surface");
|
|
|
|
|
println!("Created surface");
|
|
|
|
|
surface
|
|
|
|
|
}
|
|
|
|
|
.expect("Failed to create surface");
|
|
|
|
|
println!("Created surface");
|
|
|
|
|
surface
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Using Intel GPU hardware terminology 🥴
|
|
|
|
|
fn find_rcs_queue_inx(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let qfams = instance.get_physical_device_queue_family_properties(*pdev);
|
|
|
|
|
for (inx, qfam) in qfams.iter().enumerate() {
|
|
|
|
|
if qfam
|
|
|
|
|
.queue_flags
|
|
|
|
|
.contains(vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE)
|
|
|
|
|
{
|
|
|
|
|
println!("Found RCS queue at index {}", inx);
|
|
|
|
|
return Some(inx as u32);
|
|
|
|
|
}
|
|
|
|
|
let qfams = unsafe { instance.get_physical_device_queue_family_properties(*pdev) };
|
|
|
|
|
qfams.into_iter().enumerate().find_map(|(inx, qfam)| {
|
|
|
|
|
if qfam
|
|
|
|
|
.queue_flags
|
|
|
|
|
.contains(vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE)
|
|
|
|
|
{
|
|
|
|
|
println!("Found RCS queue at index {}", inx);
|
|
|
|
|
Some(inx as u32)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
println!("No RCS queue found");
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_dev(
|
|
|
|
@ -144,30 +149,27 @@ fn make_dev(
|
|
|
|
|
rcs_queue_inx: u32,
|
|
|
|
|
exts: Vec<&CStr>,
|
|
|
|
|
) -> Device {
|
|
|
|
|
unsafe {
|
|
|
|
|
let dev_queue = vec![
|
|
|
|
|
vk::DeviceQueueCreateInfo::default()
|
|
|
|
|
.queue_family_index(rcs_queue_inx)
|
|
|
|
|
.queue_priorities(&[1.0]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let exts = exts.iter().map(|&s| s.as_ptr()).collect::<Vec<_>>();
|
|
|
|
|
let exts = exts.as_slice();
|
|
|
|
|
|
|
|
|
|
// Enable all features
|
|
|
|
|
let features = instance.get_physical_device_features(*pdev);
|
|
|
|
|
|
|
|
|
|
let dev_info = vk::DeviceCreateInfo::default()
|
|
|
|
|
.queue_create_infos(&dev_queue)
|
|
|
|
|
.enabled_extension_names(exts)
|
|
|
|
|
.enabled_features(&features);
|
|
|
|
|
|
|
|
|
|
let dev = instance
|
|
|
|
|
.create_device(*pdev, &dev_info, None)
|
|
|
|
|
.expect("Failed to create device");
|
|
|
|
|
println!("Created device");
|
|
|
|
|
dev
|
|
|
|
|
}
|
|
|
|
|
let dev_queue = vec![
|
|
|
|
|
vk::DeviceQueueCreateInfo::default()
|
|
|
|
|
.queue_family_index(rcs_queue_inx)
|
|
|
|
|
.queue_priorities(&[1.0]),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let exts = exts.iter().map(|&s| s.as_ptr()).collect::<Vec<_>>();
|
|
|
|
|
let exts = exts.as_slice();
|
|
|
|
|
|
|
|
|
|
// Enable all features
|
|
|
|
|
let features = unsafe { instance.get_physical_device_features(*pdev) };
|
|
|
|
|
|
|
|
|
|
let dev_info = vk::DeviceCreateInfo::default()
|
|
|
|
|
.queue_create_infos(&dev_queue)
|
|
|
|
|
.enabled_extension_names(exts)
|
|
|
|
|
.enabled_features(&features);
|
|
|
|
|
|
|
|
|
|
let dev =
|
|
|
|
|
unsafe { instance.create_device(*pdev, &dev_info, None) }.expect("Failed to create device");
|
|
|
|
|
println!("Created device");
|
|
|
|
|
dev
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_command_pool(dev: &Device, rcs_queue_inx: u32) -> vk::CommandPool {
|
|
|
|
@ -184,69 +186,60 @@ fn make_command_pool(dev: &Device, rcs_queue_inx: u32) -> vk::CommandPool {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn alloc_cmd_buf(dev: &Device, pool: vk::CommandPool) -> vk::CommandBuffer {
|
|
|
|
|
unsafe {
|
|
|
|
|
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
|
|
|
|
.command_pool(pool)
|
|
|
|
|
.level(vk::CommandBufferLevel::PRIMARY)
|
|
|
|
|
.command_buffer_count(1);
|
|
|
|
|
let cmd_buf = dev
|
|
|
|
|
.allocate_command_buffers(&alloc_info)
|
|
|
|
|
.expect("Failed to allocate command buffer")
|
|
|
|
|
.remove(0);
|
|
|
|
|
println!("Allocated command buffer");
|
|
|
|
|
cmd_buf
|
|
|
|
|
}
|
|
|
|
|
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
|
|
|
|
.command_pool(pool)
|
|
|
|
|
.level(vk::CommandBufferLevel::PRIMARY)
|
|
|
|
|
.command_buffer_count(1);
|
|
|
|
|
let cmd_buf = unsafe { dev.allocate_command_buffers(&alloc_info) }
|
|
|
|
|
.expect("Failed to allocate command buffer")[0];
|
|
|
|
|
println!("Allocated command buffer");
|
|
|
|
|
cmd_buf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_host_visible(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mem_props = instance.get_physical_device_memory_properties(*pdev);
|
|
|
|
|
for (i, mem_type) in mem_props.memory_types.iter().enumerate() {
|
|
|
|
|
if mem_type.property_flags.contains(
|
|
|
|
|
vk::MemoryPropertyFlags::DEVICE_LOCAL
|
|
|
|
|
| vk::MemoryPropertyFlags::HOST_VISIBLE
|
|
|
|
|
| vk::MemoryPropertyFlags::HOST_COHERENT,
|
|
|
|
|
) {
|
|
|
|
|
println!("Found host visible memory at index {}", i);
|
|
|
|
|
return Some(i as u32);
|
|
|
|
|
}
|
|
|
|
|
let mem_props = unsafe { instance.get_physical_device_memory_properties(*pdev) };
|
|
|
|
|
for (i, mem_type) in mem_props.memory_types.iter().enumerate() {
|
|
|
|
|
if mem_type.property_flags.contains(
|
|
|
|
|
vk::MemoryPropertyFlags::DEVICE_LOCAL
|
|
|
|
|
| vk::MemoryPropertyFlags::HOST_VISIBLE
|
|
|
|
|
| vk::MemoryPropertyFlags::HOST_COHERENT,
|
|
|
|
|
) {
|
|
|
|
|
println!("Found host visible memory at index {}", i);
|
|
|
|
|
return Some(i as u32);
|
|
|
|
|
}
|
|
|
|
|
println!("No host visible memory found");
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
println!("No host visible memory found");
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_host_invisible(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mem_props = instance.get_physical_device_memory_properties(*pdev);
|
|
|
|
|
for (i, mem_type) in mem_props.memory_types.iter().enumerate() {
|
|
|
|
|
if mem_type
|
|
|
|
|
.property_flags
|
|
|
|
|
.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL)
|
|
|
|
|
&& !mem_type.property_flags.contains(
|
|
|
|
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
println!("Found host invisible memory at index {}", i);
|
|
|
|
|
return Some(i as u32);
|
|
|
|
|
}
|
|
|
|
|
let mem_props = unsafe { instance.get_physical_device_memory_properties(*pdev) };
|
|
|
|
|
for (i, mem_type) in mem_props.memory_types.iter().enumerate() {
|
|
|
|
|
if mem_type
|
|
|
|
|
.property_flags
|
|
|
|
|
.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL)
|
|
|
|
|
&& !mem_type.property_flags.contains(
|
|
|
|
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
println!("Found host invisible memory at index {}", i);
|
|
|
|
|
return Some(i as u32);
|
|
|
|
|
}
|
|
|
|
|
println!("No host invisible memory found");
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
println!("No host invisible memory found");
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn mem_alloc(dev: &Device, mem_type_inx: u32, size: u64) -> vk::DeviceMemory {
|
|
|
|
|
unsafe {
|
|
|
|
|
let mem_info = vk::MemoryAllocateInfo::default()
|
|
|
|
|
.allocation_size(size)
|
|
|
|
|
.memory_type_index(mem_type_inx);
|
|
|
|
|
let mem = dev
|
|
|
|
|
.allocate_memory(&mem_info, None)
|
|
|
|
|
.expect("Failed to allocate memory");
|
|
|
|
|
println!("Allocated memory");
|
|
|
|
|
mem
|
|
|
|
|
}
|
|
|
|
|
let mem_info = vk::MemoryAllocateInfo::default()
|
|
|
|
|
.allocation_size(size)
|
|
|
|
|
.memory_type_index(mem_type_inx);
|
|
|
|
|
let mem = unsafe {
|
|
|
|
|
dev.allocate_memory(&mem_info, None)
|
|
|
|
|
.expect("Failed to allocate memory")
|
|
|
|
|
};
|
|
|
|
|
println!("Allocated memory");
|
|
|
|
|
mem
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_depth_img(
|
|
|
|
@ -257,36 +250,31 @@ fn make_depth_img(
|
|
|
|
|
mem: vk::DeviceMemory,
|
|
|
|
|
qfam: u32,
|
|
|
|
|
) -> vk::Image {
|
|
|
|
|
unsafe {
|
|
|
|
|
let queue_fams = [qfam];
|
|
|
|
|
let img_info = vk::ImageCreateInfo::default()
|
|
|
|
|
.flags(vk::ImageCreateFlags::empty())
|
|
|
|
|
.image_type(vk::ImageType::TYPE_2D)
|
|
|
|
|
.format(vk::Format::D32_SFLOAT)
|
|
|
|
|
.extent(vk::Extent3D {
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
depth: 1,
|
|
|
|
|
})
|
|
|
|
|
.mip_levels(1)
|
|
|
|
|
.array_layers(1)
|
|
|
|
|
.samples(vk::SampleCountFlags::TYPE_1)
|
|
|
|
|
.tiling(vk::ImageTiling::OPTIMAL)
|
|
|
|
|
.usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT)
|
|
|
|
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
|
|
|
|
.queue_family_indices(&queue_fams)
|
|
|
|
|
.initial_layout(vk::ImageLayout::UNDEFINED);
|
|
|
|
|
|
|
|
|
|
let img = dev
|
|
|
|
|
.create_image(&img_info, None)
|
|
|
|
|
.expect("Failed to create image");
|
|
|
|
|
println!("Created image");
|
|
|
|
|
|
|
|
|
|
dev.bind_image_memory(img, mem, 0)
|
|
|
|
|
.expect("Failed to bind image memory");
|
|
|
|
|
|
|
|
|
|
img
|
|
|
|
|
}
|
|
|
|
|
let queue_fams = [qfam];
|
|
|
|
|
let img_info = vk::ImageCreateInfo::default()
|
|
|
|
|
.flags(vk::ImageCreateFlags::empty())
|
|
|
|
|
.image_type(vk::ImageType::TYPE_2D)
|
|
|
|
|
.format(vk::Format::D32_SFLOAT)
|
|
|
|
|
.extent(vk::Extent3D {
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
depth: 1,
|
|
|
|
|
})
|
|
|
|
|
.mip_levels(1)
|
|
|
|
|
.array_layers(1)
|
|
|
|
|
.samples(vk::SampleCountFlags::TYPE_1)
|
|
|
|
|
.tiling(vk::ImageTiling::OPTIMAL)
|
|
|
|
|
.usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT)
|
|
|
|
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
|
|
|
|
.queue_family_indices(&queue_fams)
|
|
|
|
|
.initial_layout(vk::ImageLayout::UNDEFINED);
|
|
|
|
|
|
|
|
|
|
let img = unsafe { dev.create_image(&img_info, None) }.expect("Failed to create image");
|
|
|
|
|
println!("Created image");
|
|
|
|
|
|
|
|
|
|
unsafe { dev.bind_image_memory(img, mem, 0) }.expect("Failed to bind image memory");
|
|
|
|
|
|
|
|
|
|
img
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn alloc_buf(
|
|
|
|
@ -295,30 +283,22 @@ fn alloc_buf(
|
|
|
|
|
size: u64,
|
|
|
|
|
usage: vk::BufferUsageFlags,
|
|
|
|
|
) -> vk::Buffer {
|
|
|
|
|
unsafe {
|
|
|
|
|
let buf_info = vk::BufferCreateInfo::default()
|
|
|
|
|
.size(size)
|
|
|
|
|
.usage(usage)
|
|
|
|
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
|
|
|
|
let buf = dev
|
|
|
|
|
.create_buffer(&buf_info, None)
|
|
|
|
|
.expect("Failed to create buffer");
|
|
|
|
|
|
|
|
|
|
dev.bind_buffer_memory(buf, *mem, 0)
|
|
|
|
|
.expect("Failed to bind buffer memory");
|
|
|
|
|
println!("Created buffer");
|
|
|
|
|
buf
|
|
|
|
|
}
|
|
|
|
|
let buf_info = vk::BufferCreateInfo::default()
|
|
|
|
|
.size(size)
|
|
|
|
|
.usage(usage)
|
|
|
|
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
|
|
|
|
let buf = unsafe { dev.create_buffer(&buf_info, None) }.expect("Failed to create buffer");
|
|
|
|
|
|
|
|
|
|
unsafe { dev.bind_buffer_memory(buf, *mem, 0) }.expect("Failed to bind buffer memory");
|
|
|
|
|
println!("Created buffer");
|
|
|
|
|
buf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn buf_to_ptr(dev: &Device, mem: &vk::DeviceMemory, buf: &vk::Buffer) -> *mut std::ffi::c_void {
|
|
|
|
|
unsafe {
|
|
|
|
|
let ptr = dev
|
|
|
|
|
.map_memory(*mem, 0, vk::WHOLE_SIZE, vk::MemoryMapFlags::empty())
|
|
|
|
|
.expect("Failed to map memory");
|
|
|
|
|
println!("Mapped memory");
|
|
|
|
|
ptr
|
|
|
|
|
}
|
|
|
|
|
let ptr = unsafe { dev.map_memory(*mem, 0, vk::WHOLE_SIZE, vk::MemoryMapFlags::empty()) }
|
|
|
|
|
.expect("Failed to map memory");
|
|
|
|
|
println!("Mapped memory");
|
|
|
|
|
ptr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn setup_desc_layout(dev: &Device) -> vk::DescriptorSetLayout {
|
|
|
|
@ -330,11 +310,8 @@ fn setup_desc_layout(dev: &Device) -> vk::DescriptorSetLayout {
|
|
|
|
|
let layouts = [storage_binding];
|
|
|
|
|
|
|
|
|
|
let layout_info = vk::DescriptorSetLayoutCreateInfo::default().bindings(&layouts);
|
|
|
|
|
let layout = unsafe {
|
|
|
|
|
dev.create_descriptor_set_layout(&layout_info, None)
|
|
|
|
|
.expect("Failed to create descriptor set layout")
|
|
|
|
|
};
|
|
|
|
|
layout
|
|
|
|
|
unsafe { dev.create_descriptor_set_layout(&layout_info, None) }
|
|
|
|
|
.expect("Failed to create descriptor set layout")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn setup_render_pass(dev: &Device) -> vk::RenderPass {
|
|
|
|
@ -401,15 +378,11 @@ fn setup_render_pass(dev: &Device) -> vk::RenderPass {
|
|
|
|
|
.subpasses(subpasses.as_ref())
|
|
|
|
|
.dependencies(deps.as_ref());
|
|
|
|
|
|
|
|
|
|
let pass = unsafe {
|
|
|
|
|
dev.create_render_pass(&pass_info, None)
|
|
|
|
|
.expect("Failed to create render pass")
|
|
|
|
|
};
|
|
|
|
|
pass
|
|
|
|
|
unsafe { dev.create_render_pass(&pass_info, None) }.expect("Failed to create render pass")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn setup_pipe_layout(dev: &Device) -> vk::PipelineLayout {
|
|
|
|
|
let layout = setup_desc_layout(&dev);
|
|
|
|
|
let layout = setup_desc_layout(dev);
|
|
|
|
|
let push_range: [vk::PushConstantRange; 2] = [
|
|
|
|
|
vk::PushConstantRange::default()
|
|
|
|
|
.stage_flags(vk::ShaderStageFlags::VERTEX)
|
|
|
|
@ -426,11 +399,8 @@ fn setup_pipe_layout(dev: &Device) -> vk::PipelineLayout {
|
|
|
|
|
let pipe_layout = vk::PipelineLayoutCreateInfo::default()
|
|
|
|
|
.set_layouts(layouts.as_ref())
|
|
|
|
|
.push_constant_ranges(&push_range);
|
|
|
|
|
let pipe_layout = unsafe {
|
|
|
|
|
dev.create_pipeline_layout(&pipe_layout, None)
|
|
|
|
|
.expect("Failed to create pipeline layout")
|
|
|
|
|
};
|
|
|
|
|
pipe_layout
|
|
|
|
|
unsafe { dev.create_pipeline_layout(&pipe_layout, None) }
|
|
|
|
|
.expect("Failed to create pipeline layout")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn setup_shader_stage(
|
|
|
|
@ -441,11 +411,11 @@ fn setup_shader_stage(
|
|
|
|
|
let vert_stage = vk::PipelineShaderStageCreateInfo::default()
|
|
|
|
|
.stage(vk::ShaderStageFlags::VERTEX)
|
|
|
|
|
.module(vert_shader)
|
|
|
|
|
.name(CStr::from_bytes_with_nul(b"main\0").unwrap());
|
|
|
|
|
.name(c"main");
|
|
|
|
|
let frag_stage = vk::PipelineShaderStageCreateInfo::default()
|
|
|
|
|
.stage(vk::ShaderStageFlags::FRAGMENT)
|
|
|
|
|
.module(frag_shader)
|
|
|
|
|
.name(CStr::from_bytes_with_nul(b"main\0").unwrap());
|
|
|
|
|
.name(c"main");
|
|
|
|
|
[vert_stage, frag_stage]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -456,7 +426,7 @@ fn setup_pipeline(
|
|
|
|
|
pass: &vk::RenderPass,
|
|
|
|
|
pipe_layout: &vk::PipelineLayout,
|
|
|
|
|
) -> vk::Pipeline {
|
|
|
|
|
let shader_stages = setup_shader_stage(&dev, *vert_shader, *frag_shader);
|
|
|
|
|
let shader_stages = setup_shader_stage(dev, *vert_shader, *frag_shader);
|
|
|
|
|
let vert_input = vk::PipelineVertexInputStateCreateInfo::default();
|
|
|
|
|
let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default()
|
|
|
|
|
.topology(vk::PrimitiveTopology::TRIANGLE_LIST);
|
|
|
|
@ -516,11 +486,9 @@ fn setup_pipeline(
|
|
|
|
|
.render_pass(*pass)
|
|
|
|
|
.subpass(0);
|
|
|
|
|
|
|
|
|
|
let pipe = unsafe {
|
|
|
|
|
dev.create_graphics_pipelines(vk::PipelineCache::null(), &[pipe_info], None)
|
|
|
|
|
.expect("Failed to create graphics pipeline")
|
|
|
|
|
.remove(0)
|
|
|
|
|
};
|
|
|
|
|
let pipe =
|
|
|
|
|
unsafe { dev.create_graphics_pipelines(vk::PipelineCache::null(), &[pipe_info], None) }
|
|
|
|
|
.expect("Failed to create graphics pipeline")[0];
|
|
|
|
|
println!("Created pipeline");
|
|
|
|
|
pipe
|
|
|
|
|
}
|
|
|
|
@ -536,25 +504,18 @@ fn setup_swapchain(
|
|
|
|
|
width: u32,
|
|
|
|
|
height: u32,
|
|
|
|
|
) -> (vk::SwapchainKHR, vk::Extent2D) {
|
|
|
|
|
let caps = unsafe {
|
|
|
|
|
surface_loader
|
|
|
|
|
.get_physical_device_surface_capabilities(*pdev, *surface)
|
|
|
|
|
.expect("Failed to get surface capabilities")
|
|
|
|
|
};
|
|
|
|
|
let caps = unsafe { surface_loader.get_physical_device_surface_capabilities(*pdev, *surface) }
|
|
|
|
|
.expect("Failed to get surface capabilities");
|
|
|
|
|
|
|
|
|
|
let formats = unsafe {
|
|
|
|
|
surface_loader
|
|
|
|
|
.get_physical_device_surface_formats(*pdev, *surface)
|
|
|
|
|
.expect("Failed to get surface formats")
|
|
|
|
|
};
|
|
|
|
|
let formats = unsafe { surface_loader.get_physical_device_surface_formats(*pdev, *surface) }
|
|
|
|
|
.expect("Failed to get surface formats");
|
|
|
|
|
|
|
|
|
|
let format = (formats)
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|f| {
|
|
|
|
|
.find(|f| {
|
|
|
|
|
f.format == vk::Format::B8G8R8A8_UNORM
|
|
|
|
|
&& f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
|
|
|
|
})
|
|
|
|
|
.next()
|
|
|
|
|
.expect("No suitable format found");
|
|
|
|
|
|
|
|
|
|
// When the window is resized fast, then the caps goes out of sync of the target extents
|
|
|
|
@ -579,11 +540,8 @@ fn setup_swapchain(
|
|
|
|
|
.present_mode(vk::PresentModeKHR::MAILBOX)
|
|
|
|
|
.clipped(true);
|
|
|
|
|
|
|
|
|
|
let swapchain = unsafe {
|
|
|
|
|
swapchain_loader
|
|
|
|
|
.create_swapchain(&swap_create, None)
|
|
|
|
|
.expect("Failed to create swapchain")
|
|
|
|
|
};
|
|
|
|
|
let swapchain = unsafe { swapchain_loader.create_swapchain(&swap_create, None) }
|
|
|
|
|
.expect("Failed to create swapchain");
|
|
|
|
|
println!("Created swapchain");
|
|
|
|
|
(swapchain, caps.current_extent)
|
|
|
|
|
}
|
|
|
|
@ -596,11 +554,8 @@ fn setup_desc_pool(dev: &Device) -> vk::DescriptorPool {
|
|
|
|
|
let pool_info = vk::DescriptorPoolCreateInfo::default()
|
|
|
|
|
.max_sets(1)
|
|
|
|
|
.pool_sizes(&pool_sizes);
|
|
|
|
|
let pool = unsafe {
|
|
|
|
|
dev.create_descriptor_pool(&pool_info, None)
|
|
|
|
|
.expect("Failed to create descriptor pool")
|
|
|
|
|
};
|
|
|
|
|
pool
|
|
|
|
|
unsafe { dev.create_descriptor_pool(&pool_info, None) }
|
|
|
|
|
.expect("Failed to create descriptor pool")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_swap_images(
|
|
|
|
@ -608,18 +563,15 @@ fn make_swap_images(
|
|
|
|
|
swapchain: &vk::SwapchainKHR,
|
|
|
|
|
swapchain_loader: &swapchain::Device,
|
|
|
|
|
) -> Vec<vk::Image> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let images = swapchain_loader
|
|
|
|
|
.get_swapchain_images(*swapchain)
|
|
|
|
|
.expect("Failed to get swapchain images");
|
|
|
|
|
println!("Fetched swapchain images");
|
|
|
|
|
images
|
|
|
|
|
}
|
|
|
|
|
let images = unsafe { swapchain_loader.get_swapchain_images(*swapchain) }
|
|
|
|
|
.expect("Failed to get swapchain images");
|
|
|
|
|
println!("Fetched swapchain images");
|
|
|
|
|
images
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_swap_views(
|
|
|
|
|
dev: &Device,
|
|
|
|
|
swap_images: &Vec<vk::Image>,
|
|
|
|
|
swap_images: &[vk::Image],
|
|
|
|
|
format: vk::Format,
|
|
|
|
|
) -> Vec<vk::ImageView> {
|
|
|
|
|
let mut views = Vec::new();
|
|
|
|
@ -637,10 +589,8 @@ fn make_swap_views(
|
|
|
|
|
.base_array_layer(0)
|
|
|
|
|
.layer_count(1),
|
|
|
|
|
);
|
|
|
|
|
let view = unsafe {
|
|
|
|
|
dev.create_image_view(&view_info, None)
|
|
|
|
|
.expect("Failed to create image view")
|
|
|
|
|
};
|
|
|
|
|
let view = unsafe { dev.create_image_view(&view_info, None) }
|
|
|
|
|
.expect("Failed to create image view");
|
|
|
|
|
views.push(view);
|
|
|
|
|
}
|
|
|
|
|
views
|
|
|
|
@ -660,16 +610,12 @@ fn make_depth_view(dev: &Device, depth_img: &vk::Image, format: vk::Format) -> v
|
|
|
|
|
.base_array_layer(0)
|
|
|
|
|
.layer_count(1),
|
|
|
|
|
);
|
|
|
|
|
let view = unsafe {
|
|
|
|
|
dev.create_image_view(&view_info, None)
|
|
|
|
|
.expect("Failed to create image view")
|
|
|
|
|
};
|
|
|
|
|
view
|
|
|
|
|
unsafe { dev.create_image_view(&view_info, None) }.expect("Failed to create image view")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_framebufs(
|
|
|
|
|
dev: &Device,
|
|
|
|
|
swap_views: &Vec<vk::ImageView>,
|
|
|
|
|
swap_views: &[vk::ImageView],
|
|
|
|
|
depth_view: &vk::ImageView,
|
|
|
|
|
pass: &vk::RenderPass,
|
|
|
|
|
width: u32,
|
|
|
|
@ -684,29 +630,24 @@ fn make_framebufs(
|
|
|
|
|
.width(width)
|
|
|
|
|
.height(height)
|
|
|
|
|
.layers(1);
|
|
|
|
|
let framebuf = unsafe {
|
|
|
|
|
dev.create_framebuffer(&framebuf_info, None)
|
|
|
|
|
.expect("Failed to create framebuffer")
|
|
|
|
|
};
|
|
|
|
|
let framebuf = unsafe { dev.create_framebuffer(&framebuf_info, None) }
|
|
|
|
|
.expect("Failed to create framebuffer");
|
|
|
|
|
framebufs.push(framebuf);
|
|
|
|
|
}
|
|
|
|
|
framebufs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_desc_sets(dev: &Device, desc_pool: &vk::DescriptorPool) -> Vec<vk::DescriptorSet> {
|
|
|
|
|
let layout = setup_desc_layout(&dev);
|
|
|
|
|
let layout = setup_desc_layout(dev);
|
|
|
|
|
let layouts = [layout];
|
|
|
|
|
let alloc_info = vk::DescriptorSetAllocateInfo::default()
|
|
|
|
|
.descriptor_pool(*desc_pool)
|
|
|
|
|
.set_layouts(&layouts);
|
|
|
|
|
let sets = unsafe {
|
|
|
|
|
dev.allocate_descriptor_sets(&alloc_info)
|
|
|
|
|
.expect("Failed to allocate descriptor sets")
|
|
|
|
|
};
|
|
|
|
|
sets
|
|
|
|
|
unsafe { dev.allocate_descriptor_sets(&alloc_info) }
|
|
|
|
|
.expect("Failed to allocate descriptor sets")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn write_desc_sets(dev: &Device, desc_sets: &Vec<vk::DescriptorSet>, mesh_buf: &vk::Buffer) {
|
|
|
|
|
fn write_desc_sets(dev: &Device, desc_sets: &[vk::DescriptorSet], mesh_buf: &vk::Buffer) {
|
|
|
|
|
let buf_info = vk::DescriptorBufferInfo::default()
|
|
|
|
|
.buffer(*mesh_buf)
|
|
|
|
|
.offset(0)
|
|
|
|
@ -725,35 +666,25 @@ fn write_desc_sets(dev: &Device, desc_sets: &Vec<vk::DescriptorSet>, mesh_buf: &
|
|
|
|
|
|
|
|
|
|
fn make_sem(dev: &Device) -> vk::Semaphore {
|
|
|
|
|
let sem_info = vk::SemaphoreCreateInfo::default();
|
|
|
|
|
let sem = unsafe {
|
|
|
|
|
dev.create_semaphore(&sem_info, None)
|
|
|
|
|
.expect("Failed to create semaphore")
|
|
|
|
|
};
|
|
|
|
|
sem
|
|
|
|
|
unsafe { dev.create_semaphore(&sem_info, None) }.expect("Failed to create semaphore")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_fence(dev: &Device) -> vk::Fence {
|
|
|
|
|
let fence_info = vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED);
|
|
|
|
|
let fence = unsafe {
|
|
|
|
|
dev.create_fence(&fence_info, None)
|
|
|
|
|
.expect("Failed to create fence")
|
|
|
|
|
};
|
|
|
|
|
fence
|
|
|
|
|
unsafe { dev.create_fence(&fence_info, None) }.expect("Failed to create fence")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn wait_for_fence(dev: &Device, fence: &vk::Fence) {
|
|
|
|
|
unsafe {
|
|
|
|
|
let fence = [*fence];
|
|
|
|
|
dev.wait_for_fences(&fence, true, u64::MAX)
|
|
|
|
|
.expect("Failed to wait for fence");
|
|
|
|
|
}
|
|
|
|
|
.expect("Failed to wait for fence");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reset_fence(dev: &Device, fence: &vk::Fence) {
|
|
|
|
|
unsafe {
|
|
|
|
|
let fence = [*fence];
|
|
|
|
|
dev.reset_fences(&fence).expect("Failed to reset fence");
|
|
|
|
|
}
|
|
|
|
|
let fence = [*fence];
|
|
|
|
|
unsafe { dev.reset_fences(&fence) }.expect("Failed to reset fence");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ack_next_img(
|
|
|
|
@ -763,12 +694,11 @@ fn ack_next_img(
|
|
|
|
|
sem_avail: &vk::Semaphore,
|
|
|
|
|
fence: &vk::Fence,
|
|
|
|
|
) -> u32 {
|
|
|
|
|
unsafe {
|
|
|
|
|
let (img_inx, _) = swapchain_loader
|
|
|
|
|
.acquire_next_image(*swapchain, u64::MAX, *sem_avail, vk::Fence::null())
|
|
|
|
|
.expect("Failed to acquire next image");
|
|
|
|
|
img_inx
|
|
|
|
|
let (img_inx, _) = unsafe {
|
|
|
|
|
swapchain_loader.acquire_next_image(*swapchain, u64::MAX, *sem_avail, vk::Fence::null())
|
|
|
|
|
}
|
|
|
|
|
.expect("Failed to acquire next image");
|
|
|
|
|
img_inx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn record_commands(
|
|
|
|
@ -880,21 +810,16 @@ fn record_commands(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn start_cmd_buf(dev: &Device, cmd_buf: &vk::CommandBuffer) {
|
|
|
|
|
unsafe {
|
|
|
|
|
dev.reset_command_buffer(*cmd_buf, vk::CommandBufferResetFlags::empty())
|
|
|
|
|
.expect("Failed to reset command buffer");
|
|
|
|
|
let begin_info =
|
|
|
|
|
vk::CommandBufferBeginInfo::default().flags(vk::CommandBufferUsageFlags::empty());
|
|
|
|
|
dev.begin_command_buffer(*cmd_buf, &begin_info)
|
|
|
|
|
.expect("Failed to begin command buffer");
|
|
|
|
|
}
|
|
|
|
|
unsafe { dev.reset_command_buffer(*cmd_buf, vk::CommandBufferResetFlags::empty()) }
|
|
|
|
|
.expect("Failed to reset command buffer");
|
|
|
|
|
let begin_info =
|
|
|
|
|
vk::CommandBufferBeginInfo::default().flags(vk::CommandBufferUsageFlags::empty());
|
|
|
|
|
unsafe { dev.begin_command_buffer(*cmd_buf, &begin_info) }
|
|
|
|
|
.expect("Failed to begin command buffer");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn end_cmd_buf(dev: &Device, cmd_buf: &vk::CommandBuffer) {
|
|
|
|
|
unsafe {
|
|
|
|
|
dev.end_command_buffer(*cmd_buf)
|
|
|
|
|
.expect("Failed to end command buffer");
|
|
|
|
|
}
|
|
|
|
|
unsafe { dev.end_command_buffer(*cmd_buf) }.expect("Failed to end command buffer");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn submit_queue(
|
|
|
|
@ -913,10 +838,7 @@ fn submit_queue(
|
|
|
|
|
.wait_semaphores(&wait_sems)
|
|
|
|
|
.wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT])
|
|
|
|
|
.signal_semaphores(&signal_sems);
|
|
|
|
|
unsafe {
|
|
|
|
|
dev.queue_submit(*queue, &[submit_info], *fence)
|
|
|
|
|
.expect("Failed to submit queue");
|
|
|
|
|
}
|
|
|
|
|
unsafe { dev.queue_submit(*queue, &[submit_info], *fence) }.expect("Failed to submit queue");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn queue_present(
|
|
|
|
@ -933,11 +855,8 @@ fn queue_present(
|
|
|
|
|
.swapchains(&swapchains)
|
|
|
|
|
.image_indices(&img_inxs)
|
|
|
|
|
.wait_semaphores(&wait_sems);
|
|
|
|
|
unsafe {
|
|
|
|
|
swapchain_loader
|
|
|
|
|
.queue_present(*queue, &present_info)
|
|
|
|
|
.expect("Failed to present queue");
|
|
|
|
|
}
|
|
|
|
|
unsafe { swapchain_loader.queue_present(*queue, &present_info) }
|
|
|
|
|
.expect("Failed to present queue");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
@ -1156,10 +1075,11 @@ fn main() {
|
|
|
|
|
width = w as u32;
|
|
|
|
|
height = h as u32;
|
|
|
|
|
unsafe {
|
|
|
|
|
dev.device_wait_idle().expect("Failed to wait for device idle");
|
|
|
|
|
dev.device_wait_idle()
|
|
|
|
|
.expect("Failed to wait for device idle");
|
|
|
|
|
swapchain_loader.destroy_swapchain(swapchain, None);
|
|
|
|
|
}
|
|
|
|
|
(swapchain, extents) = setup_swapchain(
|
|
|
|
|
(swapchain, _) = setup_swapchain(
|
|
|
|
|
&pdev,
|
|
|
|
|
&dev,
|
|
|
|
|
&surface,
|
|
|
|
|