rendering blue background

This commit is contained in:
Janis 2024-12-15 01:59:19 +01:00
parent 052fdc4e3e
commit d9f302cb5a
2 changed files with 228 additions and 46 deletions

View file

@ -50,6 +50,7 @@ impl WindowState {
fn handle_draw_request(&mut self, window_id: WindowId) { fn handle_draw_request(&mut self, window_id: WindowId) {
_ = window_id; _ = window_id;
info!("TODO: implement draw request"); info!("TODO: implement draw request");
self.renderer.debug_draw().expect("drawing");
} }
} }
@ -71,7 +72,7 @@ impl ApplicationHandler for WindowState {
height: size.height, height: size.height,
}; };
self.renderer.new_window_context( let _ = self.renderer.new_window_context(
extent, extent,
window_id, window_id,
self.window self.window

View file

@ -13,6 +13,12 @@ use dyn_clone::DynClone;
use tinyvec::{array_vec, ArrayVec}; use tinyvec::{array_vec, ArrayVec};
use winit::raw_window_handle::DisplayHandle; use winit::raw_window_handle::DisplayHandle;
mod commands;
mod images;
mod sync;
type VkAllocator = Arc<vk_mem::Allocator>;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
#[error(transparent)] #[error(transparent)]
@ -90,6 +96,15 @@ impl Queue {
device.get_device_queue(family, index) device.get_device_queue(family, index)
}))) })))
} }
pub fn with_locked<T, F: FnOnce(vk::Queue) -> T>(&self, map: F) -> T {
let lock = self.0.lock().expect("mutex lock poison");
map(*lock)
}
pub fn lock(&self) -> std::sync::MutexGuard<'_, vk::Queue> {
self.0.lock().unwrap()
}
} }
trait ExtendsDeviceFeatures2Debug: trait ExtendsDeviceFeatures2Debug:
@ -198,6 +213,21 @@ impl PhysicalDeviceFeatures {
} }
} }
fn with_extension2(mut self, ext: vk::ExtensionProperties) -> Self {
self.device_extensions.push(ext);
self
}
fn with_extensions2<I: IntoIterator<Item = vk::ExtensionProperties>>(
mut self,
exts: I,
) -> Self {
self.device_extensions.extend(exts);
self
}
fn with_extension<F>( fn with_extension<F>(
mut self, mut self,
ext: vk::ExtensionProperties, ext: vk::ExtensionProperties,
@ -409,31 +439,45 @@ struct Device {
physical: PhysicalDevice, physical: PhysicalDevice,
device: ash::Device, device: ash::Device,
swapchain: khr::swapchain::Device, swapchain: khr::swapchain::Device,
main_queue: Queue,
compute_queue: Queue,
transfer_queue: Queue,
present_queue: Queue,
} }
impl Device { #[derive(Clone)]
fn new( struct Device2(Arc<Device>);
device: ash::Device,
physical: PhysicalDevice, impl Device2 {
swapchain: khr::swapchain::Device, fn dev(&self) -> &ash::Device {
) -> Self { &self.0.device
Self { }
device, fn swapchain(&self) -> &khr::swapchain::Device {
physical, &self.0.swapchain
swapchain, }
} fn queue_families(&self) -> &DeviceQueueFamilies {
&self.0.physical.queue_families
}
fn phy(&self) -> &vk::PhysicalDevice {
&self.0.physical.pdev
}
fn graphics_queue(&self) -> &Queue {
&self.0.main_queue
}
fn present_queue(&self) -> &Queue {
&self.0.present_queue
} }
} }
impl AsRef<khr::swapchain::Device> for Device { impl AsRef<khr::swapchain::Device> for Device2 {
fn as_ref(&self) -> &khr::swapchain::Device { fn as_ref(&self) -> &khr::swapchain::Device {
&self.swapchain &self.0.swapchain
} }
} }
impl AsRef<ash::Device> for Device { impl AsRef<ash::Device> for Device2 {
fn as_ref(&self) -> &ash::Device { fn as_ref(&self) -> &ash::Device {
&self.device &self.0.device
} }
} }
@ -560,8 +604,14 @@ impl Swapchain {
.cloned() .cloned()
.expect("no surface format available!"); .expect("no surface format available!");
let image_count = let image_count = 3u32.clamp(
3u32.clamp(caps.min_image_count, caps.max_image_count); caps.min_image_count,
if caps.max_image_count == 0 {
u32::MAX
} else {
caps.max_image_count
},
);
let extent = current_extent_or_clamped(&caps, requested_extent); let extent = current_extent_or_clamped(&caps, requested_extent);
@ -767,8 +817,8 @@ impl Drop for Surface {
pub struct Vulkan { pub struct Vulkan {
instance: Arc<Instance>, instance: Arc<Instance>,
device: DeviceAndQueues, device: Arc<Device>,
alloc: Arc<vk_mem::Allocator>, alloc: VkAllocator,
} }
impl Vulkan { impl Vulkan {
@ -907,13 +957,13 @@ impl Vulkan {
) )
.with_extension( .with_extension(
make_extention_properties( make_extention_properties(
ash::khr::index_type_uint8::NAME, ash::ext::index_type_uint8::NAME,
ash::khr::index_type_uint8::SPEC_VERSION, ash::ext::index_type_uint8::SPEC_VERSION,
), ),
vk::PhysicalDeviceIndexTypeUint8FeaturesKHR::default() vk::PhysicalDeviceIndexTypeUint8FeaturesEXT::default()
.index_type_uint8(true), .index_type_uint8(true),
) )
.device_extensions(vec![ .with_extensions2([
make_extention_properties( make_extention_properties(
khr::swapchain::NAME, khr::swapchain::NAME,
khr::swapchain::SPEC_VERSION, khr::swapchain::SPEC_VERSION,
@ -938,19 +988,20 @@ impl Vulkan {
)?; )?;
tracing::debug!("pdev: {pdev:?}"); tracing::debug!("pdev: {pdev:?}");
let dev = Self::create_device(&instance, pdev, &mut features)?; let device =
Arc::new(Self::create_device(&instance, pdev, &mut features)?);
let alloc_info = vk_mem::AllocatorCreateInfo::new( let alloc_info = vk_mem::AllocatorCreateInfo::new(
&instance.instance, &instance.instance,
dev.as_ref(), &device.device,
dev.device.physical.pdev, device.physical.pdev,
); );
let alloc = Arc::new(unsafe { vk_mem::Allocator::new(alloc_info)? }); let alloc = Arc::new(unsafe { vk_mem::Allocator::new(alloc_info)? });
Ok(Self { Ok(Self {
instance, instance,
device: dev, device,
alloc, alloc,
}) })
} }
@ -1145,13 +1196,16 @@ impl Vulkan {
instance: &Instance, instance: &Instance,
pdev: PhysicalDevice, pdev: PhysicalDevice,
features: &mut PhysicalDeviceFeatures, features: &mut PhysicalDeviceFeatures,
) -> Result<DeviceAndQueues> { ) -> Result<Device> {
let mut unique_families = BTreeMap::<u32, u32>::new(); let mut unique_families = BTreeMap::<u32, u32>::new();
let mut helper = |family: u32| { let mut helper = |family: u32| {
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
let index = match unique_families.entry(family) { let index = match unique_families.entry(family) {
Entry::Vacant(vacant_entry) => *vacant_entry.insert(0), Entry::Vacant(vacant_entry) => {
vacant_entry.insert(1);
0
}
Entry::Occupied(mut occupied_entry) => { Entry::Occupied(mut occupied_entry) => {
let idx = occupied_entry.get_mut(); let idx = occupied_entry.get_mut();
*idx += 1; *idx += 1;
@ -1162,6 +1216,8 @@ impl Vulkan {
(family, index) (family, index)
}; };
eprintln!("queue families: {:?}", pdev.queue_families);
let graphics_family_and_index = helper(pdev.queue_families.graphics); let graphics_family_and_index = helper(pdev.queue_families.graphics);
let compute_family_and_index = let compute_family_and_index =
pdev.queue_families.async_compute.map(|f| helper(f)); pdev.queue_families.async_compute.map(|f| helper(f));
@ -1176,8 +1232,11 @@ impl Vulkan {
as usize as usize
]; ];
eprintln!("unique_families: {unique_families:?}");
let queue_infos = unique_families let queue_infos = unique_families
.into_iter() .into_iter()
.filter(|&(_, count)| count > 0)
.map(|(family, queues)| { .map(|(family, queues)| {
vk::DeviceQueueCreateInfo::default() vk::DeviceQueueCreateInfo::default()
.queue_family_index(family) .queue_family_index(family)
@ -1185,6 +1244,8 @@ impl Vulkan {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
eprintln!("infos: {queue_infos:#?}");
let extensions = features let extensions = features
.device_extensions .device_extensions
.iter() .iter()
@ -1197,7 +1258,7 @@ impl Vulkan {
.enabled_extension_names(&extensions) .enabled_extension_names(&extensions)
.push_next(&mut features2); .push_next(&mut features2);
let device_and_queues = unsafe { let device = unsafe {
let device = instance.instance.create_device( let device = instance.instance.create_device(
pdev.pdev, pdev.pdev,
&device_info, &device_info,
@ -1222,15 +1283,13 @@ impl Vulkan {
.map(|(f, i)| Queue::new(&device, f, i)) .map(|(f, i)| Queue::new(&device, f, i))
.unwrap_or(compute_queue.clone()); .unwrap_or(compute_queue.clone());
DeviceAndQueues { Device {
device: Arc::new(Device { device: device.clone(),
device: device.clone(), physical: pdev,
physical: pdev, swapchain: khr::swapchain::Device::new(
swapchain: khr::swapchain::Device::new( &instance.instance,
&instance.instance, &device,
&device, ),
),
}),
main_queue, main_queue,
present_queue, present_queue,
compute_queue, compute_queue,
@ -1238,7 +1297,7 @@ impl Vulkan {
} }
}; };
Ok(device_and_queues) Ok(device)
} }
fn choose_physical_device( fn choose_physical_device(
@ -1417,7 +1476,7 @@ pub struct WindowContext {
} }
impl WindowContext { impl WindowContext {
pub fn new( fn new(
instance: Arc<Instance>, instance: Arc<Instance>,
device: Arc<Device>, device: Arc<Device>,
extent: vk::Extent2D, extent: vk::Extent2D,
@ -1468,11 +1527,133 @@ impl Renderer {
} }
pub fn debug_draw(&mut self) -> Result<()> { pub fn debug_draw(&mut self) -> Result<()> {
let dev = self.vulkan.device.device.clone(); let dev = Device2(self.vulkan.device.clone());
unsafe { dev.device.device_wait_idle()? }; unsafe { dev.dev().device_wait_idle()? };
todo!() let pool = commands::SingleUseCommandPool::new(
dev.clone(),
dev.queue_families().graphics,
)?;
for ctx in self.window_contexts.values() {
let cmd =
commands::SingleUseCommand::new(dev.clone(), pool.pool())?;
let buffer = cmd.command_buffer();
let extent = ctx.current_swapchain.extent;
let ready_semaphore = sync::Semaphore::new(dev.clone())?;
let (swapchain_index, suboptimal) = unsafe {
dev.swapchain().acquire_next_image(
ctx.current_swapchain.swapchain,
u64::MAX,
ready_semaphore.semaphore(),
vk::Fence::null(),
)?
};
if suboptimal {
continue;
}
let image = ctx.current_swapchain.images.first().cloned().unwrap();
// let image = images::Image2D::new_exclusive(
// self.vulkan.alloc.clone(),
// extent,
// 1,
// 1,
// vk::Format::R8G8B8A8_UNORM,
// vk::ImageTiling::OPTIMAL,
// vk::ImageUsageFlags::TRANSFER_SRC,
// vk_mem::MemoryUsage::AutoPreferDevice,
// vk_mem::AllocationCreateFlags::empty(),
// )?;
// let view = image.view(&dev, vk::ImageAspectFlags::COLOR)?;
let clear_values = vk::ClearColorValue {
float32: [0.275, 0.769, 0.941, 1.0],
};
unsafe {
let barriers = [images::image_barrier(
image,
vk::ImageAspectFlags::COLOR,
vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::empty(),
vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::TRANSFER_WRITE,
vk::ImageLayout::UNDEFINED,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
None,
)];
let dependency_info = vk::DependencyInfo::default()
.dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(&barriers);
dev.dev().cmd_pipeline_barrier2(buffer, &dependency_info);
dev.dev().cmd_clear_color_image(
buffer,
image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&clear_values,
&[vk::ImageSubresourceRange::default()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.base_mip_level(0)
.base_array_layer(0)
.level_count(vk::REMAINING_MIP_LEVELS)
.layer_count(vk::REMAINING_ARRAY_LAYERS)],
);
let barriers = [images::image_barrier(
image,
vk::ImageAspectFlags::COLOR,
vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::TRANSFER_WRITE,
vk::PipelineStageFlags2::BOTTOM_OF_PIPE,
vk::AccessFlags2::empty(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
vk::ImageLayout::PRESENT_SRC_KHR,
None,
)];
let dependency_info = vk::DependencyInfo::default()
.dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(&barriers);
dev.dev().cmd_pipeline_barrier2(buffer, &dependency_info);
let signal_semaphore = sync::Semaphore::new(dev.clone())?;
let future = cmd.submit_async(
dev.graphics_queue().clone(),
Some((
ready_semaphore.semaphore(),
vk::PipelineStageFlags::TOP_OF_PIPE,
)),
Some(signal_semaphore.semaphore()),
)?;
let wait_semaphores = [signal_semaphore.semaphore()];
let swapchains = [ctx.current_swapchain.swapchain];
let indices = [swapchain_index];
let present_info = vk::PresentInfoKHR::default()
.image_indices(&indices)
.swapchains(&swapchains)
.wait_semaphores(&wait_semaphores);
dev.present_queue().with_locked(|queue| {
dev.swapchain().queue_present(queue, &present_info)
})?;
future.block_until()?;
}
}
//unsafe {dev.dev().}
Ok(())
} }
pub fn new_window_context( pub fn new_window_context(
@ -1486,7 +1667,7 @@ impl Renderer {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
let ctx = WindowContext::new( let ctx = WindowContext::new(
self.vulkan.instance.clone(), self.vulkan.instance.clone(),
self.vulkan.device.device.clone(), self.vulkan.device.clone(),
extent, extent,
window.as_raw(), window.as_raw(),
self.display, self.display,