1use {
2 super::{
3 level::{Level, PrimaryLevel, SecondaryLevel},
4 state::RecordingState,
5 submit::Submittable,
6 usage::RenderPassContinue,
7 CommandBuffer,
8 },
9 crate::{
10 capability::{Capability, Compute, Graphics, Supports, Transfer},
11 family::FamilyId,
12 },
13};
14
15#[repr(C)]
19#[derive(Clone, Copy, Debug)]
20pub struct DrawCommand {
21 pub vertex_count: u32,
23
24 pub instance_count: u32,
26
27 pub first_vertex: u32,
29
30 pub first_instance: u32,
32}
33
34#[repr(C)]
38#[derive(Clone, Copy, Debug)]
39pub struct DrawIndexedCommand {
40 pub index_count: u32,
42
43 pub instance_count: u32,
45
46 pub first_index: u32,
48
49 pub vertex_offset: i32,
51
52 pub first_instance: u32,
54}
55
56#[repr(C)]
58#[derive(Clone, Copy, Debug)]
59pub struct DispatchCommand {
60 pub x: u32,
62
63 pub y: u32,
65
66 pub z: u32,
68}
69
70#[derive(Debug)]
72pub struct EncoderCommon<'a, B: rendy_core::hal::Backend, C> {
73 raw: &'a mut B::CommandBuffer,
74 capability: C,
75 family: FamilyId,
76}
77
78impl<'a, B, C> EncoderCommon<'a, B, C>
79where
80 B: rendy_core::hal::Backend,
81{
82 pub unsafe fn bind_index_buffer<'b>(
97 &mut self,
98 buffer: &'b B::Buffer,
99 offset: u64,
100 index_type: rendy_core::hal::IndexType,
101 ) where
102 C: Supports<Graphics>,
103 {
104 self.capability.assert();
105 rendy_core::hal::command::CommandBuffer::bind_index_buffer(
106 self.raw,
107 rendy_core::hal::buffer::IndexBufferView {
108 buffer: buffer,
109 offset,
110 index_type,
111 },
112 )
113 }
114
115 pub unsafe fn bind_vertex_buffers<'b>(
130 &mut self,
131 first_binding: u32,
132 buffers: impl IntoIterator<Item = (&'b B::Buffer, u64)>,
133 ) where
134 C: Supports<Graphics>,
135 {
136 self.capability.assert();
137 rendy_core::hal::command::CommandBuffer::bind_vertex_buffers(
138 self.raw,
139 first_binding,
140 buffers,
141 )
142 }
143
144 pub fn bind_graphics_pipeline(&mut self, pipeline: &B::GraphicsPipeline)
151 where
152 C: Supports<Graphics>,
153 {
154 self.capability.assert();
155
156 unsafe {
157 rendy_core::hal::command::CommandBuffer::bind_graphics_pipeline(self.raw, pipeline);
158 }
159 }
160
161 pub unsafe fn bind_graphics_descriptor_sets<'b>(
167 &mut self,
168 layout: &B::PipelineLayout,
169 first_set: u32,
170 sets: impl IntoIterator<Item = &'b B::DescriptorSet>,
171 offsets: impl IntoIterator<Item = u32>,
172 ) where
173 C: Supports<Graphics>,
174 {
175 self.capability.assert();
176
177 rendy_core::hal::command::CommandBuffer::bind_graphics_descriptor_sets(
178 self.raw,
179 layout,
180 first_set as _,
181 sets,
182 offsets,
183 );
184 }
185
186 pub fn bind_compute_pipeline(&mut self, pipeline: &B::ComputePipeline)
188 where
189 C: Supports<Compute>,
190 {
191 self.capability.assert();
192
193 unsafe {
194 rendy_core::hal::command::CommandBuffer::bind_compute_pipeline(self.raw, pipeline);
195 }
196 }
197
198 pub unsafe fn bind_compute_descriptor_sets<'b>(
204 &mut self,
205 layout: &B::PipelineLayout,
206 first_set: u32,
207 sets: impl IntoIterator<Item = &'b B::DescriptorSet>,
208 offsets: impl IntoIterator<Item = u32>,
209 ) where
210 C: Supports<Compute>,
211 {
212 self.capability.assert();
213
214 rendy_core::hal::command::CommandBuffer::bind_compute_descriptor_sets(
215 self.raw,
216 layout,
217 first_set as usize,
218 sets,
219 offsets,
220 );
221 }
222
223 pub unsafe fn pipeline_barrier<'b>(
229 &mut self,
230 stages: std::ops::Range<rendy_core::hal::pso::PipelineStage>,
231 dependencies: rendy_core::hal::memory::Dependencies,
232 barriers: impl IntoIterator<Item = rendy_core::hal::memory::Barrier<'b, B>>,
233 ) {
234 rendy_core::hal::command::CommandBuffer::pipeline_barrier(
235 self.raw,
236 stages,
237 dependencies,
238 barriers,
239 )
240 }
241
242 pub unsafe fn push_constants<'b>(
252 &mut self,
253 layout: &B::PipelineLayout,
254 stages: rendy_core::hal::pso::ShaderStageFlags,
255 offset: u32,
256 constants: &[u32],
257 ) {
258 rendy_core::hal::command::CommandBuffer::push_graphics_constants(
259 self.raw, layout, stages, offset, constants,
260 );
261 }
262
263 pub unsafe fn set_viewports<'b>(
267 &mut self,
268 first_viewport: u32,
269 viewports: impl IntoIterator<Item = &'b rendy_core::hal::pso::Viewport>,
270 ) where
271 C: Supports<Graphics>,
272 {
273 self.capability.assert();
274 rendy_core::hal::command::CommandBuffer::set_viewports(self.raw, first_viewport, viewports)
275 }
276
277 pub unsafe fn set_scissors<'b>(
286 &mut self,
287 first_scissor: u32,
288 rects: impl IntoIterator<Item = &'b rendy_core::hal::pso::Rect>,
289 ) where
290 C: Supports<Graphics>,
291 {
292 self.capability.assert();
293 rendy_core::hal::command::CommandBuffer::set_scissors(self.raw, first_scissor, rects)
294 }
295
296 pub unsafe fn set_stencil_reference(
300 &mut self,
301 faces: rendy_core::hal::pso::Face,
302 value: rendy_core::hal::pso::StencilValue,
303 ) where
304 C: Supports<Graphics>,
305 {
306 self.capability.assert();
307 rendy_core::hal::command::CommandBuffer::set_stencil_reference(self.raw, faces, value);
308 }
309
310 pub unsafe fn set_stencil_read_mask(
314 &mut self,
315 faces: rendy_core::hal::pso::Face,
316 value: rendy_core::hal::pso::StencilValue,
317 ) where
318 C: Supports<Graphics>,
319 {
320 self.capability.assert();
321 rendy_core::hal::command::CommandBuffer::set_stencil_read_mask(self.raw, faces, value);
322 }
323
324 pub unsafe fn set_stencil_write_mask(
328 &mut self,
329 faces: rendy_core::hal::pso::Face,
330 value: rendy_core::hal::pso::StencilValue,
331 ) where
332 C: Supports<Graphics>,
333 {
334 self.capability.assert();
335 rendy_core::hal::command::CommandBuffer::set_stencil_write_mask(self.raw, faces, value);
336 }
337
338 pub unsafe fn set_blend_constants(&mut self, color: rendy_core::hal::pso::ColorValue)
342 where
343 C: Supports<Graphics>,
344 {
345 self.capability.assert();
346 rendy_core::hal::command::CommandBuffer::set_blend_constants(self.raw, color);
347 }
348
349 pub unsafe fn set_depth_bounds(&mut self, bounds: std::ops::Range<f32>)
353 where
354 C: Supports<Graphics>,
355 {
356 self.capability.assert();
357 rendy_core::hal::command::CommandBuffer::set_depth_bounds(self.raw, bounds);
358 }
359
360 pub unsafe fn set_line_width(&mut self, width: f32)
364 where
365 C: Supports<Graphics>,
366 {
367 self.capability.assert();
368 rendy_core::hal::command::CommandBuffer::set_line_width(self.raw, width);
369 }
370
371 pub unsafe fn set_depth_bias(&mut self, depth_bias: rendy_core::hal::pso::DepthBias)
375 where
376 C: Supports<Graphics>,
377 {
378 self.capability.assert();
379 rendy_core::hal::command::CommandBuffer::set_depth_bias(self.raw, depth_bias);
380 }
381
382 pub fn reborrow<K>(&mut self) -> EncoderCommon<'_, B, K>
384 where
385 C: Supports<K>,
386 {
387 EncoderCommon {
388 capability: self.capability.supports().unwrap(),
389 raw: &mut *self.raw,
390 family: self.family,
391 }
392 }
393}
394
395#[derive(Debug)]
397pub struct RenderPassEncoder<'a, B: rendy_core::hal::Backend> {
398 inner: EncoderCommon<'a, B, Graphics>,
399}
400
401impl<'a, B> std::ops::Deref for RenderPassEncoder<'a, B>
402where
403 B: rendy_core::hal::Backend,
404{
405 type Target = EncoderCommon<'a, B, Graphics>;
406
407 fn deref(&self) -> &EncoderCommon<'a, B, Graphics> {
408 &self.inner
409 }
410}
411
412impl<'a, B> std::ops::DerefMut for RenderPassEncoder<'a, B>
413where
414 B: rendy_core::hal::Backend,
415{
416 fn deref_mut(&mut self) -> &mut EncoderCommon<'a, B, Graphics> {
417 &mut self.inner
418 }
419}
420
421impl<'a, B> RenderPassEncoder<'a, B>
422where
423 B: rendy_core::hal::Backend,
424{
425 pub unsafe fn clear_attachments(
429 &mut self,
430 clears: impl IntoIterator<
431 Item = impl std::borrow::Borrow<rendy_core::hal::command::AttachmentClear>,
432 >,
433 rects: impl IntoIterator<Item = impl std::borrow::Borrow<rendy_core::hal::pso::ClearRect>>,
434 ) {
435 rendy_core::hal::command::CommandBuffer::clear_attachments(self.inner.raw, clears, rects);
436 }
437
438 pub unsafe fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
448 rendy_core::hal::command::CommandBuffer::draw(self.inner.raw, vertices, instances)
449 }
450
451 pub unsafe fn draw_indexed(
461 &mut self,
462 indices: std::ops::Range<u32>,
463 base_vertex: i32,
464 instances: std::ops::Range<u32>,
465 ) {
466 rendy_core::hal::command::CommandBuffer::draw_indexed(
467 self.inner.raw,
468 indices,
469 base_vertex,
470 instances,
471 )
472 }
473
474 pub unsafe fn draw_indirect(
487 &mut self,
488 buffer: &B::Buffer,
489 offset: u64,
490 draw_count: u32,
491 stride: u32,
492 ) {
493 rendy_core::hal::command::CommandBuffer::draw_indirect(
494 self.inner.raw,
495 buffer,
496 offset,
497 draw_count,
498 stride,
499 )
500 }
501
502 pub unsafe fn draw_indexed_indirect(
515 &mut self,
516 buffer: &B::Buffer,
517 offset: u64,
518 draw_count: u32,
519 stride: u32,
520 ) {
521 rendy_core::hal::command::CommandBuffer::draw_indexed_indirect(
522 self.inner.raw,
523 buffer,
524 offset,
525 draw_count,
526 stride,
527 )
528 }
529
530 pub fn reborrow(&mut self) -> RenderPassEncoder<'_, B> {
532 RenderPassEncoder {
533 inner: self.inner.reborrow(),
534 }
535 }
536}
537
538#[derive(Debug)]
540pub struct RenderPassInlineEncoder<'a, B: rendy_core::hal::Backend> {
541 inner: RenderPassEncoder<'a, B>,
542}
543
544impl<'a, B> Drop for RenderPassInlineEncoder<'a, B>
545where
546 B: rendy_core::hal::Backend,
547{
548 fn drop(&mut self) {
549 unsafe { rendy_core::hal::command::CommandBuffer::end_render_pass(self.inner.inner.raw) }
550 }
551}
552
553impl<'a, B> std::ops::Deref for RenderPassInlineEncoder<'a, B>
554where
555 B: rendy_core::hal::Backend,
556{
557 type Target = RenderPassEncoder<'a, B>;
558
559 fn deref(&self) -> &RenderPassEncoder<'a, B> {
560 &self.inner
561 }
562}
563
564impl<'a, B> std::ops::DerefMut for RenderPassInlineEncoder<'a, B>
565where
566 B: rendy_core::hal::Backend,
567{
568 fn deref_mut(&mut self) -> &mut RenderPassEncoder<'a, B> {
569 &mut self.inner
570 }
571}
572
573impl<'a, B> RenderPassInlineEncoder<'a, B>
574where
575 B: rendy_core::hal::Backend,
576{
577 pub fn next_subpass_inline(self) -> RenderPassInlineEncoder<'a, B> {
579 unsafe {
580 rendy_core::hal::command::CommandBuffer::next_subpass(
581 self.inner.inner.raw,
582 rendy_core::hal::command::SubpassContents::Inline,
583 );
584 }
585
586 self
587 }
588
589 pub fn next_subpass_secondary(self) -> RenderPassSecondaryEncoder<'a, B> {
591 unsafe {
592 rendy_core::hal::command::CommandBuffer::next_subpass(
593 self.inner.inner.raw,
594 rendy_core::hal::command::SubpassContents::SecondaryBuffers,
595 );
596 }
597
598 unsafe {
599 let next = RenderPassSecondaryEncoder {
600 inner: std::ptr::read(&self.inner.inner),
601 };
602
603 std::mem::forget(self);
604 next
605 }
606 }
607}
608
609#[derive(Debug)]
611pub struct RenderPassSecondaryEncoder<'a, B: rendy_core::hal::Backend> {
612 inner: EncoderCommon<'a, B, Graphics>,
613}
614
615impl<'a, B> Drop for RenderPassSecondaryEncoder<'a, B>
616where
617 B: rendy_core::hal::Backend,
618{
619 fn drop(&mut self) {
620 unsafe { rendy_core::hal::command::CommandBuffer::end_render_pass(self.inner.raw) }
621 }
622}
623
624impl<'a, B> RenderPassSecondaryEncoder<'a, B>
625where
626 B: rendy_core::hal::Backend,
627{
628 pub fn execute_commands(
630 &mut self,
631 submittables: impl IntoIterator<Item = impl Submittable<B, SecondaryLevel, RenderPassContinue>>,
632 ) {
633 let family = self.inner.family;
634 unsafe {
635 rendy_core::hal::command::CommandBuffer::execute_commands(
636 self.inner.raw,
637 submittables.into_iter().map(|submit| {
638 assert_eq!(family, submit.family());
639 submit.raw()
640 }),
641 )
642 }
643 }
644
645 pub fn next_subpass_inline(self) -> RenderPassInlineEncoder<'a, B> {
647 unsafe {
648 rendy_core::hal::command::CommandBuffer::next_subpass(
649 self.inner.raw,
650 rendy_core::hal::command::SubpassContents::Inline,
651 );
652
653 let next = RenderPassInlineEncoder {
654 inner: RenderPassEncoder {
655 inner: std::ptr::read(&self.inner),
656 },
657 };
658
659 std::mem::forget(self);
660 next
661 }
662 }
663
664 pub fn next_subpass_secondary(self) -> RenderPassSecondaryEncoder<'a, B> {
666 unsafe {
667 rendy_core::hal::command::CommandBuffer::next_subpass(
668 self.inner.raw,
669 rendy_core::hal::command::SubpassContents::SecondaryBuffers,
670 );
671 }
672
673 self
674 }
675}
676
677#[derive(Debug)]
679pub struct Encoder<'a, B: rendy_core::hal::Backend, C, L> {
680 inner: EncoderCommon<'a, B, C>,
681 level: L,
682}
683
684impl<'a, B, C, L> std::ops::Deref for Encoder<'a, B, C, L>
685where
686 B: rendy_core::hal::Backend,
687{
688 type Target = EncoderCommon<'a, B, C>;
689
690 fn deref(&self) -> &EncoderCommon<'a, B, C> {
691 &self.inner
692 }
693}
694
695impl<'a, B, C, L> std::ops::DerefMut for Encoder<'a, B, C, L>
696where
697 B: rendy_core::hal::Backend,
698{
699 fn deref_mut(&mut self) -> &mut EncoderCommon<'a, B, C> {
700 &mut self.inner
701 }
702}
703
704impl<'a, B, C> Encoder<'a, B, C, PrimaryLevel>
705where
706 B: rendy_core::hal::Backend,
707{
708 pub fn begin_render_pass_inline(
710 &mut self,
711 render_pass: &B::RenderPass,
712 framebuffer: &B::Framebuffer,
713 render_area: rendy_core::hal::pso::Rect,
714 clear_values: &[rendy_core::hal::command::ClearValue],
715 ) -> RenderPassInlineEncoder<'_, B>
716 where
717 C: Supports<Graphics>,
718 {
719 self.capability.assert();
720
721 unsafe {
722 rendy_core::hal::command::CommandBuffer::begin_render_pass(
723 self.inner.raw,
724 render_pass,
725 framebuffer,
726 render_area,
727 clear_values,
728 rendy_core::hal::command::SubpassContents::Inline,
729 )
730 }
731
732 RenderPassInlineEncoder {
733 inner: RenderPassEncoder {
734 inner: self.inner.reborrow(),
735 },
736 }
737 }
738
739 pub fn begin_render_pass_secondary(
741 &mut self,
742 render_pass: &B::RenderPass,
743 framebuffer: &B::Framebuffer,
744 render_area: rendy_core::hal::pso::Rect,
745 clear_values: &[rendy_core::hal::command::ClearValue],
746 ) -> RenderPassSecondaryEncoder<'_, B>
747 where
748 C: Supports<Graphics>,
749 {
750 self.capability.assert();
751
752 unsafe {
753 rendy_core::hal::command::CommandBuffer::begin_render_pass(
754 self.inner.raw,
755 render_pass,
756 framebuffer,
757 render_area,
758 clear_values,
759 rendy_core::hal::command::SubpassContents::SecondaryBuffers,
760 )
761 }
762
763 RenderPassSecondaryEncoder {
764 inner: self.inner.reborrow(),
765 }
766 }
767
768 pub fn execute_commands(
770 &mut self,
771 submittables: impl IntoIterator<Item = impl Submittable<B, SecondaryLevel>>,
772 ) {
773 let family = self.inner.family;
774 unsafe {
775 rendy_core::hal::command::CommandBuffer::execute_commands(
776 self.inner.raw,
777 submittables.into_iter().map(|submit| {
778 assert_eq!(family, submit.family());
779 submit.raw()
780 }),
781 )
782 }
783 }
784}
785
786impl<'a, B, C, L> Encoder<'a, B, C, L>
787where
788 B: rendy_core::hal::Backend,
789{
790 pub fn level(&self) -> L
792 where
793 L: Level,
794 {
795 self.level
796 }
797
798 pub unsafe fn copy_buffer(
810 &mut self,
811 src: &B::Buffer,
812 dst: &B::Buffer,
813 regions: impl IntoIterator<Item = rendy_core::hal::command::BufferCopy>,
814 ) where
815 C: Supports<Transfer>,
816 {
817 self.capability.assert();
818
819 rendy_core::hal::command::CommandBuffer::copy_buffer(self.inner.raw, src, dst, regions)
820 }
821
822 pub unsafe fn copy_buffer_to_image(
830 &mut self,
831 src: &B::Buffer,
832 dst: &B::Image,
833 dst_layout: rendy_core::hal::image::Layout,
834 regions: impl IntoIterator<Item = rendy_core::hal::command::BufferImageCopy>,
835 ) where
836 C: Supports<Transfer>,
837 {
838 self.capability.assert();
839
840 rendy_core::hal::command::CommandBuffer::copy_buffer_to_image(
841 self.inner.raw,
842 src,
843 dst,
844 dst_layout,
845 regions,
846 )
847 }
848
849 pub unsafe fn copy_image(
857 &mut self,
858 src: &B::Image,
859 src_layout: rendy_core::hal::image::Layout,
860 dst: &B::Image,
861 dst_layout: rendy_core::hal::image::Layout,
862 regions: impl IntoIterator<Item = rendy_core::hal::command::ImageCopy>,
863 ) where
864 C: Supports<Transfer>,
865 {
866 self.capability.assert();
867
868 rendy_core::hal::command::CommandBuffer::copy_image(
869 self.inner.raw,
870 src,
871 src_layout,
872 dst,
873 dst_layout,
874 regions,
875 )
876 }
877
878 pub unsafe fn blit_image(
886 &mut self,
887 src: &B::Image,
888 src_layout: rendy_core::hal::image::Layout,
889 dst: &B::Image,
890 dst_layout: rendy_core::hal::image::Layout,
891 filter: rendy_core::hal::image::Filter,
892 regions: impl IntoIterator<Item = rendy_core::hal::command::ImageBlit>,
893 ) where
894 C: Supports<Graphics>,
895 {
896 self.capability.assert();
897
898 rendy_core::hal::command::CommandBuffer::blit_image(
899 self.inner.raw,
900 src,
901 src_layout,
902 dst,
903 dst_layout,
904 filter,
905 regions,
906 )
907 }
908
909 pub unsafe fn dispatch(&mut self, x: u32, y: u32, z: u32)
915 where
916 C: Supports<Compute>,
917 {
918 self.capability.assert();
919
920 rendy_core::hal::command::CommandBuffer::dispatch(self.inner.raw, [x, y, z])
921 }
922
923 pub unsafe fn dispatch_indirect(&mut self, buffer: &B::Buffer, offset: u64)
934 where
935 C: Supports<Compute>,
936 {
937 self.capability.assert();
938
939 rendy_core::hal::command::CommandBuffer::dispatch_indirect(self.inner.raw, buffer, offset)
940 }
941}
942
943impl<B, C, U, L, R> CommandBuffer<B, C, RecordingState<U>, L, R>
944where
945 B: rendy_core::hal::Backend,
946 C: Capability,
947 L: Level,
948{
949 pub fn encoder(&mut self) -> Encoder<'_, B, C, L> {
951 Encoder {
952 level: self.level,
953 inner: EncoderCommon {
954 capability: self.capability,
955 family: self.family,
956 raw: self.raw(),
957 },
958 }
959 }
960}
961
962impl<B, C, U, R> CommandBuffer<B, C, RecordingState<U, RenderPassContinue>, SecondaryLevel, R>
963where
964 B: rendy_core::hal::Backend,
965 C: Supports<Graphics>,
966{
967 pub fn render_pass_encoder(&mut self) -> RenderPassEncoder<'_, B> {
969 RenderPassEncoder {
970 inner: EncoderCommon {
971 capability: self.capability.supports().unwrap(),
972 family: self.family,
973 raw: self.raw(),
974 },
975 }
976 }
977}