idek so much when i thought i was only doing egui integration
egui cant draw yet, but textures are loaded/updated
This commit is contained in:
parent
f7e6a92018
commit
f0fff72bce
|
@ -12,7 +12,7 @@ anyhow = "1.0.89"
|
||||||
ash = "0.38.0"
|
ash = "0.38.0"
|
||||||
ash-window = "0.13.0"
|
ash-window = "0.13.0"
|
||||||
glam = "0.29.0"
|
glam = "0.29.0"
|
||||||
thiserror = "1.0.64"
|
thiserror = "2.0"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
vk-mem = "0.4.0"
|
vk-mem = "0.4.0"
|
||||||
|
@ -28,5 +28,5 @@ rayon = "1.10"
|
||||||
winit = {version = "0.30.5", features = ["rwh_06"]}
|
winit = {version = "0.30.5", features = ["rwh_06"]}
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
|
|
||||||
egui = "0.30.0"
|
egui = "0.30"
|
||||||
egui_winit_platform = "0.24.0"
|
egui_winit_platform = "0.25"
|
|
@ -11,3 +11,4 @@ renderer = { path = "../renderer" }
|
||||||
|
|
||||||
egui = { workspace = true }
|
egui = { workspace = true }
|
||||||
egui_winit_platform = { workspace = true }
|
egui_winit_platform = { workspace = true }
|
||||||
|
egui_demo_lib = "0.30.0"
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::collections::BTreeMap;
|
||||||
|
|
||||||
use renderer::Renderer;
|
use renderer::Renderer;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
use winit::{
|
use winit::{
|
||||||
application::ApplicationHandler,
|
application::ApplicationHandler,
|
||||||
dpi::{LogicalSize, PhysicalSize},
|
dpi::{LogicalSize, PhysicalSize},
|
||||||
|
@ -14,10 +15,7 @@ use winit::{
|
||||||
struct WindowState {
|
struct WindowState {
|
||||||
window: Window,
|
window: Window,
|
||||||
egui_platform: egui_winit_platform::Platform,
|
egui_platform: egui_winit_platform::Platform,
|
||||||
}
|
demo_app: egui_demo_lib::DemoWindows,
|
||||||
|
|
||||||
struct EguiRenderState {
|
|
||||||
textures: BTreeMap<u64, ()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WinitState {
|
struct WinitState {
|
||||||
|
@ -37,20 +35,13 @@ impl WinitState {
|
||||||
window_attrs: WindowAttributes::default()
|
window_attrs: WindowAttributes::default()
|
||||||
.with_title(window_title)
|
.with_title(window_title)
|
||||||
.with_resizable(true)
|
.with_resizable(true)
|
||||||
.with_inner_size(LogicalSize::new(
|
.with_inner_size(LogicalSize::new(Self::BASE_WIDTH, Self::BASE_HEIGHT)),
|
||||||
Self::BASE_WIDTH,
|
|
||||||
Self::BASE_HEIGHT,
|
|
||||||
)),
|
|
||||||
// TODO: pass down this error and add some kind of error handling UI or dump
|
// TODO: pass down this error and add some kind of error handling UI or dump
|
||||||
renderer: Renderer::new(display.as_raw()).expect("renderer"),
|
renderer: Renderer::new(display.as_raw()).expect("renderer"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_final_resize(
|
fn handle_final_resize(&mut self, window_id: WindowId, new_size: PhysicalSize<u32>) {
|
||||||
&mut self,
|
|
||||||
window_id: WindowId,
|
|
||||||
new_size: PhysicalSize<u32>,
|
|
||||||
) {
|
|
||||||
_ = (window_id, new_size);
|
_ = (window_id, new_size);
|
||||||
info!("TODO: implement resize events");
|
info!("TODO: implement resize events");
|
||||||
if let Some(ctx) = self.renderer.window_contexts.get_mut(&window_id) {
|
if let Some(ctx) = self.renderer.window_contexts.get_mut(&window_id) {
|
||||||
|
@ -71,21 +62,17 @@ impl WinitState {
|
||||||
if let Some(window) = self.windows2.get_mut(&window_id) {
|
if let Some(window) = self.windows2.get_mut(&window_id) {
|
||||||
// egui
|
// egui
|
||||||
|
|
||||||
window.egui_platform.begin_frame();
|
window.egui_platform.begin_pass();
|
||||||
let output = window.egui_platform.end_frame(Some(&window.window));
|
window.demo_app.ui(&window.egui_platform.context());
|
||||||
|
let output = window.egui_platform.end_pass(Some(&window.window));
|
||||||
|
|
||||||
let _draw_data = window
|
self.renderer
|
||||||
.egui_platform
|
.draw_egui(&window.egui_platform.context(), output);
|
||||||
.context()
|
|
||||||
.tessellate(output.shapes, output.pixels_per_point);
|
|
||||||
|
|
||||||
// rendering
|
// rendering
|
||||||
self.renderer
|
self.renderer
|
||||||
.debug_draw(
|
.debug_draw(&window_id, || { // window.window.pre_present_notify()
|
||||||
&window_id,
|
})
|
||||||
|| { // window.window.pre_present_notify()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("drawing");
|
.expect("drawing");
|
||||||
window.window.request_redraw();
|
window.window.request_redraw();
|
||||||
}
|
}
|
||||||
|
@ -98,10 +85,7 @@ impl WinitState {
|
||||||
self.renderer.window_contexts.remove(&window_id);
|
self.renderer.window_contexts.remove(&window_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_window(
|
fn create_window(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
&mut self,
|
|
||||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
|
||||||
) {
|
|
||||||
let window = event_loop
|
let window = event_loop
|
||||||
.create_window(
|
.create_window(
|
||||||
self.window_attrs
|
self.window_attrs
|
||||||
|
@ -132,6 +116,7 @@ impl WinitState {
|
||||||
window_id,
|
window_id,
|
||||||
WindowState {
|
WindowState {
|
||||||
window,
|
window,
|
||||||
|
demo_app: egui_demo_lib::DemoWindows::default(),
|
||||||
egui_platform: egui_winit_platform::Platform::new(
|
egui_platform: egui_winit_platform::Platform::new(
|
||||||
egui_winit_platform::PlatformDescriptor {
|
egui_winit_platform::PlatformDescriptor {
|
||||||
physical_width: size.width,
|
physical_width: size.width,
|
||||||
|
@ -152,10 +137,7 @@ impl ApplicationHandler for WinitState {
|
||||||
self.create_window(event_loop);
|
self.create_window(event_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn about_to_wait(
|
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
&mut self,
|
|
||||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
|
||||||
) {
|
|
||||||
tracing::info!("winit::about_to_wait");
|
tracing::info!("winit::about_to_wait");
|
||||||
for (&window, &resize) in self.last_resize_events.clone().iter() {
|
for (&window, &resize) in self.last_resize_events.clone().iter() {
|
||||||
self.handle_final_resize(window, resize);
|
self.handle_final_resize(window, resize);
|
||||||
|
@ -192,9 +174,7 @@ impl ApplicationHandler for WinitState {
|
||||||
event:
|
event:
|
||||||
winit::event::KeyEvent {
|
winit::event::KeyEvent {
|
||||||
physical_key:
|
physical_key:
|
||||||
winit::keyboard::PhysicalKey::Code(
|
winit::keyboard::PhysicalKey::Code(winit::keyboard::KeyCode::KeyQ),
|
||||||
winit::keyboard::KeyCode::KeyQ,
|
|
||||||
),
|
|
||||||
state: ElementState::Pressed,
|
state: ElementState::Pressed,
|
||||||
repeat: false,
|
repeat: false,
|
||||||
..
|
..
|
||||||
|
@ -207,9 +187,7 @@ impl ApplicationHandler for WinitState {
|
||||||
event:
|
event:
|
||||||
winit::event::KeyEvent {
|
winit::event::KeyEvent {
|
||||||
physical_key:
|
physical_key:
|
||||||
winit::keyboard::PhysicalKey::Code(
|
winit::keyboard::PhysicalKey::Code(winit::keyboard::KeyCode::Space),
|
||||||
winit::keyboard::KeyCode::Space,
|
|
||||||
),
|
|
||||||
state: ElementState::Pressed,
|
state: ElementState::Pressed,
|
||||||
repeat: false,
|
repeat: false,
|
||||||
..
|
..
|
||||||
|
@ -247,7 +225,9 @@ impl ApplicationHandler for WinitState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tracing_subscriber::fmt().init();
|
let _ = tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.init();
|
||||||
let ev = EventLoop::new().unwrap();
|
let ev = EventLoop::new().unwrap();
|
||||||
ev.set_control_flow(winit::event_loop::ControlFlow::Poll);
|
ev.set_control_flow(winit::event_loop::ControlFlow::Poll);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ anyhow = "1.0.89"
|
||||||
ash = "0.38.0"
|
ash = "0.38.0"
|
||||||
ash-window = "0.13.0"
|
ash-window = "0.13.0"
|
||||||
glam = "0.29.0"
|
glam = "0.29.0"
|
||||||
thiserror = "1.0.64"
|
thiserror = {workspace = true}
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
vk-mem = "0.4.0"
|
vk-mem = "0.4.0"
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::{ops::Deref, sync::Arc};
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use ash::{prelude::VkResult, vk};
|
use ash::{prelude::VkResult, vk};
|
||||||
use vk_mem::Alloc;
|
use vk_mem::Alloc;
|
||||||
|
@ -33,14 +36,15 @@ impl Buffer {
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags,
|
alloc_flags: vk_mem::AllocationCreateFlags,
|
||||||
) -> VkResult<Arc<Self>> {
|
) -> VkResult<Arc<Self>> {
|
||||||
let sharing_mode = if queue_families.len() > 1 {
|
let sharing_mode = if queue_families.len() > 1 {
|
||||||
vk::SharingMode::EXCLUSIVE
|
|
||||||
} else {
|
|
||||||
vk::SharingMode::CONCURRENT
|
vk::SharingMode::CONCURRENT
|
||||||
|
} else {
|
||||||
|
vk::SharingMode::EXCLUSIVE
|
||||||
};
|
};
|
||||||
|
|
||||||
let (buffer, allocation) = unsafe {
|
let (buffer, allocation) = unsafe {
|
||||||
device.alloc().create_buffer(
|
device.alloc().create_buffer(
|
||||||
&vk::BufferCreateInfo::default()
|
&vk::BufferCreateInfo::default()
|
||||||
|
.size(size as u64)
|
||||||
.usage(usage)
|
.usage(usage)
|
||||||
.queue_family_indices(queue_families)
|
.queue_family_indices(queue_families)
|
||||||
.sharing_mode(sharing_mode),
|
.sharing_mode(sharing_mode),
|
||||||
|
@ -66,17 +70,32 @@ impl Buffer {
|
||||||
pub fn map(&mut self) -> VkResult<MappedBuffer<'_>> {
|
pub fn map(&mut self) -> VkResult<MappedBuffer<'_>> {
|
||||||
let bytes = unsafe {
|
let bytes = unsafe {
|
||||||
let data = self.device.alloc().map_memory(&mut self.allocation)?;
|
let data = self.device.alloc().map_memory(&mut self.allocation)?;
|
||||||
let slice = core::slice::from_raw_parts(data, self.size as usize);
|
let slice = core::slice::from_raw_parts_mut(data, self.size as usize);
|
||||||
|
|
||||||
slice
|
slice
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(MappedBuffer { bytes })
|
Ok(MappedBuffer { inner: self, bytes })
|
||||||
|
}
|
||||||
|
pub fn buffer(&self) -> vk::Buffer {
|
||||||
|
self.buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MappedBuffer<'a> {
|
pub struct MappedBuffer<'a> {
|
||||||
bytes: &'a [u8],
|
bytes: &'a mut [u8],
|
||||||
|
inner: &'a mut Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for MappedBuffer<'_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.inner
|
||||||
|
.device
|
||||||
|
.alloc()
|
||||||
|
.unmap_memory(&mut self.inner.allocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for MappedBuffer<'_> {
|
impl Deref for MappedBuffer<'_> {
|
||||||
|
@ -86,3 +105,9 @@ impl Deref for MappedBuffer<'_> {
|
||||||
self.bytes
|
self.bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DerefMut for MappedBuffer<'_> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
self.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
buffers::Buffer,
|
buffers::Buffer,
|
||||||
images::{Image2D, QueueOwnership},
|
images::{Image2D, QueueOwnership},
|
||||||
sync::{self, FenceFuture},
|
sync::{self, FenceFuture},
|
||||||
util::{FormatExt, MutexExt},
|
util::{self, FormatExt, MutexExt},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Device, Queue};
|
use super::{Device, Queue};
|
||||||
|
@ -33,8 +33,7 @@ impl SingleUseCommandPool {
|
||||||
.queue_family_index(queue.family())
|
.queue_family_index(queue.family())
|
||||||
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
||||||
|
|
||||||
let pool =
|
let pool = unsafe { device.dev().create_command_pool(&pool_info, None)? };
|
||||||
unsafe { device.dev().create_command_pool(&pool_info, None)? };
|
|
||||||
|
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
device,
|
device,
|
||||||
|
@ -68,18 +67,15 @@ impl !Sync for SingleUseCommand {}
|
||||||
impl Drop for SingleUseCommand {
|
impl Drop for SingleUseCommand {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.pool.pool.with_locked(|&pool| {
|
self.pool
|
||||||
self.device.dev().free_command_buffers(pool, &[self.buffer])
|
.pool
|
||||||
})
|
.with_locked(|&pool| self.device.dev().free_command_buffers(pool, &[self.buffer]))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleUseCommand {
|
impl SingleUseCommand {
|
||||||
pub fn new(
|
pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> {
|
||||||
device: Device,
|
|
||||||
pool: Arc<SingleUseCommandPool>,
|
|
||||||
) -> VkResult<Self> {
|
|
||||||
let buffer = unsafe {
|
let buffer = unsafe {
|
||||||
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
||||||
.command_buffer_count(1)
|
.command_buffer_count(1)
|
||||||
|
@ -154,6 +150,52 @@ impl SingleUseCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blit_images(
|
||||||
|
&self,
|
||||||
|
src: &Image2D,
|
||||||
|
src_region: util::Rect2D,
|
||||||
|
dst: &Image2D,
|
||||||
|
dst_region: util::Rect2D,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.device.dev().cmd_blit_image(
|
||||||
|
self.buffer,
|
||||||
|
src.image(),
|
||||||
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
|
dst.image(),
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
&[vk::ImageBlit::default()
|
||||||
|
.src_subresource(
|
||||||
|
vk::ImageSubresourceLayers::default()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.layer_count(1),
|
||||||
|
)
|
||||||
|
.dst_subresource(
|
||||||
|
vk::ImageSubresourceLayers::default()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.layer_count(1),
|
||||||
|
)
|
||||||
|
.src_offsets(src_region.into_offsets_3d())
|
||||||
|
.dst_offsets(dst_region.into_offsets_3d())],
|
||||||
|
vk::Filter::LINEAR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy_buffer_to_image(
|
||||||
|
&self,
|
||||||
|
buffer: vk::Buffer,
|
||||||
|
image: vk::Image,
|
||||||
|
layout: vk::ImageLayout,
|
||||||
|
regions: &[vk::BufferImageCopy],
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.dev()
|
||||||
|
.cmd_copy_buffer_to_image(self.buffer, buffer, image, layout, regions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clear_color_image(
|
pub fn clear_color_image(
|
||||||
&self,
|
&self,
|
||||||
image: vk::Image,
|
image: vk::Image,
|
||||||
|
@ -194,15 +236,12 @@ impl SingleUseCommand {
|
||||||
unsafe { self.device.dev().end_command_buffer(self.buffer)? };
|
unsafe { self.device.dev().end_command_buffer(self.buffer)? };
|
||||||
|
|
||||||
let buffers = [self.buffer];
|
let buffers = [self.buffer];
|
||||||
let mut submit_info =
|
let mut submit_info = vk::SubmitInfo::default().command_buffers(&buffers);
|
||||||
vk::SubmitInfo::default().command_buffers(&buffers);
|
|
||||||
|
|
||||||
if let Some(semaphore) = signal.as_ref() {
|
if let Some(semaphore) = signal.as_ref() {
|
||||||
// SAFETY: T and [T;1] have the same layout
|
// SAFETY: T and [T;1] have the same layout
|
||||||
submit_info = submit_info.signal_semaphores(unsafe {
|
submit_info = submit_info.signal_semaphores(unsafe {
|
||||||
core::mem::transmute::<&vk::Semaphore, &[vk::Semaphore; 1]>(
|
core::mem::transmute::<&vk::Semaphore, &[vk::Semaphore; 1]>(semaphore)
|
||||||
semaphore,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some((semaphore, stage)) = wait.as_ref() {
|
if let Some((semaphore, stage)) = wait.as_ref() {
|
||||||
|
|
314
crates/renderer/src/device.rs
Normal file
314
crates/renderer/src/device.rs
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
use std::{borrow::Cow, collections::BTreeMap, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
|
use ash::{khr, prelude::VkResult, vk};
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use tinyvec::{array_vec, ArrayVec};
|
||||||
|
|
||||||
|
use crate::{sync, Instance, PhysicalDevice, Queue};
|
||||||
|
|
||||||
|
#[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),
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct DeviceWrapper(ash::Device);
|
||||||
|
|
||||||
|
impl Deref for DeviceWrapper {
|
||||||
|
type Target = ash::Device;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DeviceWrapper {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
_ = self.0.device_wait_idle();
|
||||||
|
self.0.destroy_device(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DeviceInner {
|
||||||
|
alloc: vk_mem::Allocator,
|
||||||
|
device: DeviceWrapper,
|
||||||
|
physical: PhysicalDevice,
|
||||||
|
instance: Arc<Instance>,
|
||||||
|
swapchain: khr::swapchain::Device,
|
||||||
|
debug_utils: ash::ext::debug_utils::Device,
|
||||||
|
allocated_queues: BTreeMap<(u32, u32), Queue>,
|
||||||
|
// these are resident in allocated_queues, and may in fact be clones of each
|
||||||
|
// other, for ease of access
|
||||||
|
main_queue: Queue,
|
||||||
|
compute_queue: Queue,
|
||||||
|
transfer_queue: Queue,
|
||||||
|
present_queue: Queue,
|
||||||
|
sync_threadpool: sync::SyncThreadpool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for DeviceInner {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("DeviceInner")
|
||||||
|
.field("device", &self.device.handle())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Device(Arc<DeviceInner>);
|
||||||
|
pub type WeakDevice = std::sync::Weak<DeviceInner>;
|
||||||
|
|
||||||
|
impl Device {
|
||||||
|
pub fn new(
|
||||||
|
instance: Arc<Instance>,
|
||||||
|
physical: PhysicalDevice,
|
||||||
|
mut features: crate::PhysicalDeviceFeatures,
|
||||||
|
) -> VkResult<Self> {
|
||||||
|
// we have 4 queues at most: graphics, compute, transfer, present
|
||||||
|
let priorities = [1.0f32; 4];
|
||||||
|
|
||||||
|
let queue_infos = physical
|
||||||
|
.queue_families
|
||||||
|
.families
|
||||||
|
.iter()
|
||||||
|
.map(|&(family, queues)| {
|
||||||
|
vk::DeviceQueueCreateInfo::default()
|
||||||
|
.queue_family_index(family)
|
||||||
|
.queue_priorities(&priorities[..queues as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let extensions = features
|
||||||
|
.device_extensions
|
||||||
|
.iter()
|
||||||
|
.map(|ext| ext.extension_name.as_ptr())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut features2 = features.features2();
|
||||||
|
let device_info = vk::DeviceCreateInfo::default()
|
||||||
|
.queue_create_infos(&queue_infos)
|
||||||
|
.enabled_extension_names(&extensions)
|
||||||
|
.push_next(&mut features2);
|
||||||
|
|
||||||
|
let device = unsafe {
|
||||||
|
let device = instance
|
||||||
|
.instance
|
||||||
|
.create_device(physical.pdev, &device_info, None)?;
|
||||||
|
|
||||||
|
let allocated_queues = queue_infos
|
||||||
|
.iter()
|
||||||
|
.flat_map(|info| {
|
||||||
|
(0..info.queue_count).map(|i| {
|
||||||
|
(
|
||||||
|
(info.queue_family_index, i),
|
||||||
|
Queue::new(&device, info.queue_family_index, i),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<BTreeMap<_, _>>();
|
||||||
|
|
||||||
|
let get_queue =
|
||||||
|
|(family, index)| allocated_queues.get(&(family, index)).cloned().unwrap();
|
||||||
|
|
||||||
|
let main_queue = get_queue(physical.queue_families.graphics);
|
||||||
|
let present_queue = get_queue(physical.queue_families.present);
|
||||||
|
let compute_queue = get_queue(physical.queue_families.async_compute);
|
||||||
|
let transfer_queue = get_queue(physical.queue_families.transfer);
|
||||||
|
|
||||||
|
let alloc_info =
|
||||||
|
vk_mem::AllocatorCreateInfo::new(&instance.instance, &device, physical.pdev);
|
||||||
|
|
||||||
|
let alloc = unsafe { vk_mem::Allocator::new(alloc_info)? };
|
||||||
|
|
||||||
|
DeviceInner {
|
||||||
|
device: DeviceWrapper(device.clone()),
|
||||||
|
physical,
|
||||||
|
swapchain: khr::swapchain::Device::new(&instance.instance, &device),
|
||||||
|
debug_utils: ash::ext::debug_utils::Device::new(&instance.instance, &device),
|
||||||
|
instance,
|
||||||
|
alloc,
|
||||||
|
allocated_queues,
|
||||||
|
main_queue,
|
||||||
|
present_queue,
|
||||||
|
compute_queue,
|
||||||
|
transfer_queue,
|
||||||
|
sync_threadpool: sync::SyncThreadpool::new(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self(Arc::new(device)))
|
||||||
|
}
|
||||||
|
pub fn sync_threadpool(&self) -> &sync::SyncThreadpool {
|
||||||
|
&self.0.sync_threadpool
|
||||||
|
}
|
||||||
|
pub fn weak(&self) -> WeakDevice {
|
||||||
|
Arc::downgrade(&self.0)
|
||||||
|
}
|
||||||
|
pub fn alloc(&self) -> &vk_mem::Allocator {
|
||||||
|
&self.0.alloc
|
||||||
|
}
|
||||||
|
pub fn dev(&self) -> &ash::Device {
|
||||||
|
&self.0.device
|
||||||
|
}
|
||||||
|
pub fn swapchain(&self) -> &khr::swapchain::Device {
|
||||||
|
&self.0.swapchain
|
||||||
|
}
|
||||||
|
pub fn debug_utils(&self) -> &ash::ext::debug_utils::Device {
|
||||||
|
&self.0.debug_utils
|
||||||
|
}
|
||||||
|
pub fn queue_families(&self) -> &DeviceQueueFamilies {
|
||||||
|
&self.0.physical.queue_families
|
||||||
|
}
|
||||||
|
pub fn phy(&self) -> vk::PhysicalDevice {
|
||||||
|
self.0.physical.pdev
|
||||||
|
}
|
||||||
|
pub fn graphics_queue(&self) -> &Queue {
|
||||||
|
&self.0.main_queue
|
||||||
|
}
|
||||||
|
pub fn present_queue(&self) -> &Queue {
|
||||||
|
&self.0.present_queue
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn lock_queues(&self) {
|
||||||
|
// this is obviously awful, allocating for this
|
||||||
|
self.0
|
||||||
|
.allocated_queues
|
||||||
|
.values()
|
||||||
|
.for_each(|q| core::mem::forget(q.lock()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn unlock_queues(&self) {
|
||||||
|
self.0
|
||||||
|
.allocated_queues
|
||||||
|
.values()
|
||||||
|
.for_each(|q| unsafe { q.0.force_unlock() });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_queue_idle(&self, queue: &Queue) -> VkResult<()> {
|
||||||
|
tracing::warn!("locking queue {queue:?} and waiting for idle");
|
||||||
|
|
||||||
|
queue.with_locked(|q| unsafe { self.dev().queue_wait_idle(q) })?;
|
||||||
|
|
||||||
|
tracing::warn!("finished waiting: unlocking queue {queue:?}.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_idle(&self) -> VkResult<()> {
|
||||||
|
tracing::warn!("locking all queues and waiting for device to idle");
|
||||||
|
unsafe {
|
||||||
|
self.lock_queues();
|
||||||
|
self.dev().device_wait_idle()?;
|
||||||
|
self.unlock_queues();
|
||||||
|
}
|
||||||
|
tracing::warn!("finished waiting: unlocking all queues.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<khr::swapchain::Device> for Device {
|
||||||
|
fn as_ref(&self) -> &khr::swapchain::Device {
|
||||||
|
&self.0.swapchain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<ash::Device> for Device {
|
||||||
|
fn as_ref(&self) -> &ash::Device {
|
||||||
|
&self.0.device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DeviceAndQueues {
|
||||||
|
pub(crate) device: Device,
|
||||||
|
pub(crate) main_queue: Queue,
|
||||||
|
pub(crate) compute_queue: Queue,
|
||||||
|
pub(crate) transfer_queue: Queue,
|
||||||
|
pub(crate) present_queue: Queue,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<ash::Device> for DeviceAndQueues {
|
||||||
|
fn as_ref(&self) -> &ash::Device {
|
||||||
|
&self.device.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsRef<ash::khr::swapchain::Device> for DeviceAndQueues {
|
||||||
|
fn as_ref(&self) -> &ash::khr::swapchain::Device {
|
||||||
|
&self.device.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DeviceOwnedDebugObject<T> {
|
||||||
|
device: Device,
|
||||||
|
object: T,
|
||||||
|
name: Option<Cow<'static, str>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DeviceOwnedDebugObject<T> {
|
||||||
|
fn new<S: Into<Cow<'static, str>>>(
|
||||||
|
device: crate::Device,
|
||||||
|
object: T,
|
||||||
|
name: Option<S>,
|
||||||
|
) -> ash::prelude::VkResult<Self>
|
||||||
|
where
|
||||||
|
T: vk::Handle + Copy,
|
||||||
|
{
|
||||||
|
let name = name.map(Into::<Cow<_>>::into);
|
||||||
|
if let Some(name) = name.as_ref() {
|
||||||
|
let name =
|
||||||
|
std::ffi::CString::new(name.as_bytes()).unwrap_or(c"invalid name".to_owned());
|
||||||
|
unsafe {
|
||||||
|
device.debug_utils().set_debug_utils_object_name(
|
||||||
|
&vk::DebugUtilsObjectNameInfoEXT::default()
|
||||||
|
.object_handle(object)
|
||||||
|
.object_name(&name),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
device,
|
||||||
|
object,
|
||||||
|
name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dev(&self) -> &crate::Device {
|
||||||
|
&self.device
|
||||||
|
}
|
||||||
|
pub fn handle(&self) -> T
|
||||||
|
where
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
self.object
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use super::{Device, Queue};
|
||||||
use ash::{prelude::*, vk};
|
use ash::{prelude::*, vk};
|
||||||
use vk_mem::Alloc;
|
use vk_mem::Alloc;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Image2D {
|
pub struct Image2D {
|
||||||
device: Device,
|
device: Device,
|
||||||
size: vk::Extent2D,
|
size: vk::Extent2D,
|
||||||
|
@ -13,10 +14,12 @@ pub struct Image2D {
|
||||||
format: vk::Format,
|
format: vk::Format,
|
||||||
image: vk::Image,
|
image: vk::Image,
|
||||||
allocation: vk_mem::Allocation,
|
allocation: vk_mem::Allocation,
|
||||||
|
name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Image2D {
|
impl Drop for Image2D {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
tracing::debug!("destroying image {:?}", self);
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device
|
self.device
|
||||||
.alloc()
|
.alloc()
|
||||||
|
@ -36,6 +39,7 @@ impl Image2D {
|
||||||
usage: vk::ImageUsageFlags,
|
usage: vk::ImageUsageFlags,
|
||||||
memory_usage: vk_mem::MemoryUsage,
|
memory_usage: vk_mem::MemoryUsage,
|
||||||
alloc_flags: vk_mem::AllocationCreateFlags,
|
alloc_flags: vk_mem::AllocationCreateFlags,
|
||||||
|
name: Option<&str>,
|
||||||
) -> VkResult<Arc<Self>> {
|
) -> VkResult<Arc<Self>> {
|
||||||
let create_info = vk::ImageCreateInfo::default()
|
let create_info = vk::ImageCreateInfo::default()
|
||||||
.array_layers(array_layers)
|
.array_layers(array_layers)
|
||||||
|
@ -62,6 +66,19 @@ impl Image2D {
|
||||||
let (image, allocation) =
|
let (image, allocation) =
|
||||||
unsafe { device.alloc().create_image(&create_info, &alloc_info)? };
|
unsafe { device.alloc().create_image(&create_info, &alloc_info)? };
|
||||||
|
|
||||||
|
if let Some(name) = name {
|
||||||
|
let info = device.alloc().get_allocation_info(&allocation);
|
||||||
|
|
||||||
|
let name = std::ffi::CString::new(name).unwrap_or(c"invalid name".to_owned());
|
||||||
|
unsafe {
|
||||||
|
device.debug_utils().set_debug_utils_object_name(
|
||||||
|
&vk::DebugUtilsObjectNameInfoEXT::default()
|
||||||
|
.object_handle(info.device_memory)
|
||||||
|
.object_name(&name),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
size: extent,
|
size: extent,
|
||||||
mip_levels,
|
mip_levels,
|
||||||
|
@ -69,6 +86,7 @@ impl Image2D {
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
image,
|
image,
|
||||||
allocation,
|
allocation,
|
||||||
|
name: name.map(|s| s.to_owned()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,12 +94,6 @@ impl Image2D {
|
||||||
self.format
|
self.format
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_from_buffer(&self, buffer: &Buffer) {
|
|
||||||
unsafe {
|
|
||||||
// self.device.dev().cmd_copy_buffer_to_image(command_buffer, src_buffer, dst_image, dst_image_layout, regions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn view(
|
pub fn view(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
|
@ -101,8 +113,7 @@ impl Image2D {
|
||||||
.layer_count(1),
|
.layer_count(1),
|
||||||
);
|
);
|
||||||
|
|
||||||
let view =
|
let view = unsafe { device.dev().create_image_view(&create_info, None)? };
|
||||||
unsafe { device.dev().create_image_view(&create_info, None)? };
|
|
||||||
|
|
||||||
Ok(Arc::new(ImageView2D {
|
Ok(Arc::new(ImageView2D {
|
||||||
view,
|
view,
|
||||||
|
@ -114,6 +125,15 @@ impl Image2D {
|
||||||
pub fn image(&self) -> vk::Image {
|
pub fn image(&self) -> vk::Image {
|
||||||
self.image
|
self.image
|
||||||
}
|
}
|
||||||
|
pub fn size(&self) -> vk::Extent2D {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
pub fn width(&self) -> u32 {
|
||||||
|
self.size.width
|
||||||
|
}
|
||||||
|
pub fn height(&self) -> u32 {
|
||||||
|
self.size.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImageView2D {
|
pub struct ImageView2D {
|
||||||
|
@ -172,11 +192,10 @@ pub fn image_barrier<'a>(
|
||||||
.new_layout(new_layout)
|
.new_layout(new_layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange =
|
pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange = vk::ImageSubresourceRange {
|
||||||
vk::ImageSubresourceRange {
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
base_mip_level: 0,
|
||||||
base_mip_level: 0,
|
level_count: vk::REMAINING_MIP_LEVELS,
|
||||||
level_count: vk::REMAINING_MIP_LEVELS,
|
base_array_layer: 0,
|
||||||
base_array_layer: 0,
|
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
||||||
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
};
|
||||||
};
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,8 +14,9 @@ impl std::hash::Hash for Rgba {
|
||||||
std::num::FpCategory::Infinite | std::num::FpCategory::Zero => {
|
std::num::FpCategory::Infinite | std::num::FpCategory::Zero => {
|
||||||
(classify as u8, f.signum() as i8).hash(state)
|
(classify as u8, f.signum() as i8).hash(state)
|
||||||
}
|
}
|
||||||
std::num::FpCategory::Subnormal
|
std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => {
|
||||||
| std::num::FpCategory::Normal => f.to_bits().hash(state),
|
f.to_bits().hash(state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.0.map(|f| hash_f32(state, f));
|
self.0.map(|f| hash_f32(state, f));
|
||||||
|
|
|
@ -45,17 +45,15 @@ impl SyncThreadpool {
|
||||||
|
|
||||||
fn try_spawn_thread(&self) -> Option<()> {
|
fn try_spawn_thread(&self) -> Option<()> {
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
match self.num_threads.fetch_update(
|
match self
|
||||||
Ordering::Release,
|
.num_threads
|
||||||
Ordering::Acquire,
|
.fetch_update(Ordering::Release, Ordering::Acquire, |i| {
|
||||||
|i| {
|
|
||||||
if i < self.max_threads {
|
if i < self.max_threads {
|
||||||
Some(i + 1)
|
Some(i + 1)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
}) {
|
||||||
) {
|
|
||||||
Ok(tid) => {
|
Ok(tid) => {
|
||||||
struct SyncThread {
|
struct SyncThread {
|
||||||
timeout: u64,
|
timeout: u64,
|
||||||
|
@ -68,22 +66,14 @@ impl SyncThreadpool {
|
||||||
fn run(self, barrier: Arc<std::sync::Barrier>) {
|
fn run(self, barrier: Arc<std::sync::Barrier>) {
|
||||||
tracing::info!("spawned new sync thread");
|
tracing::info!("spawned new sync thread");
|
||||||
barrier.wait();
|
barrier.wait();
|
||||||
while let Ok((sync, waker)) =
|
while let Ok((sync, waker)) = self.rx.recv_timeout(self.thread_dies_after) {
|
||||||
self.rx.recv_timeout(self.thread_dies_after)
|
tracing::info!("received ({:?}, {:?})", sync, waker);
|
||||||
{
|
|
||||||
tracing::info!(
|
|
||||||
"received ({:?}, {:?})",
|
|
||||||
sync,
|
|
||||||
waker
|
|
||||||
);
|
|
||||||
loop {
|
loop {
|
||||||
let wait_result = match &sync {
|
let wait_result = match &sync {
|
||||||
SyncPrimitive::Fence(fence) => {
|
SyncPrimitive::Fence(fence) => {
|
||||||
fence.wait_on(Some(self.timeout))
|
fence.wait_on(Some(self.timeout))
|
||||||
}
|
}
|
||||||
SyncPrimitive::DeviceIdle(device) => {
|
SyncPrimitive::DeviceIdle(device) => device.wait_idle(),
|
||||||
device.wait_idle()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match wait_result {
|
match wait_result {
|
||||||
|
@ -95,7 +85,7 @@ impl SyncThreadpool {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
"failed to wait on {sync:?} in waiter thread: {err}"
|
"failed to wait on {sync:?} in waiter thread: {err}"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,8 +187,7 @@ impl Fence {
|
||||||
Ok(Self::new(
|
Ok(Self::new(
|
||||||
dev.clone(),
|
dev.clone(),
|
||||||
dev.dev().create_fence(
|
dev.dev().create_fence(
|
||||||
&vk::FenceCreateInfo::default()
|
&vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED),
|
||||||
.flags(vk::FenceCreateFlags::SIGNALED),
|
|
||||||
None,
|
None,
|
||||||
)?,
|
)?,
|
||||||
))
|
))
|
||||||
|
@ -207,11 +196,9 @@ impl Fence {
|
||||||
pub fn wait_on(&self, timeout: Option<u64>) -> Result<(), vk::Result> {
|
pub fn wait_on(&self, timeout: Option<u64>) -> Result<(), vk::Result> {
|
||||||
use core::slice::from_ref;
|
use core::slice::from_ref;
|
||||||
unsafe {
|
unsafe {
|
||||||
self.dev.dev().wait_for_fences(
|
self.dev
|
||||||
from_ref(&self.fence),
|
.dev()
|
||||||
true,
|
.wait_for_fences(from_ref(&self.fence), true, timeout.unwrap_or(u64::MAX))
|
||||||
timeout.unwrap_or(u64::MAX),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn fence(&self) -> vk::Fence {
|
pub fn fence(&self) -> vk::Fence {
|
||||||
|
@ -236,12 +223,10 @@ impl AsRef<vk::Fence> for Fence {
|
||||||
|
|
||||||
impl Semaphore {
|
impl Semaphore {
|
||||||
pub fn new(device: Device) -> VkResult<Self> {
|
pub fn new(device: Device) -> VkResult<Self> {
|
||||||
let mut type_info = vk::SemaphoreTypeCreateInfo::default()
|
let mut type_info =
|
||||||
.semaphore_type(vk::SemaphoreType::BINARY);
|
vk::SemaphoreTypeCreateInfo::default().semaphore_type(vk::SemaphoreType::BINARY);
|
||||||
let create_info =
|
let create_info = vk::SemaphoreCreateInfo::default().push_next(&mut type_info);
|
||||||
vk::SemaphoreCreateInfo::default().push_next(&mut type_info);
|
let inner = unsafe { device.dev().create_semaphore(&create_info, None)? };
|
||||||
let inner =
|
|
||||||
unsafe { device.dev().create_semaphore(&create_info, None)? };
|
|
||||||
|
|
||||||
Ok(Self { device, inner })
|
Ok(Self { device, inner })
|
||||||
}
|
}
|
||||||
|
@ -249,10 +234,8 @@ impl Semaphore {
|
||||||
let mut type_info = vk::SemaphoreTypeCreateInfo::default()
|
let mut type_info = vk::SemaphoreTypeCreateInfo::default()
|
||||||
.semaphore_type(vk::SemaphoreType::TIMELINE)
|
.semaphore_type(vk::SemaphoreType::TIMELINE)
|
||||||
.initial_value(value);
|
.initial_value(value);
|
||||||
let create_info =
|
let create_info = vk::SemaphoreCreateInfo::default().push_next(&mut type_info);
|
||||||
vk::SemaphoreCreateInfo::default().push_next(&mut type_info);
|
let inner = unsafe { device.dev().create_semaphore(&create_info, None)? };
|
||||||
let inner =
|
|
||||||
unsafe { device.dev().create_semaphore(&create_info, None)? };
|
|
||||||
|
|
||||||
Ok(Self { device, inner })
|
Ok(Self { device, inner })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,28 @@
|
||||||
use std::ops::Deref;
|
use std::{borrow::Cow, ops::Deref};
|
||||||
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! def_monotonic_id {
|
||||||
|
($ty:ident) => {
|
||||||
|
#[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
|
||||||
|
pub struct $ty(::core::num::NonZero<u32>);
|
||||||
|
|
||||||
|
impl $ty {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
use ::core::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
static COUNTER: AtomicU32 = AtomicU32::new(1);
|
||||||
|
|
||||||
|
let inner = COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||||
|
Self(
|
||||||
|
::core::num::NonZero::<u32>::new(inner)
|
||||||
|
.expect(&format!("integer overwarp for {}", stringify!($ty))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub trait MutexExt<'a, T: 'a> {
|
pub trait MutexExt<'a, T: 'a> {
|
||||||
type Guard: Deref<Target = T> + 'a;
|
type Guard: Deref<Target = T> + 'a;
|
||||||
fn lock(&'a self) -> Self::Guard;
|
fn lock(&'a self) -> Self::Guard;
|
||||||
|
@ -239,3 +260,41 @@ impl FormatExt for vk::Format {
|
||||||
format_to_primitive(*self) == FormatComponentKind::SInt
|
format_to_primitive(*self) == FormatComponentKind::SInt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
pub struct Rect2D {
|
||||||
|
top_left: glam::IVec2,
|
||||||
|
bottom_right: glam::IVec2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rect2D {
|
||||||
|
pub fn new(left: i32, top: i32, right: i32, bottom: i32) -> Self {
|
||||||
|
use glam::ivec2;
|
||||||
|
Self {
|
||||||
|
top_left: ivec2(left, top),
|
||||||
|
bottom_right: ivec2(right, bottom),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new_from_size(pos: glam::IVec2, size: glam::IVec2) -> Self {
|
||||||
|
use glam::ivec2;
|
||||||
|
Self {
|
||||||
|
top_left: pos,
|
||||||
|
bottom_right: pos + size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_offsets_3d(&self) -> [vk::Offset3D; 2] {
|
||||||
|
[
|
||||||
|
vk::Offset3D {
|
||||||
|
x: self.top_left.x,
|
||||||
|
y: self.top_left.y,
|
||||||
|
z: 0,
|
||||||
|
},
|
||||||
|
vk::Offset3D {
|
||||||
|
x: self.bottom_right.x,
|
||||||
|
y: self.bottom_right.y,
|
||||||
|
z: 1,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue