1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use {
    super::{
        level::PrimaryLevel,
        state::{ExecutableState, InvalidState, PendingState},
        usage::{MultiShot, NoSimultaneousUse, OneShot, OutsideRenderPass, SimultaneousUse},
        CommandBuffer,
    },
    crate::family::FamilyId,
};

/// Structure contains command buffer ready for submission.
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct Submit<
    B: gfx_hal::Backend,
    S = NoSimultaneousUse,
    L = PrimaryLevel,
    P = OutsideRenderPass,
> {
    #[derivative(Debug = "ignore")]
    raw: std::ptr::NonNull<B::CommandBuffer>,
    family: FamilyId,
    simultaneous: S,
    level: L,
    pass_continue: P,
}

unsafe impl<B, S, L, P> Send for Submit<B, S, L, P>
where
    B: gfx_hal::Backend,
    B::CommandBuffer: Send + Sync,
    FamilyId: Send,
    S: Send,
    L: Send,
    P: Send,
{
}

unsafe impl<B, S, L, P> Sync for Submit<B, S, L, P>
where
    B: gfx_hal::Backend,
    B::CommandBuffer: Send + Sync,
    S: Sync,
    L: Sync,
    P: Sync,
{
}

/// Submittable object.
/// Values that implement this trait can be submitted to the queues
/// or executed as part of primary buffers (in case of `Submittable<B, SecondaryLevel>`).
pub unsafe trait Submittable<B: gfx_hal::Backend, L = PrimaryLevel, P = OutsideRenderPass> {
    /// Get family that this submittable is belong to.
    fn family(&self) -> FamilyId;

    /// Get raw command buffer.
    /// This function is intended for submitting command buffer into raw queue.
    ///
    /// # Safety
    ///
    /// This function returns unbound reference to the raw command buffer.
    /// The actual lifetime of the command buffer is tied to the original `CommandBuffer` wrapper.
    /// `CommandBuffer` must not destroy raw command buffer or give access to it before submitted command is complete so
    /// using this funcion to submit command buffer into queue must be valid.
    unsafe fn raw<'a>(self) -> &'a B::CommandBuffer;
}

unsafe impl<B, S, L, P> Submittable<B, L, P> for Submit<B, S, L, P>
where
    B: gfx_hal::Backend,
{
    fn family(&self) -> FamilyId {
        self.family
    }

    unsafe fn raw<'a>(self) -> &'a B::CommandBuffer {
        &*self.raw.as_ptr()
    }
}

unsafe impl<'a, B, L, P> Submittable<B, L, P> for &'a Submit<B, SimultaneousUse, L, P>
where
    B: gfx_hal::Backend,
{
    fn family(&self) -> FamilyId {
        self.family
    }

    unsafe fn raw<'b>(self) -> &'b B::CommandBuffer {
        &*self.raw.as_ptr()
    }
}

impl<B, C, P, L, R> CommandBuffer<B, C, ExecutableState<OneShot, P>, L, R>
where
    B: gfx_hal::Backend,
    P: Copy,
    L: Copy,
{
    /// Produce `Submit` object that can be used to populate submission.
    pub fn submit_once(
        self,
    ) -> (
        Submit<B, NoSimultaneousUse, L, P>,
        CommandBuffer<B, C, PendingState<InvalidState>, L, R>,
    ) {
        let pass_continue = self.state.1;
        let level = self.level;

        let buffer = unsafe { self.change_state(|_| PendingState(InvalidState)) };

        let submit = Submit {
            raw: buffer.raw,
            family: buffer.family,
            pass_continue,
            simultaneous: NoSimultaneousUse,
            level,
        };

        (submit, buffer)
    }
}

impl<B, C, S, L, P, R> CommandBuffer<B, C, ExecutableState<MultiShot<S>, P>, L, R>
where
    B: gfx_hal::Backend,
    P: Copy,
    S: Copy,
    L: Copy,
{
    /// Produce `Submit` object that can be used to populate submission.
    pub fn submit(
        self,
    ) -> (
        Submit<B, S, L, P>,
        CommandBuffer<B, C, PendingState<ExecutableState<MultiShot<S>, P>>, L, R>,
    ) {
        let MultiShot(simultaneous) = self.state.0;
        let pass_continue = self.state.1;
        let level = self.level;

        let buffer = unsafe { self.change_state(|state| PendingState(state)) };

        let submit = Submit {
            raw: buffer.raw,
            family: buffer.family,
            pass_continue,
            simultaneous,
            level,
        };

        (submit, buffer)
    }
}