fix egui ?

This commit is contained in:
janis 2026-04-03 03:13:51 +02:00
parent 297b79d347
commit b00b1b3151
10 changed files with 297 additions and 327 deletions

View file

@ -42,6 +42,7 @@ ash = "0.38.0"
ash-window = "0.13.0" ash-window = "0.13.0"
vk-mem = "0.5.0" vk-mem = "0.5.0"
gpu-allocator = { git = "https://github.com/janis-bhm/gpu-allocator", branch = "main" } gpu-allocator = { git = "https://github.com/janis-bhm/gpu-allocator", branch = "main" }
rectangle-pack = "0.4.2"
vk-sync = "0.1.6" vk-sync = "0.1.6"
arrayvec = "0.7.6" arrayvec = "0.7.6"

View file

@ -24,6 +24,7 @@ ash = { workspace = true }
ash-window = { workspace = true } ash-window = { workspace = true }
vk-mem = { workspace = true } vk-mem = { workspace = true }
gpu-allocator = { workspace = true } gpu-allocator = { workspace = true }
rectangle-pack = { workspace = true }
raw-window-handle = { workspace = true } raw-window-handle = { workspace = true }
egui = { workspace = true , features = ["bytemuck"]} egui = { workspace = true , features = ["bytemuck"]}

View file

@ -14,7 +14,6 @@ use ash::{
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use raw_window_handle::RawDisplayHandle; use raw_window_handle::RawDisplayHandle;
use tinyvec::{ArrayVec, array_vec};
use crate::{ use crate::{
Instance, PhysicalDeviceFeatures, PhysicalDeviceInfo, Result, Instance, PhysicalDeviceFeatures, PhysicalDeviceInfo, Result,
@ -22,62 +21,6 @@ use crate::{
sync::{self, BinarySemaphore, TimelineSemaphore}, sync::{self, BinarySemaphore, TimelineSemaphore},
}; };
#[derive(Debug, Default)]
pub struct DeviceQueueFamilies {
pub(crate) families: Vec<(u32, u32)>,
pub(crate) graphics: (u32, u32),
pub(crate) present: (u32, u32),
pub(crate) async_compute: (u32, u32),
pub(crate) transfer: (u32, u32),
#[expect(dead_code)]
pub(crate) properties: Box<[vk::QueueFamilyProperties]>,
}
impl DeviceQueueFamilies {
pub fn swapchain_family_indices(&self) -> ArrayVec<[u32; 2]> {
let mut indices = array_vec!([u32; 2] => self.graphics.0);
if self.present.0 != self.graphics.0 {
indices.push(self.present.0);
}
indices
}
pub fn graphics_familty(&self) -> u32 {
self.graphics.0
}
pub fn present_familty(&self) -> u32 {
self.present.0
}
pub fn async_compute_familty(&self) -> u32 {
self.async_compute.0
}
pub fn transfer_familty(&self) -> u32 {
self.transfer.0
}
pub fn family_indices(&self, flags: QueueFlags) -> ArrayVec<[u32; 4]> {
let mut indices = array_vec!([u32; 4]);
if flags.contains(QueueFlags::GRAPHICS) {
indices.push(self.graphics_familty());
}
if flags.contains(QueueFlags::PRESENT) {
indices.push(self.present_familty());
}
if flags.contains(QueueFlags::ASYNC_COMPUTE) {
indices.push(self.async_compute_familty());
}
if flags.contains(QueueFlags::TRANSFER) {
indices.push(self.transfer_familty());
}
let unique_len = indices.partition_dedup().0.len();
indices.drain(unique_len..);
indices
}
}
bitflags::bitflags! { bitflags::bitflags! {
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -102,9 +45,10 @@ impl Drop for DeviceDrop {
} }
} }
struct DeviceExtensions { pub(crate) struct DeviceExtensions {
pub(crate) debug_utils: ext::debug_utils::Device, pub(crate) debug_utils: ext::debug_utils::Device,
pub(crate) swapchain: Option<khr::swapchain::Device>, pub(crate) swapchain: Option<khr::swapchain::Device>,
#[allow(dead_code)]
pub(crate) mesh_shader: Option<ext::mesh_shader::Device>, pub(crate) mesh_shader: Option<ext::mesh_shader::Device>,
} }
@ -131,7 +75,7 @@ pub enum AllocationStrategy {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum Allocation { pub enum Allocation {
Owned(DeviceObject<GpuAllocation>), Owned(DeviceObject<GpuAllocation>),
Shared(Arc<DeviceObject<GpuAllocation>>), Shared(Arc<DeviceObject<GpuAllocation>>),
Unmanaged, Unmanaged,
@ -163,6 +107,7 @@ pub struct DeviceInner {
pub(crate) queues: DeviceQueues, pub(crate) queues: DeviceQueues,
pub(crate) sync_threadpool: sync::SyncThreadpool, pub(crate) sync_threadpool: sync::SyncThreadpool,
pub(crate) device_extensions: DeviceExtensions, pub(crate) device_extensions: DeviceExtensions,
#[allow(dead_code)]
pub(crate) enabled_extensions: Vec<&'static CStr>, pub(crate) enabled_extensions: Vec<&'static CStr>,
_drop: DeviceDrop, _drop: DeviceDrop,
} }
@ -550,7 +495,7 @@ impl DeviceInner {
pub fn features(&self) -> &crate::PhysicalDeviceFeatures { pub fn features(&self) -> &crate::PhysicalDeviceFeatures {
&self.adapter.features &self.adapter.features
} }
pub fn properties(&self) -> &crate::PhysicalDeviceProperties { pub(crate) fn properties(&self) -> &crate::PhysicalDeviceProperties {
&self.adapter.properties &self.adapter.properties
} }
pub fn physical_device(&self) -> &PhysicalDeviceInfo { pub fn physical_device(&self) -> &PhysicalDeviceInfo {
@ -566,12 +511,18 @@ impl DeviceInner {
self.queues.transfer() self.queues.transfer()
} }
/// # Safety
///
/// The caller must ensure that the queues aren't already locked when calling this function.
pub unsafe fn lock_queues(&self) { pub unsafe fn lock_queues(&self) {
unsafe { unsafe {
self.queues.lock(); self.queues.lock();
} }
} }
/// # Safety
///
/// The caller must have acquired and have logical ownership of the lock on the queues.
pub unsafe fn unlock_queues(&self) { pub unsafe fn unlock_queues(&self) {
unsafe { unsafe {
self.queues.unlock(); self.queues.unlock();

View file

@ -1,4 +1,7 @@
use std::{collections::BTreeMap, sync::Arc}; use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use ash::vk; use ash::vk;
use gpu_allocator::MemoryLocation; use gpu_allocator::MemoryLocation;
@ -14,8 +17,7 @@ use crate::{
Access, Barrier, GraphResourceDesc, GraphResourceId, PassDesc, RecordFn, RenderContext, Access, Barrier, GraphResourceDesc, GraphResourceId, PassDesc, RecordFn, RenderContext,
RenderGraph, buffer_barrier, image_barrier, RenderGraph, buffer_barrier, image_barrier,
}, },
texture, texture::{self, TextureId},
util::Rect2D,
}; };
pub fn egui_pre_pass( pub fn egui_pre_pass(
@ -32,15 +34,32 @@ pub fn egui_pre_pass(
return Ok(()); return Ok(());
} }
use rectangle_pack::{
GroupedRectsToPlace, RectToInsert, TargetBin, contains_smallest_box, pack_rects,
volume_heuristic,
};
let mut rects_to_place = GroupedRectsToPlace::<TextureId, ()>::new();
let mut max_width = 0;
let mut max_height = 0;
// create textures for new egui textures // create textures for new egui textures
for (egui_id, delta) in output // these are real images that will be sampled from in the shader.
let updates = output
.textures_delta .textures_delta
.set .set
.iter() .iter()
.filter(|(_, image)| image.is_whole()) .map(|(egui_id, delta)| {
{ max_width = max_width.max(delta.image.width() as u32);
max_height = max_height.max(delta.image.height() as u32);
use std::collections::hash_map::Entry;
let id = match egui_state.textures.entry(*egui_id) {
Entry::Occupied(entry) => entry.get().id,
Entry::Vacant(entry) => {
tracing::trace!("creating texture image for egui image {egui_id:?}"); tracing::trace!("creating texture image for egui image {egui_id:?}");
let image = Image::new(
let Ok(image) = Image::new(
dev.clone(), dev.clone(),
ImageDesc { ImageDesc {
name: Some(format!("egui-texture-{egui_id:?}").into()), name: Some(format!("egui-texture-{egui_id:?}").into()),
@ -55,45 +74,66 @@ pub fn egui_pre_pass(
alloc_scheme: AllocationStrategy::Dedicated, alloc_scheme: AllocationStrategy::Dedicated,
..Default::default() ..Default::default()
}, },
)?; ) else {
return Err(crate::Error::Todo(
let tid = textures.insert_image(Arc::new(image)); "handle image creation failure in egui pre-pass",
if let Some(old) = egui_state.textures.insert(
*egui_id,
crate::EguiTextureInfo {
id: tid,
options: delta.options,
},
) {
textures.remove_texture(old.id);
}
}
// calculate size for staging buffer.
// calculate size for staging image.
let (staging_size, image_size) = output.textures_delta.set.iter().fold(
(0usize, glam::UVec2::ZERO),
|(mut buffer, mut image), (_id, delta)| {
let bytes = delta.image.height() * delta.image.width() * delta.image.bytes_per_pixel();
image = image.max(glam::uvec2(
delta.image.width() as u32,
delta.image.height() as u32,
)); ));
buffer += bytes; };
(buffer, image) let id = textures.insert_image(Arc::new(image));
}, entry.insert(crate::EguiTextureInfo {
id,
options: delta.options,
});
id
}
};
rects_to_place.push_rect(
id,
None,
RectToInsert::new(delta.image.width() as u32, delta.image.height() as u32, 1),
); );
Ok((id, (delta.pos, &delta.image)))
})
.collect::<crate::Result<HashMap<_, _>>>()?;
let rect_placements = loop {
let mut target_bins = BTreeMap::new();
target_bins.insert(0, TargetBin::new(max_width, max_height, 1));
match pack_rects(
&rects_to_place,
&mut target_bins,
&volume_heuristic,
&contains_smallest_box,
) {
Ok(placements) => break placements,
Err(_) => {
max_width *= 2;
max_height *= 2;
}
}
};
let extent = rect_placements
.packed_locations()
.iter()
.fold((0u32, 0u32), |(w, h), (_id, (_bin, loc))| {
(w.max(loc.x() + loc.width()), h.max(loc.y() + loc.height()))
});
tracing::trace!( tracing::trace!(
staging_size, "creating staging buffer {}x{} for uploading egui textures",
"creating staging buffer for uploading egui textures" extent.0,
extent.1,
); );
let mut staging_buffer = Buffer::new( let mut staging_buffer = Buffer::new(
dev.clone(), dev.clone(),
BufferDesc { BufferDesc {
name: Some("egui-prepass-staging-buffer".into()), name: Some("egui-prepass-staging-buffer".into()),
size: staging_size as u64, size: (extent.0 * extent.1 * 4) as u64, // RGBA8
usage: vk::BufferUsageFlags::TRANSFER_SRC, usage: vk::BufferUsageFlags::TRANSFER_SRC,
queue_families: device::QueueFlags::empty(), queue_families: device::QueueFlags::empty(),
mem_location: MemoryLocation::CpuToGpu, mem_location: MemoryLocation::CpuToGpu,
@ -101,15 +141,14 @@ pub fn egui_pre_pass(
}, },
)?; )?;
tracing::trace!("creating staging image for uploading egui textures with dims={image_size:?}"); let staging_image = Image::new(
let staging_image = Arc::new(Image::new(
dev.clone(), dev.clone(),
ImageDesc { ImageDesc {
name: Some("egui-prepass-staging-buffer".into()), name: Some("egui-prepass-staging-buffer".into()),
format: vk::Format::R8G8B8A8_UNORM, format: vk::Format::R8G8B8A8_UNORM,
extent: vk::Extent3D { extent: vk::Extent3D {
width: image_size.x, width: extent.0,
height: image_size.y, height: extent.1,
depth: 1, depth: 1,
}, },
usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST, usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST,
@ -117,104 +156,90 @@ pub fn egui_pre_pass(
mem_location: MemoryLocation::GpuOnly, mem_location: MemoryLocation::GpuOnly,
..Default::default() ..Default::default()
}, },
)?); )?;
let aliased_images = { let staging_map = staging_buffer.map_mut().unwrap();
tracing::trace!("mmap-ing staging buffer");
let mut staging_map = staging_buffer.map().unwrap();
let mut offset = 0;
output struct ImageUpdate {
.textures_delta #[allow(dead_code)]
.set id: TextureId,
.iter() graph_id: GraphResourceId,
.map(|(id, delta)| { dest_offset: (u32, u32),
let bytes = src_offset: (u32, u32),
delta.image.height() * delta.image.width() * delta.image.bytes_per_pixel(); size: (u32, u32),
let mem = &mut staging_map[offset..offset + bytes];
match &delta.image {
egui::ImageData::Color(arc) => {
let slice = unsafe {
core::slice::from_raw_parts(
arc.pixels.as_ptr().cast::<u8>(),
arc.pixels.len() * size_of::<egui::Color32>(),
)
};
mem[..slice.len()].copy_from_slice(slice);
}
} }
let old_offset = offset; let updates = updates
offset += bytes; .into_iter()
.filter_map(|(id, (pos, image))| {
let (_, loc) = rect_placements.packed_locations().get(&id)?;
let pos = delta.pos.unwrap_or_default(); // copy scanlines from image data into staging buffer
let rect = Rect2D::new_from_size( let rect_width = loc.width() as usize;
glam::ivec2(pos[0] as i32, pos[1] as i32), let rect_height = loc.height() as usize;
glam::ivec2(delta.image.width() as i32, delta.image.height() as i32), let rect_x = loc.x() as usize;
); let rect_y = loc.y() as usize;
(*id, (old_offset, bytes, rect))
})
.collect::<BTreeMap<_, _>>()
// let tessellated = egui.tessellate(output.shapes, output.pixels_per_point); let pixel_size = 4usize; // RGBA8
let atlas_width = extent.0 as usize;
let image_data = match image {
egui::ImageData::Color(color_image) => color_image.as_raw(),
}; };
let textures = output for (atlas_y, image_y) in (rect_y..rect_y + rect_height).enumerate() {
.textures_delta let atlas_start = (image_y * atlas_width + rect_x) * pixel_size;
.set let atlas_end = atlas_start + rect_width * pixel_size;
.iter()
.filter_map(|(egui_id, _)| { let image_start = (atlas_y * rect_width) * pixel_size;
egui_state let image_end = image_start + rect_width * pixel_size;
.lookup_texture(*egui_id) staging_map[atlas_start..atlas_end]
.and_then(|tid| textures.get_texture(tid)) .copy_from_slice(&image_data[image_start..image_end]);
.map(|img| (*egui_id, img)) }
})
.map(|(id, img)| { let graph_id = rg.import_image(
( textures.get_texture(id)?,
id, Access {
rg.import_image( layout: vk::ImageLayout::GENERAL,
img, ..Access::undefined()
},
);
Some(ImageUpdate {
id,
graph_id,
dest_offset: pos.map(|p| (p[0] as u32, p[1] as u32)).unwrap_or_default(),
src_offset: (rect_x as u32, rect_y as u32),
size: (rect_width as u32, rect_height as u32),
})
})
.collect::<Vec<_>>();
let writes = updates
.iter()
.map(|update| {
(
update.graph_id,
Access { Access {
layout: vk::ImageLayout::GENERAL, layout: vk::ImageLayout::GENERAL,
..Access::undefined() ..Access::undefined()
}, },
),
) )
}) })
.collect::<BTreeMap<_, _>>(); .collect::<Vec<_>>();
let staging_buffer = rg.import_buffer(Arc::new(staging_buffer), Access::undefined()); let staging_buffer = rg.import_buffer(Arc::new(staging_buffer), Access::undefined());
let staging_image = rg.import_image(staging_image, Access::undefined()); let staging_image = rg.import_image(Arc::new(staging_image), Access::undefined());
let record = Box::new({ let record = Box::new({
let textures = textures.clone(); // let textures = textures.clone();
move |ctx: &RenderContext| -> crate::Result<()> { move |ctx: &RenderContext| -> crate::Result<()> {
let staging_image = ctx.get_image(staging_image).unwrap().clone(); let staging_image = ctx.get_image(staging_image).unwrap().clone();
let staging_buffer = ctx.get_buffer(staging_buffer).unwrap(); let staging_buffer = ctx.get_buffer(staging_buffer).unwrap();
for (id, (offset, _, rect)) in aliased_images {
tracing::trace!(
"record-prepass: fetching alias of prepass staging image id={id:?}"
);
let alias = staging_image.get_alias(ImageDesc {
name: Some(format!("egui-prepass-staging-aliased-{id:?}v").into()),
format: vk::Format::R8G8B8A8_UNORM,
extent: vk::Extent3D {
width: rect.width() as u32,
height: rect.height() as u32,
depth: 1,
},
usage: vk::ImageUsageFlags::TRANSFER_SRC | vk::ImageUsageFlags::TRANSFER_DST,
queue_families: device::QueueFlags::empty(),
..Default::default()
})?;
let texture = textures.get(&id).and_then(|id| ctx.get_image(*id)).unwrap();
let image: Barrier = image_barrier( let image: Barrier = image_barrier(
alias.raw(), staging_image.raw(),
alias.format(), staging_image.format(),
Access { Access {
stage: vk::PipelineStageFlags2::NONE, stage: vk::PipelineStageFlags2::NONE,
mask: vk::AccessFlags2::empty(), mask: vk::AccessFlags2::empty(),
@ -237,25 +262,25 @@ pub fn egui_pre_pass(
ctx.cmd.copy_buffer_to_image( ctx.cmd.copy_buffer_to_image(
staging_buffer.raw(), staging_buffer.raw(),
alias.raw(), staging_image.raw(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[vk::BufferImageCopy { &[vk::BufferImageCopy {
buffer_offset: offset as u64, buffer_offset: 0,
buffer_row_length: alias.width(), buffer_row_length: staging_image.width(),
buffer_image_height: alias.height(), buffer_image_height: staging_image.height(),
image_subresource: vk::ImageSubresourceLayers::default() image_subresource: vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR) .aspect_mask(vk::ImageAspectFlags::COLOR)
.base_array_layer(0) .base_array_layer(0)
.mip_level(0) .mip_level(0)
.layer_count(1), .layer_count(1),
image_offset: vk::Offset3D { x: 0, y: 0, z: 0 }, image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
image_extent: alias.size(), image_extent: staging_image.size(),
}], }],
); );
let from_barrier = image_barrier( let from_barrier: Barrier = image_barrier(
alias.raw(), staging_image.raw(),
alias.format(), staging_image.format(),
Access { Access {
stage: vk::PipelineStageFlags2::TRANSFER, stage: vk::PipelineStageFlags2::TRANSFER,
mask: vk::AccessFlags2::TRANSFER_WRITE, mask: vk::AccessFlags2::TRANSFER_WRITE,
@ -267,9 +292,26 @@ pub fn egui_pre_pass(
layout: vk::ImageLayout::TRANSFER_SRC_OPTIMAL, layout: vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
}, },
None, None,
); )
.into();
let to_barrier = image_barrier( unsafe {
ctx.device
.dev()
.cmd_pipeline_barrier2(ctx.cmd.buffer(), &((&from_barrier).into()));
}
for ImageUpdate {
graph_id,
dest_offset,
src_offset,
size,
..
} in &updates
{
let texture = ctx.get_image(*graph_id).unwrap();
let to_barrier: Barrier = image_barrier(
texture.raw(), texture.raw(),
texture.format(), texture.format(),
Access { Access {
@ -281,7 +323,7 @@ pub fn egui_pre_pass(
// overwritten, so the layout doesn't matter, and else // overwritten, so the layout doesn't matter, and else
// the layout will be `GENERAL` because the texture was // the layout will be `GENERAL` because the texture was
// previously written to. // previously written to.
layout: if alias.size() == texture.size() { layout: if staging_image.size() == texture.size() {
vk::ImageLayout::UNDEFINED vk::ImageLayout::UNDEFINED
} else { } else {
vk::ImageLayout::GENERAL vk::ImageLayout::GENERAL
@ -293,17 +335,17 @@ pub fn egui_pre_pass(
layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL, layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
}, },
None, None,
); )
.into();
unsafe { unsafe {
ctx.device.dev().cmd_pipeline_barrier2( ctx.device
ctx.cmd.buffer(), .dev()
&vk::DependencyInfo::default() .cmd_pipeline_barrier2(ctx.cmd.buffer(), &((&to_barrier).into()));
.image_memory_barriers(&[from_barrier, to_barrier]),
);
} }
ctx.cmd.copy_images( ctx.cmd.copy_images(
alias.raw(), staging_image.raw(),
vk::ImageLayout::TRANSFER_SRC_OPTIMAL, vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
texture.raw(), texture.raw(),
vk::ImageLayout::TRANSFER_DST_OPTIMAL, vk::ImageLayout::TRANSFER_DST_OPTIMAL,
@ -313,18 +355,26 @@ pub fn egui_pre_pass(
.base_array_layer(0) .base_array_layer(0)
.mip_level(0) .mip_level(0)
.layer_count(1), .layer_count(1),
src_offset: vk::Offset3D { x: 0, y: 0, z: 0 }, src_offset: vk::Offset3D {
x: src_offset.0 as i32,
y: src_offset.1 as i32,
z: 0,
},
dst_subresource: vk::ImageSubresourceLayers::default() dst_subresource: vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR) .aspect_mask(vk::ImageAspectFlags::COLOR)
.base_array_layer(0) .base_array_layer(0)
.mip_level(0) .mip_level(0)
.layer_count(1), .layer_count(1),
dst_offset: vk::Offset3D { dst_offset: vk::Offset3D {
x: rect.top_left().x, x: dest_offset.0 as i32,
y: rect.top_left().y, y: dest_offset.1 as i32,
z: 0, z: 0,
}, },
extent: alias.size(), extent: vk::Extent3D {
width: size.0,
height: size.1,
depth: 0,
},
}], }],
); );
@ -368,18 +418,7 @@ pub fn egui_pre_pass(
(staging_image, Access::undefined()), (staging_image, Access::undefined()),
] ]
.to_vec(), .to_vec(),
writes: textures writes,
.values()
.map(|id| {
(
*id,
Access {
layout: vk::ImageLayout::GENERAL,
..Access::undefined()
},
)
})
.collect(),
record: Some(record), record: Some(record),
}); });
Ok(()) Ok(())

View file

@ -154,6 +154,7 @@ impl ImageInner {
pub struct Image { pub struct Image {
image: ImageInner, image: ImageInner,
desc: ImageDesc, desc: ImageDesc,
#[allow(dead_code)]
views: Mutex<WeakVec<ImageView>>, views: Mutex<WeakVec<ImageView>>,
} }
@ -529,6 +530,7 @@ impl ImageViewDesc {
} }
} }
#[allow(dead_code)]
pub(crate) fn hash_eq_copy(&self) -> Self { pub(crate) fn hash_eq_copy(&self) -> Self {
let &Self { let &Self {
flags, flags,
@ -630,6 +632,7 @@ impl PartialEq for ImageViewDesc {
#[derive(Debug)] #[derive(Debug)]
pub struct ImageView { pub struct ImageView {
view: DeviceObject<vk::ImageView>, view: DeviceObject<vk::ImageView>,
#[allow(dead_code)]
desc: ImageViewDesc, desc: ImageViewDesc,
image: Arc<Image>, image: Arc<Image>,
} }
@ -673,6 +676,7 @@ pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange = vk::ImageSubre
}; };
// copilot generated from spec: // copilot generated from spec:
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FormatClass { pub enum FormatClass {
Bits8, Bits8,

View file

@ -1,12 +1,11 @@
#![feature( #![feature(
closure_lifetime_binder,
negative_impls, negative_impls,
map_try_insert, map_try_insert,
debug_closure_helpers, debug_closure_helpers,
slice_partition_dedup slice_partition_dedup
)] )]
use std::{collections::HashMap, ffi::CStr, fmt::Debug, marker::PhantomData, sync::Arc}; use std::{collections::HashMap, fmt::Debug, sync::Arc};
use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
@ -35,7 +34,7 @@ pub mod sync;
mod text; mod text;
pub mod util; pub mod util;
use device::{Device, DeviceOwned, DeviceQueueFamilies}; use device::{Device, DeviceOwned};
mod texture { mod texture {
use std::{collections::BTreeMap, sync::Arc}; use std::{collections::BTreeMap, sync::Arc};
@ -124,22 +123,6 @@ pub enum Error {
pub type Result<T> = core::result::Result<T, Error>; pub type Result<T> = core::result::Result<T, Error>;
struct VkNameList<'a> {
names: Vec<*const i8>,
_pd: PhantomData<&'a ()>,
}
impl<'a> VkNameList<'a> {
fn from_strs(strs: &[&'a CStr]) -> Self {
let names = strs.iter().map(|str| str.as_ptr()).collect::<Vec<_>>();
Self {
names,
_pd: PhantomData,
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(dead_code)] #[allow(dead_code)]
struct DeviceExtension<'a> { struct DeviceExtension<'a> {
@ -147,13 +130,6 @@ struct DeviceExtension<'a> {
version: u32, version: u32,
} }
fn make_extention_properties(name: &CStr, version: u32) -> vk::ExtensionProperties {
vk::ExtensionProperties::default()
.spec_version(version)
.extension_name(name)
.unwrap()
}
/// returns true if lhs and rhs have the same name and lhs spec_version is less /// returns true if lhs and rhs have the same name and lhs spec_version is less
/// than or equal to rhs spec_version /// than or equal to rhs spec_version
#[allow(dead_code)] #[allow(dead_code)]
@ -548,7 +524,7 @@ impl PhysicalDeviceFeatures {
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct PhysicalDeviceProperties { pub struct PhysicalDeviceProperties {
/// Extensions supported by the device, as reported by `enumerate_device_extension_properties`. /// Extensions supported by the device, as reported by `enumerate_device_extension_properties`.
supported_extensions: Vec<vk::ExtensionProperties>, supported_extensions: Vec<vk::ExtensionProperties>,
/// Vulkan 1.0 properties. /// Vulkan 1.0 properties.
@ -661,14 +637,6 @@ impl PhysicalDeviceProperties {
} }
} }
#[derive(Debug)]
pub struct PhysicalDevice {
pdev: vk::PhysicalDevice,
queue_families: DeviceQueueFamilies,
#[allow(dead_code)]
properties: PhysicalDeviceProperties,
}
pub(crate) use instance::DebugUtils; pub(crate) use instance::DebugUtils;
pub use instance::{DebugUtilsCreateInfo, Instance}; pub use instance::{DebugUtilsCreateInfo, Instance};

View file

@ -164,6 +164,9 @@ impl DeviceQueues {
core::slice::from_ref(&self.graphics.family.index) core::slice::from_ref(&self.graphics.family.index)
} }
/// # Safety
///
/// The caller must ensure that the queues aren't already locked when calling this function.
pub unsafe fn lock(&self) { pub unsafe fn lock(&self) {
core::mem::forget(( core::mem::forget((
self.graphics.inner.lock.lock(), self.graphics.inner.lock.lock(),
@ -172,6 +175,9 @@ impl DeviceQueues {
)); ));
} }
/// # Safety
///
/// The caller must have acquired and have logical ownership of the lock on the queues.
pub unsafe fn unlock(&self) { pub unsafe fn unlock(&self) {
unsafe { unsafe {
self.graphics.inner.lock.force_unlock(); self.graphics.inner.lock.force_unlock();
@ -190,31 +196,29 @@ pub struct DeviceQueueInfos {
impl DeviceQueueInfos { impl DeviceQueueInfos {
const PRIORITIES: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; const PRIORITIES: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
pub fn into_create_infos(&self) -> Vec<vk::DeviceQueueCreateInfo> { pub fn into_create_infos(&self) -> Vec<vk::DeviceQueueCreateInfo<'_>> {
let families = self.queue_family_indices(); let families = self.queue_family_indices();
let create_infos = families families
.into_iter() .into_iter()
.map(|(index, count)| { .map(|(index, count)| {
vk::DeviceQueueCreateInfo::default() vk::DeviceQueueCreateInfo::default()
.queue_family_index(index) .queue_family_index(index)
.queue_priorities(&Self::PRIORITIES[..count as usize]) .queue_priorities(&Self::PRIORITIES[..count as usize])
}) })
.collect(); .collect()
create_infos
} }
fn queue_family_indices(&self) -> HashMap<u32, u32> { fn queue_family_indices(&self) -> HashMap<u32, u32> {
let mut families = HashMap::new(); let mut families = HashMap::new();
families.insert(self.graphics.index, 1); families.insert(self.graphics.index, 1);
self.compute.map(|compute| { if let Some(compute) = self.compute {
*families.entry(compute.index).or_insert(0) += 1; *families.entry(compute.index).or_insert(0) += 1;
}); }
self.transfer.map(|transfer| { if let Some(transfer) = self.transfer {
*families.entry(transfer.index).or_insert(0) += 1; *families.entry(transfer.index).or_insert(0) += 1;
}); }
families families
} }

View file

@ -209,6 +209,7 @@ impl Surface {
Ok(()) Ok(())
} }
#[allow(dead_code)]
fn get_fallback_swapchain_configuration( fn get_fallback_swapchain_configuration(
&self, &self,
instance: &Instance, instance: &Instance,
@ -366,7 +367,7 @@ impl Swapchain {
surface.validate_swapchain_configuration(&device.instance, &device.adapter, &mut config)?; surface.validate_swapchain_configuration(&device.instance, &device.adapter, &mut config)?;
let surface_caps = device let surface_caps = device
.instance .instance
.get_adapter_surface_capabilities(device.adapter.pdev, &surface)?; .get_adapter_surface_capabilities(device.adapter.pdev, surface)?;
let functor = device let functor = device
.device_extensions .device_extensions
@ -532,7 +533,7 @@ impl Swapchain {
.await?; .await?;
let idx = idx as usize; let idx = idx as usize;
let image = self.images[idx].clone(); let image = self.images[idx];
let image = Arc::new(images::Image::from_swapchain_image(image, &self)); let image = Arc::new(images::Image::from_swapchain_image(image, &self));
let view = image.create_view(ImageViewDesc { let view = image.create_view(ImageViewDesc {
name: Some(format!("swapchain-{:x}-image-view-{idx}", self.raw().as_raw()).into()), name: Some(format!("swapchain-{:x}-image-view-{idx}", self.raw().as_raw()).into()),
@ -638,7 +639,6 @@ impl Swapchain {
Ok((swapchain, images)) Ok((swapchain, images))
} }
} }
static SWAPCHAIN_COUNT: AtomicU64 = AtomicU64::new(0);
#[derive(Debug)] #[derive(Debug)]
#[must_use = "This struct represents an acquired image from the Swapchain and #[must_use = "This struct represents an acquired image from the Swapchain and
@ -702,6 +702,7 @@ impl SwapchainFrame {
} }
} }
#[allow(dead_code)]
fn current_extent_or_clamped( fn current_extent_or_clamped(
caps: &vk::SurfaceCapabilitiesKHR, caps: &vk::SurfaceCapabilitiesKHR,
fallback: vk::Extent2D, fallback: vk::Extent2D,
@ -867,7 +868,7 @@ mod tests {
#[test] #[test]
fn async_swapchain_acquiring() { fn async_swapchain_acquiring() {
let (_dev, surface) = create_headless_vk().expect("init"); let (_dev, surface) = create_headless_vk().expect("init");
let ctx = Arc::new(surface); let _ctx = Arc::new(surface);
// let (rx, handle) = ctx.clone().images(); // let (rx, handle) = ctx.clone().images();
// eprintln!("hello world!"); // eprintln!("hello world!");

View file

@ -246,7 +246,7 @@ impl Fence {
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum SemaphoreType { pub enum SemaphoreType {
Binary, Binary,
Timeline(u64), Timeline(u64),
} }

View file

@ -7,6 +7,7 @@ use ash::vk;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
pub(crate) mod weak_vec { pub(crate) mod weak_vec {
#![allow(dead_code)]
//! Module containing the [`WeakVec`] API. //! Module containing the [`WeakVec`] API.
use std::{sync::Weak, vec::Vec}; use std::{sync::Weak, vec::Vec};