1mod encoder;
4mod level;
5mod reset;
6mod state;
7mod submit;
8mod usage;
9
10use {
11 crate::{
12 capability::{Capability, Supports},
13 family::FamilyId,
14 },
15 rendy_core::hal::Backend,
16};
17
18pub use self::{encoder::*, level::*, reset::*, state::*, submit::*, usage::*};
19
20#[derive(Debug)]
24pub struct CommandBuffer<B: Backend, C, S, L = PrimaryLevel, R = NoIndividualReset> {
25 raw: std::ptr::NonNull<B::CommandBuffer>,
26 capability: C,
27 state: S,
28 level: L,
29 reset: R,
30 family: FamilyId,
31 relevant: relevant::Relevant,
32}
33
34family_owned!(CommandBuffer<B, C, S, L, R>);
35
36unsafe impl<B, C, S, L, R> Send for CommandBuffer<B, C, S, L, R>
37where
38 B: Backend,
39 B::CommandBuffer: Send,
40 C: Send,
41 S: Send,
42 L: Send,
43 R: Send,
44 FamilyId: Send,
45 relevant::Relevant: Send,
46{
47}
48
49unsafe impl<B, C, S, L, R> Sync for CommandBuffer<B, C, S, L, R>
50where
51 B: Backend,
52 B::CommandBuffer: Sync,
53 C: Sync,
54 S: Sync,
55 L: Sync,
56 R: Sync,
57 FamilyId: Sync,
58 relevant::Relevant: Sync,
59{
60}
61
62impl<B, C, S, L, R> CommandBuffer<B, C, S, L, R>
63where
64 B: Backend,
65{
66 pub(crate) unsafe fn from_raw(
77 raw: B::CommandBuffer,
78 capability: C,
79 state: S,
80 level: L,
81 reset: R,
82 family: FamilyId,
83 ) -> Self {
84 CommandBuffer {
85 raw: std::ptr::NonNull::new_unchecked(Box::into_raw(Box::new(raw))),
86 capability,
87 state,
88 level,
89 reset,
90 family,
91 relevant: relevant::Relevant,
92 }
93 }
94
95 pub unsafe fn change_state<U>(self, f: impl FnOnce(S) -> U) -> CommandBuffer<B, C, U, L, R> {
101 CommandBuffer {
102 raw: self.raw,
103 capability: self.capability,
104 state: f(self.state),
105 level: self.level,
106 reset: self.reset,
107 family: self.family,
108 relevant: self.relevant,
109 }
110 }
111
112 pub fn capability(&self) -> C
114 where
115 C: Capability,
116 {
117 self.capability
118 }
119
120 pub fn family(&self) -> FamilyId {
122 self.family
123 }
124
125 pub fn with_queue_type(self) -> CommandBuffer<B, rendy_core::hal::queue::QueueType, S, L, R>
127 where
128 C: Capability,
129 {
130 CommandBuffer {
131 raw: self.raw,
132 capability: self.capability.into_queue_type(),
133 state: self.state,
134 level: self.level,
135 reset: self.reset,
136 family: self.family,
137 relevant: self.relevant,
138 }
139 }
140
141 pub fn with_capability<U>(self) -> Result<CommandBuffer<B, U, S, L, R>, Self>
143 where
144 C: Supports<U>,
145 {
146 if let Some(capability) = self.capability.supports() {
147 Ok(CommandBuffer {
148 raw: self.raw,
149 capability: capability,
150 state: self.state,
151 level: self.level,
152 reset: self.reset,
153 family: self.family,
154 relevant: self.relevant,
155 })
156 } else {
157 Err(self)
158 }
159 }
160}
161
162pub unsafe trait BeginInfo<'a, B: Backend, L> {
164 type PassRelation: RenderPassRelation<L>;
166
167 fn inheritance_info(self) -> rendy_core::hal::command::CommandBufferInheritanceInfo<'a, B>;
169}
170
171unsafe impl<'a, B, L> BeginInfo<'a, B, L> for ()
172where
173 B: Backend,
174 L: Level,
175{
176 type PassRelation = OutsideRenderPass;
177
178 fn inheritance_info(self) -> rendy_core::hal::command::CommandBufferInheritanceInfo<'a, B> {
179 rendy_core::hal::command::CommandBufferInheritanceInfo::default()
180 }
181}
182
183unsafe impl<'a, B> BeginInfo<'a, B, SecondaryLevel> for rendy_core::hal::pass::Subpass<'a, B>
184where
185 B: Backend,
186{
187 type PassRelation = RenderPassContinue;
188
189 fn inheritance_info(self) -> rendy_core::hal::command::CommandBufferInheritanceInfo<'a, B> {
190 rendy_core::hal::command::CommandBufferInheritanceInfo {
191 subpass: Some(self),
192 framebuffer: None,
193 ..rendy_core::hal::command::CommandBufferInheritanceInfo::default()
194 }
195 }
196}
197
198unsafe impl<'a, B, F> BeginInfo<'a, B, SecondaryLevel>
199 for (rendy_core::hal::pass::Subpass<'a, B>, Option<&'a F>)
200where
201 B: Backend,
202 F: std::borrow::Borrow<B::Framebuffer>,
203{
204 type PassRelation = RenderPassContinue;
205
206 fn inheritance_info(self) -> rendy_core::hal::command::CommandBufferInheritanceInfo<'a, B> {
207 rendy_core::hal::command::CommandBufferInheritanceInfo {
208 subpass: Some(self.0),
209 framebuffer: self.1.map(F::borrow),
210 ..rendy_core::hal::command::CommandBufferInheritanceInfo::default()
211 }
212 }
213}
214
215unsafe impl<'a, B, F> BeginInfo<'a, B, SecondaryLevel>
216 for (rendy_core::hal::pass::Subpass<'a, B>, &'a F)
217where
218 B: Backend,
219 F: std::borrow::Borrow<B::Framebuffer>,
220{
221 type PassRelation = RenderPassContinue;
222
223 fn inheritance_info(self) -> rendy_core::hal::command::CommandBufferInheritanceInfo<'a, B> {
224 rendy_core::hal::command::CommandBufferInheritanceInfo {
225 subpass: Some(self.0),
226 framebuffer: Some(self.1.borrow()),
227 ..rendy_core::hal::command::CommandBufferInheritanceInfo::default()
228 }
229 }
230}
231
232impl<B, C, L, R> CommandBuffer<B, C, InitialState, L, R>
233where
234 B: Backend,
235{
236 pub fn begin<'a, U, P>(
242 mut self,
243 usage: U,
244 info: impl BeginInfo<'a, B, L, PassRelation = P>,
245 ) -> CommandBuffer<B, C, RecordingState<U, P>, L, R>
246 where
247 U: Usage,
248 P: RenderPassRelation<L>,
249 {
250 let pass_relation = P::default();
251 unsafe {
252 rendy_core::hal::command::CommandBuffer::begin(
253 self.raw(),
254 usage.flags() | pass_relation.flags(),
255 info.inheritance_info(),
256 );
257
258 self.change_state(|_| RecordingState(usage, pass_relation))
259 }
260 }
261}
262
263impl<'a, B, C, U, P, L, R> CommandBuffer<B, C, RecordingState<U, P>, L, R>
264where
265 B: Backend,
266{
267 pub fn finish(mut self) -> CommandBuffer<B, C, ExecutableState<U, P>, L, R> {
269 unsafe {
270 rendy_core::hal::command::CommandBuffer::finish(self.raw());
271
272 self.change_state(|s| ExecutableState(s.0, s.1))
273 }
274 }
275}
276
277impl<B, C, N, L, R> CommandBuffer<B, C, PendingState<N>, L, R>
278where
279 B: Backend,
280{
281 pub unsafe fn mark_complete(self) -> CommandBuffer<B, C, N, L, R> {
300 self.change_state(|PendingState(state)| state)
301 }
302}
303
304impl<B, C, S, L> CommandBuffer<B, C, S, L, IndividualReset>
305where
306 B: Backend,
307 S: Resettable,
308{
309 pub fn reset(self) -> CommandBuffer<B, C, InitialState, L, IndividualReset> {
311 unsafe { self.change_state(|_| InitialState) }
312 }
313}
314
315impl<B, C, S, L> CommandBuffer<B, C, S, L>
316where
317 B: Backend,
318 S: Resettable,
319{
320 pub unsafe fn mark_reset(self) -> CommandBuffer<B, C, InitialState, L> {
329 self.change_state(|_| InitialState)
330 }
331}
332
333impl<B, C, S, L, R> CommandBuffer<B, C, S, L, R>
334where
335 B: Backend,
336 S: Resettable,
337{
338 pub fn into_raw(self) -> B::CommandBuffer {
341 self.relevant.dispose();
342 unsafe {
343 *Box::from_raw(self.raw.as_ptr())
345 }
346 }
347
348 pub fn raw(&mut self) -> &mut B::CommandBuffer {
350 unsafe {
351 self.raw.as_mut()
353 }
354 }
355}