peridot/
lib.rs

1use async_std::stream::StreamExt;
2use futures_util::FutureExt;
3pub use peridot_archive as archive;
4pub use peridot_math as math;
5
6use bedrock::{self as br, VkHandle};
7use parking_lot::RwLock;
8use std::cell::{Ref, RefCell};
9use std::collections::VecDeque;
10use std::ffi::CStr;
11use std::ops::{Deref, DerefMut};
12use std::sync::Arc;
13use std::time::{Duration, Instant as InstantTimer};
14
15mod graphics;
16pub use self::graphics::{
17    CBSubmissionType, CommandBundle, DeviceObject, Graphics, InstanceObject, LocalCommandBundle,
18    MemoryTypeManager, VulkanExtension, VulkanGfx,
19};
20mod state_track;
21mod window;
22pub use self::window::SurfaceInfo;
23mod resource;
24pub use self::resource::*;
25#[cfg(feature = "debug")]
26mod debug;
27pub mod utils;
28pub use self::utils::*;
29
30mod asset;
31pub use self::asset::*;
32mod batch;
33pub use self::batch::*;
34mod input;
35pub use self::input::*;
36pub mod audio;
37mod model;
38pub use self::model::*;
39mod presenter;
40pub use self::presenter::*;
41
42pub mod mthelper;
43#[allow(unused_imports)]
44use mthelper::DynamicMutabilityProvider;
45use mthelper::{DynamicMut, MappableGuardObject, MappableMutGuardObject};
46
47#[cfg(feature = "derive")]
48pub use peridot_derive::*;
49
50pub trait NativeLinker: Sized {
51    type AssetLoader: PlatformAssetLoader;
52    type Presenter: PlatformPresenter;
53
54    fn instance_extensions(&self) -> Vec<&CStr>;
55    fn device_extensions(&self) -> Vec<&CStr>;
56
57    fn asset_loader(&self) -> &Self::AssetLoader;
58    fn new_presenter(&self, g: &Graphics) -> Self::Presenter;
59
60    fn rendering_precision(&self) -> f32 {
61        1.0
62    }
63}
64
65pub trait EngineEvents<PL: NativeLinker>: Sized {
66    fn init(_e: &mut Engine<PL>) -> Self;
67
68    /// Updates the game.
69    fn update(&mut self, _e: &mut Engine<PL>, _on_back_buffer_of: u32, _delta_time: Duration) {}
70
71    /// Discards back-buffer-dependent resources(i.e. Framebuffers or some of CommandBuffers)
72    fn discard_back_buffer_resources(&mut self) {}
73
74    /// Called when back-buffer has resized
75    /// (called after discard_back-buffer_resources so re-create discarded resources here)
76    fn on_resize(&mut self, _e: &mut Engine<PL>, _new_size: math::Vector2<usize>) {}
77
78    // Render Resource Persistency(Recovering) //
79
80    /// Storing recovered render resources for discarding
81    fn store_render_resources(&mut self, _e: &mut Engine<PL>) {}
82
83    /// Recovering render resources
84    fn recover_render_resources(&mut self, _e: &mut Engine<PL>) {}
85}
86
87impl<PL: NativeLinker> EngineEvents<PL> for () {
88    fn init(_e: &mut Engine<PL>) -> Self {
89        ()
90    }
91}
92
93/// Specifies which type of resource is supports sparse residency?
94#[repr(transparent)]
95#[derive(Clone, Copy)]
96pub struct SparseResidencySupportBits(u16);
97impl SparseResidencySupportBits {
98    pub const EMPTY: Self = Self(0);
99    pub const BUFFER: Self = Self(0x0001);
100    pub const IMAGE_2D: Self = Self(0x0002);
101    pub const IMAGE_3D: Self = Self(0x0004);
102    pub const SAMPLE2: Self = Self(0x0008);
103    pub const SAMPLE4: Self = Self(0x0010);
104    pub const SAMPLE8: Self = Self(0x0020);
105    pub const SAMPLE16: Self = Self(0x0040);
106    pub const SAMPLE32: Self = Self(0x0080);
107    pub const ALIASED: Self = Self(0x0100);
108
109    pub const fn buffer(self) -> Self {
110        Self(self.0 | Self::BUFFER.0)
111    }
112    pub const fn image_2d(self) -> Self {
113        Self(self.0 | Self::IMAGE_2D.0)
114    }
115    pub const fn image_3d(self) -> Self {
116        Self(self.0 | Self::IMAGE_3D.0)
117    }
118    pub const fn sample2(self) -> Self {
119        Self(self.0 | Self::SAMPLE2.0)
120    }
121    pub const fn sample4(self) -> Self {
122        Self(self.0 | Self::SAMPLE4.0)
123    }
124    pub const fn sample8(self) -> Self {
125        Self(self.0 | Self::SAMPLE8.0)
126    }
127    pub const fn sample16(self) -> Self {
128        Self(self.0 | Self::SAMPLE16.0)
129    }
130    pub const fn aliased(self) -> Self {
131        Self(self.0 | Self::ALIASED.0)
132    }
133
134    const fn has_buffer(self) -> bool {
135        (self.0 & Self::BUFFER.0) != 0
136    }
137    const fn has_image_2d(self) -> bool {
138        (self.0 & Self::IMAGE_2D.0) != 0
139    }
140    const fn has_image_3d(self) -> bool {
141        (self.0 & Self::IMAGE_3D.0) != 0
142    }
143    const fn has_sample2(self) -> bool {
144        (self.0 & Self::SAMPLE2.0) != 0
145    }
146    const fn has_sample4(self) -> bool {
147        (self.0 & Self::SAMPLE4.0) != 0
148    }
149    const fn has_sample8(self) -> bool {
150        (self.0 & Self::SAMPLE8.0) != 0
151    }
152    const fn has_sample16(self) -> bool {
153        (self.0 & Self::SAMPLE16.0) != 0
154    }
155    const fn has_aliased(self) -> bool {
156        (self.0 & Self::ALIASED.0) != 0
157    }
158}
159pub trait FeatureRequests {
160    const ENABLE_GEOMETRY_SHADER: bool = false;
161    const ENABLE_TESSELLATION_SHADER: bool = false;
162    const USE_STORAGE_BUFFERS_IN_VERTEX_SHADER: bool = false;
163    const SPARSE_BINDING: bool = false;
164    const SPARSE_RESIDENCY_SUPPORT_BITS: SparseResidencySupportBits =
165        SparseResidencySupportBits::EMPTY;
166
167    fn requested_features() -> br::vk::VkPhysicalDeviceFeatures {
168        br::vk::VkPhysicalDeviceFeatures {
169            geometryShader: Self::ENABLE_GEOMETRY_SHADER as _,
170            tessellationShader: Self::ENABLE_TESSELLATION_SHADER as _,
171            vertexPipelineStoresAndAtomics: Self::USE_STORAGE_BUFFERS_IN_VERTEX_SHADER as _,
172            sparseBinding: Self::SPARSE_BINDING as _,
173            sparseResidencyBuffer: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_buffer() as _,
174            sparseResidencyImage2D: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_image_2d() as _,
175            sparseResidencyImage3D: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_image_3d() as _,
176            sparseResidency2Samples: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_sample2() as _,
177            sparseResidency4Samples: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_sample4() as _,
178            sparseResidency8Samples: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_sample8() as _,
179            sparseResidency16Samples: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_sample16() as _,
180            sparseResidencyAliased: Self::SPARSE_RESIDENCY_SUPPORT_BITS.has_aliased() as _,
181            ..Default::default()
182        }
183    }
184}
185
186pub enum EngineEvent {
187    Shutdown,
188    Resize(math::Vector2<u32>),
189}
190
191pub struct FrameData {
192    pub delta_time: Duration,
193    pub backbuffer_index: u32,
194}
195
196pub enum Event {
197    NextFrame,
198    Shutdown,
199    Resize(math::Vector2<u32>),
200}
201
202#[derive(Debug)]
203pub enum PrepareFrameError {
204    FramebufferOutOfDate,
205}
206
207pub struct EngineEventReceiver {
208    frame_timing_receiver: async_std::channel::Receiver<()>,
209    other_events_receiver: async_std::channel::Receiver<EngineEvent>,
210}
211impl EngineEventReceiver {
212    pub async fn wait_for_event(&mut self) -> Option<Event> {
213        futures_util::select! {
214            e = self.frame_timing_receiver.next().fuse() => match e {
215                Some(()) => Some(Event::NextFrame),
216                None => None,
217            },
218            e = self.other_events_receiver.next().fuse() => match e {
219                Some(EngineEvent::Shutdown) => Some(Event::Shutdown),
220                Some(EngineEvent::Resize(ns)) => Some(Event::Resize(ns)),
221                None => None,
222            }
223        }
224    }
225}
226
227pub struct NextEventFuture<'e> {
228    queue: &'e RefCell<VecDeque<Event>>,
229    queue_waker: &'e RefCell<Vec<core::task::Waker>>,
230}
231impl core::future::Future for NextEventFuture<'_> {
232    type Output = Event;
233
234    #[inline]
235    fn poll(
236        self: std::pin::Pin<&mut Self>,
237        cx: &mut std::task::Context<'_>,
238    ) -> std::task::Poll<Self::Output> {
239        if let Some(e) = self.queue.borrow_mut().pop_front() {
240            core::task::Poll::Ready(e)
241        } else {
242            self.queue_waker.borrow_mut().push(cx.waker().clone());
243            core::task::Poll::Pending
244        }
245    }
246}
247
248pub struct EventQueue {
249    queue: RefCell<VecDeque<Event>>,
250    queue_waker: RefCell<Vec<core::task::Waker>>,
251}
252impl EventQueue {
253    pub fn new() -> Self {
254        Self {
255            queue: RefCell::new(VecDeque::new()),
256            queue_waker: RefCell::new(Vec::new()),
257        }
258    }
259
260    pub fn enqueue(&self, event: Event) {
261        self.queue.borrow_mut().push_back(event);
262        for w in core::mem::replace(&mut *self.queue_waker.borrow_mut(), Vec::new()) {
263            w.wake();
264        }
265    }
266
267    #[inline(always)]
268    pub fn next_event<'q>(&'q self) -> impl core::future::Future<Output = Event> + 'q {
269        NextEventFuture {
270            queue: &self.queue,
271            queue_waker: &self.queue_waker,
272        }
273    }
274}
275
276struct LastRenderingCompletionFence {
277    handle: br::vk::VkFence,
278    device: VulkanGfx,
279    used: bool,
280}
281impl Drop for LastRenderingCompletionFence {
282    fn drop(&mut self) {
283        unsafe {
284            br::vkfn_wrapper::destroy_fence(self.device.native_ptr(), self.handle, None);
285        }
286    }
287}
288impl LastRenderingCompletionFence {
289    pub fn new(device: &VulkanGfx) -> br::Result<Self> {
290        let handle = unsafe {
291            br::vkfn_wrapper::create_fence(device.0.device, &br::FenceCreateInfo::new(0), None)?
292        };
293
294        Ok(Self {
295            handle,
296            device: device.clone(),
297            used: false,
298        })
299    }
300
301    pub fn wait(&mut self) -> br::Result<()> {
302        if self.used {
303            unsafe {
304                br::vkfn_wrapper::wait_for_fences(
305                    self.device.0.device,
306                    &[self.handle],
307                    true,
308                    u64::MAX,
309                )?;
310                br::vkfn_wrapper::reset_fences(
311                    self.device.0.device,
312                    &[br::VkHandleRefMut::dangling(self.handle)],
313                )?;
314            }
315            self.used = false;
316        }
317
318        Ok(())
319    }
320
321    #[must_use]
322    pub fn r#use(&mut self) -> br::VkHandleRefMut<br::vk::VkFence> {
323        self.used = true;
324
325        unsafe { br::VkHandleRefMut::dangling(self.handle) }
326    }
327}
328
329pub struct Engine<'q, NL: NativeLinker> {
330    native_link: NL,
331    presenter: NL::Presenter,
332    pub(self) g: Graphics,
333    ip: InputProcess,
334    game_timer: GameTimer,
335    last_rendering_completion: LastRenderingCompletionFence,
336    audio_mixer: Arc<RwLock<audio::Mixer>>,
337    request_resize: bool,
338    engine_events_sender: async_std::channel::Sender<EngineEvent>,
339    receivers: core::cell::UnsafeCell<EngineEventReceiver>,
340    shared_event_queue: &'q EventQueue,
341}
342impl<'q, PL: NativeLinker> Engine<'q, PL> {
343    pub fn new(
344        name: &str,
345        version: br::Version,
346        native_link: PL,
347        requested_features: br::vk::VkPhysicalDeviceFeatures,
348        engine_events_bus: (
349            async_std::channel::Sender<EngineEvent>,
350            async_std::channel::Receiver<EngineEvent>,
351        ),
352        frame_timing_receiver: async_std::channel::Receiver<()>,
353        shared_event_queue: &'q EventQueue,
354    ) -> Self {
355        let mut g = Graphics::new(
356            name,
357            version,
358            native_link.instance_extensions(),
359            native_link.device_extensions(),
360            requested_features,
361        );
362        let presenter = native_link.new_presenter(&g);
363        g.submit_commands(|r| presenter.emit_initialize_back_buffer_commands(r))
364            .expect("Initializing Back Buffers");
365
366        let last_rendering_completion = match LastRenderingCompletionFence::new(&g.gfx_device) {
367            Ok(x) => x,
368            Err(e) => {
369                tracing::error!(cause = ?e, "Faield to create last rendering completion fence");
370                std::process::abort();
371            }
372        };
373
374        Self {
375            ip: InputProcess::new().into(),
376            game_timer: GameTimer::new(),
377            last_rendering_completion,
378            audio_mixer: Arc::new(RwLock::new(audio::Mixer::new())),
379            native_link,
380            g,
381            presenter,
382            request_resize: false,
383            engine_events_sender: engine_events_bus.0,
384            receivers: core::cell::UnsafeCell::new(EngineEventReceiver {
385                frame_timing_receiver,
386                other_events_receiver: engine_events_bus.1,
387            }),
388            shared_event_queue,
389        }
390    }
391
392    pub fn post_init(&mut self) {
393        tracing::trace!("PostInit BaseEngine...");
394    }
395}
396impl<'q, NL: NativeLinker> Engine<'q, NL> {
397    pub fn event_receivers(&self) -> &mut EngineEventReceiver {
398        unsafe { &mut *self.receivers.get() }
399    }
400
401    #[inline(always)]
402    pub fn next_event(&self) -> impl core::future::Future<Output = Event> + 'q {
403        self.shared_event_queue.next_event()
404    }
405
406    pub async fn quit(&self) {
407        if let Err(e) = self.engine_events_sender.send(EngineEvent::Shutdown).await {
408            tracing::warn!(cause = ?e, "Engine has already shutting down");
409        }
410    }
411
412    pub const fn graphics(&self) -> &Graphics {
413        &self.g
414    }
415    pub fn graphics_mut(&mut self) -> &mut Graphics {
416        &mut self.g
417    }
418
419    pub const fn graphics_device(&self) -> &VulkanGfx {
420        &self.g.gfx_device
421    }
422    pub const fn graphics_queue_family_index(&self) -> u32 {
423        self.g.graphics_queue_family_index()
424    }
425    // 将来的に分かれるかも?
426    pub const fn transfer_queue_family_index(&self) -> u32 {
427        self.g.graphics_queue.family
428    }
429
430    pub fn back_buffer_format(&self) -> br::vk::VkFormat {
431        self.presenter.format()
432    }
433    pub fn back_buffer_size(&self) -> peridot_math::Vector2<u32> {
434        self.presenter.back_buffer_size()
435    }
436    pub fn back_buffer_count(&self) -> usize {
437        self.presenter.back_buffer_count()
438    }
439    pub fn back_buffer(&self, index: usize) -> Option<br::VkHandleRef<br::vk::VkImage>> {
440        self.presenter.back_buffer(index)
441    }
442    pub fn iter_back_buffers<'s>(
443        &'s self,
444    ) -> impl Iterator<Item = br::VkHandleRef<'s, br::vk::VkImage>> + 's {
445        (0..self.back_buffer_count())
446            .map(move |x| self.back_buffer(x).expect("unreachable while iteration"))
447    }
448    pub fn requesting_back_buffer_layout(&self) -> (br::ImageLayout, br::PipelineStageFlags) {
449        self.presenter.requesting_back_buffer_layout()
450    }
451    pub fn back_buffer_attachment_desc(&self) -> br::vk::VkAttachmentDescription {
452        let (ol, _) = self.requesting_back_buffer_layout();
453
454        br::vk::VkAttachmentDescription::new(self.back_buffer_format(), ol, ol)
455    }
456
457    pub fn screen_size(&self) -> peridot_math::Vector2<u32> {
458        self.presenter.current_geometry_extent()
459    }
460
461    pub fn input(&self) -> &InputProcess {
462        &self.ip
463    }
464    pub fn input_mut(&mut self) -> &mut InputProcess {
465        &mut self.ip
466    }
467
468    pub fn submit_commands(
469        &mut self,
470        generator: impl for<'a> FnOnce(br::CmdRecord<'a, VulkanGfx>) -> br::CmdRecord<'a, VulkanGfx>,
471    ) -> br::Result<()> {
472        self.g.submit_commands(generator)
473    }
474    pub fn submit_buffered_commands(
475        &mut self,
476        batches: &[br::SubmitInfo],
477        fence: &mut impl br::VkHandleMut<Handle = br::vk::VkFence>,
478    ) -> br::Result<()> {
479        self.g.submit_buffered_commands(batches, fence)
480    }
481
482    #[cfg(feature = "mt")]
483    /// Submits any commands as transient commands.
484    /// ## Note
485    /// Unlike other futures, commands are submitted **immediately**(even if not awaiting the returned future).
486    pub fn submit_commands_async<'s>(
487        &'s self,
488        generator: impl for<'a> FnOnce(br::CmdRecord<'a, VulkanGfx>) -> br::CmdRecord<'a, VulkanGfx>
489            + 's,
490    ) -> br::Result<impl std::future::Future<Output = br::Result<()>> + 's> {
491        self.g.submit_commands_async(generator)
492    }
493
494    #[inline]
495    pub const fn audio_mixer(&self) -> &Arc<RwLock<audio::Mixer>> {
496        &self.audio_mixer
497    }
498}
499impl<PL: NativeLinker> Engine<'_, PL> {
500    pub fn load<A: FromAsset>(&self, path: &str) -> Result<A, A::Error> {
501        A::from_asset(self.native_link.asset_loader().get(path, A::EXT)?)
502    }
503    pub fn streaming<A: FromStreamingAsset>(&self, path: &str) -> Result<A, A::Error> {
504        A::from_asset(
505            self.native_link
506                .asset_loader()
507                .get_streaming(path, A::EXT)?,
508        )
509    }
510
511    pub fn rendering_precision(&self) -> f32 {
512        self.native_link.rendering_precision()
513    }
514}
515impl<PL: NativeLinker> Engine<'_, PL> {
516    pub fn prepare_frame(&mut self) -> Result<FrameData, PrepareFrameError> {
517        if let Err(e) = self.last_rendering_completion.wait() {
518            tracing::warn!(cause = ?e, "Failed to wait last command completion");
519        }
520
521        let dt = self.game_timer.delta_time();
522        let backbuffer_index = match self.presenter.next_back_buffer_index() {
523            Err(e) if e == br::vk::VK_ERROR_OUT_OF_DATE_KHR || e == br::vk::VK_SUBOPTIMAL_KHR => {
524                return Err(PrepareFrameError::FramebufferOutOfDate);
525            }
526            e => e.expect("Acquiring available back-buffer index failed"),
527        };
528
529        self.ip.prepare_for_frame(dt);
530
531        Ok(FrameData {
532            delta_time: dt,
533            backbuffer_index,
534        })
535    }
536
537    // pub fn do_update(&mut self, callback: &mut (impl EngineEvents<PL> + ?Sized)) {
538    //     let dt = self.game_timer.delta_time();
539
540    //     let bb_index = match self.presenter.next_back_buffer_index() {
541    //         Err(e) if e == br::vk::VK_ERROR_OUT_OF_DATE_KHR => {
542    //             // Fire resize and do nothing
543    //             self.do_resize_back_buffer(self.presenter.current_geometry_extent(), callback);
544    //             return;
545    //         }
546    //         e => e.expect("Acquiring available back-buffer index"),
547    //     };
548    //     StateFence::wait(&mut self.last_rendering_completion)
549    //         .expect("Waiting Last command completion");
550
551    //     self.ip.prepare_for_frame(dt);
552
553    //     callback.update(self, bb_index, dt);
554
555    //     if self.request_resize {
556    //         self.request_resize = false;
557    //         self.do_resize_back_buffer(self.presenter.current_geometry_extent(), callback);
558    //     }
559    // }
560
561    pub fn do_render(
562        &mut self,
563        bb_index: u32,
564        copy_submission: Option<SubmissionBatchBuilder>,
565        render_submission: SubmissionBatchBuilder,
566    ) -> br::Result<()> {
567        let pr = self.presenter.render_and_present(
568            &mut self.g,
569            &mut self.last_rendering_completion.r#use(),
570            bb_index,
571            render_submission,
572            copy_submission,
573        );
574
575        match pr {
576            Err(e) if e == br::vk::VK_ERROR_OUT_OF_DATE_KHR || e == br::vk::VK_SUBOPTIMAL_KHR => {
577                // Fire resize
578                self.request_resize = true;
579
580                Ok(())
581            }
582            v => v,
583        }
584    }
585
586    pub fn wait_for_last_rendering_completion(&mut self) -> br::Result<()> {
587        self.last_rendering_completion.wait()
588    }
589
590    pub fn resize_presenter_backbuffers(&mut self, new_size: math::Vector2<u32>) {
591        let needs_re_init_back_buffers = self
592            .presenter
593            .resize(&self.g, math::Vector2(new_size.0 as _, new_size.1 as _));
594        if needs_re_init_back_buffers {
595            let pres = &self.presenter;
596
597            self.g
598                .submit_commands(|r| pres.emit_initialize_back_buffer_commands(r))
599                .expect("Initializing Back Buffers");
600        }
601    }
602
603    // pub fn do_resize_back_buffer(
604    //     &mut self,
605    //     new_size: math::Vector2<usize>,
606    //     callback: &mut (impl EngineEvents<PL> + ?Sized),
607    // ) {
608    //     StateFence::wait(&mut self.last_rendering_completion)
609    //         .expect("Waiting Last command completion");
610    //     callback.discard_back_buffer_resources();
611    //     let needs_re_init_back_buffers = self.presenter.resize(&self.g, new_size.clone());
612    //     if needs_re_init_back_buffers {
613    //         let pres = &self.presenter;
614
615    //         self.g
616    //             .submit_commands(|r| pres.emit_initialize_back_buffer_commands(r))
617    //             .expect("Initializing Back Buffers");
618    //     }
619    //     callback.on_resize(self, new_size);
620    // }
621
622    pub fn sound_backend_callback(&self, output_buffer: &mut [f32]) {
623        for (n, r) in output_buffer.iter_mut().enumerate() {
624            *r = (440.0 * n as f32 / 44100.0).to_radians().sin() * 0.1;
625        }
626    }
627}
628impl<NL: NativeLinker> Drop for Engine<'_, NL> {
629    fn drop(&mut self) {
630        if let Err(e) = self.g.wait_operations() {
631            tracing::warn!(cause = ?e, "Failed to wait device operations at drop");
632        }
633    }
634}
635
636pub struct LateInit<T>(RefCell<Option<T>>);
637impl<T> LateInit<T> {
638    pub fn new() -> Self {
639        LateInit(RefCell::new(None))
640    }
641    pub fn init(&self, v: T) {
642        *self.0.borrow_mut() = v.into();
643    }
644    pub fn get(&self) -> Ref<T> {
645        Ref::map(self.0.borrow(), |x| x.as_ref().expect("uninitialized"))
646    }
647}
648
649pub struct Discardable1<T>(Option<T>);
650impl<T> Discardable1<T> {
651    pub const fn new() -> Self {
652        Self(None)
653    }
654
655    pub fn set(&mut self, v: T) {
656        self.0 = Some(v);
657    }
658
659    pub fn get<'v>(&'v self) -> &'v T {
660        self.0.as_ref().expect("value unset")
661    }
662
663    pub fn get_mut<'v>(&'v mut self) -> &'v mut T {
664        self.0.as_mut().expect("value unset")
665    }
666
667    pub fn discard(&mut self) {
668        self.0 = None;
669    }
670
671    pub fn take(&mut self) -> Option<T> {
672        self.0.take()
673    }
674
675    pub const fn is_available(&self) -> bool {
676        self.0.is_some()
677    }
678}
679impl<T> From<T> for Discardable1<T> {
680    #[inline(always)]
681    fn from(value: T) -> Self {
682        Self(Some(value))
683    }
684}
685
686pub struct Discardable<T>(DynamicMut<Option<T>>);
687impl<T> Discardable<T> {
688    pub fn new() -> Self {
689        Discardable(DynamicMut::new(None))
690    }
691    pub fn set(&self, v: T) {
692        *self.0.borrow_mut() = v.into();
693    }
694    pub fn set_lw(&mut self, v: T) {
695        *self.0.get_mut() = v.into();
696    }
697
698    pub fn get<'v>(&'v self) -> impl Deref<Target = T> + 'v {
699        self.0
700            .borrow()
701            .map_guarded_value(|x| x.as_ref().expect("uninitialized"))
702    }
703
704    pub fn get_mut<'v>(&'v self) -> impl Deref<Target = T> + DerefMut + 'v {
705        self.0
706            .borrow_mut()
707            .map_guarded_value(|x| x.as_mut().expect("uninitialized"))
708    }
709
710    pub fn get_mut_lw(&mut self) -> &mut T {
711        self.0.get_mut().as_mut().expect("uninitialized")
712    }
713    pub fn discard(&self) {
714        *self.0.borrow_mut() = None;
715    }
716    pub fn discard_lw(&mut self) {
717        drop(self.0.get_mut().take());
718    }
719    pub fn take_lw(&mut self) -> Option<T> {
720        self.0.get_mut().take()
721    }
722    pub fn is_available(&self) -> bool {
723        self.0.borrow().is_some()
724    }
725}
726impl<T> From<T> for Discardable<T> {
727    fn from(v: T) -> Self {
728        Discardable(DynamicMut::new(Some(v)))
729    }
730}
731
732pub struct GameTimer(Option<InstantTimer>);
733impl GameTimer {
734    pub fn new() -> Self {
735        GameTimer(None)
736    }
737    pub fn delta_time(&mut self) -> Duration {
738        let d = self
739            .0
740            .as_ref()
741            .map_or_else(|| Duration::new(0, 0), |it| it.elapsed());
742        self.0 = InstantTimer::now().into();
743
744        return d;
745    }
746}
747
748pub enum SubpassDependencyTemplates {}
749impl SubpassDependencyTemplates {
750    pub fn to_color_attachment_in(
751        from_subpass: Option<u32>,
752        occurrence_subpass: u32,
753        by_region: bool,
754    ) -> br::vk::VkSubpassDependency {
755        br::vk::VkSubpassDependency {
756            dstSubpass: occurrence_subpass,
757            srcSubpass: from_subpass.unwrap_or(br::vk::VK_SUBPASS_EXTERNAL),
758            dstStageMask: br::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT.0,
759            dstAccessMask: br::AccessFlags::COLOR_ATTACHMENT.write,
760            dependencyFlags: if by_region {
761                br::vk::VK_DEPENDENCY_BY_REGION_BIT
762            } else {
763                0
764            },
765            srcStageMask: br::PipelineStageFlags::TOP_OF_PIPE.0,
766            srcAccessMask: 0,
767        }
768    }
769}
770
771pub struct LayoutedPipeline<Pipeline: br::Pipeline, Layout: br::PipelineLayout>(Pipeline, Layout);
772impl<Pipeline: br::Pipeline, Layout: br::PipelineLayout> LayoutedPipeline<Pipeline, Layout> {
773    pub const fn combine(p: Pipeline, layout: Layout) -> Self {
774        Self(p, layout)
775    }
776
777    pub const fn pipeline(&self) -> &Pipeline {
778        &self.0
779    }
780
781    pub const fn layout(&self) -> &Layout {
782        &self.1
783    }
784
785    #[inline(always)]
786    pub fn bind<'r, Device: ?Sized>(
787        &self,
788        rec: br::CmdRecord<'r, Device>,
789    ) -> br::CmdRecord<'r, Device> {
790        rec.bind_pipeline(br::PipelineBindPoint::Graphics, &self.0)
791    }
792}