use {
super::{
level::{Level, PrimaryLevel, SecondaryLevel},
state::RecordingState,
submit::Submittable,
usage::RenderPassContinue,
CommandBuffer,
},
crate::{
capability::{Capability, Compute, Graphics, Supports, Transfer},
family::FamilyId,
},
};
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DrawCommand {
pub vertex_count: u32,
pub instance_count: u32,
pub first_vertex: u32,
pub first_instance: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DrawIndexedCommand {
pub index_count: u32,
pub instance_count: u32,
pub first_index: u32,
pub vertex_offset: i32,
pub first_instance: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct DispatchCommand {
pub x: u32,
pub y: u32,
pub z: u32,
}
#[derive(Debug)]
pub struct EncoderCommon<'a, B: rendy_core::hal::Backend, C> {
raw: &'a mut B::CommandBuffer,
capability: C,
family: FamilyId,
}
impl<'a, B, C> EncoderCommon<'a, B, C>
where
B: rendy_core::hal::Backend,
{
pub unsafe fn bind_index_buffer<'b>(
&mut self,
buffer: &'b B::Buffer,
offset: u64,
index_type: rendy_core::hal::IndexType,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::bind_index_buffer(
self.raw,
rendy_core::hal::buffer::IndexBufferView {
buffer: buffer,
offset,
index_type,
},
)
}
pub unsafe fn bind_vertex_buffers<'b>(
&mut self,
first_binding: u32,
buffers: impl IntoIterator<Item = (&'b B::Buffer, u64)>,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::bind_vertex_buffers(
self.raw,
first_binding,
buffers,
)
}
pub fn bind_graphics_pipeline(&mut self, pipeline: &B::GraphicsPipeline)
where
C: Supports<Graphics>,
{
self.capability.assert();
unsafe {
rendy_core::hal::command::CommandBuffer::bind_graphics_pipeline(self.raw, pipeline);
}
}
pub unsafe fn bind_graphics_descriptor_sets<'b>(
&mut self,
layout: &B::PipelineLayout,
first_set: u32,
sets: impl IntoIterator<Item = &'b B::DescriptorSet>,
offsets: impl IntoIterator<Item = u32>,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::bind_graphics_descriptor_sets(
self.raw,
layout,
first_set as _,
sets,
offsets,
);
}
pub fn bind_compute_pipeline(&mut self, pipeline: &B::ComputePipeline)
where
C: Supports<Compute>,
{
self.capability.assert();
unsafe {
rendy_core::hal::command::CommandBuffer::bind_compute_pipeline(self.raw, pipeline);
}
}
pub unsafe fn bind_compute_descriptor_sets<'b>(
&mut self,
layout: &B::PipelineLayout,
first_set: u32,
sets: impl IntoIterator<Item = &'b B::DescriptorSet>,
offsets: impl IntoIterator<Item = u32>,
) where
C: Supports<Compute>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::bind_compute_descriptor_sets(
self.raw,
layout,
first_set as usize,
sets,
offsets,
);
}
pub unsafe fn pipeline_barrier<'b>(
&mut self,
stages: std::ops::Range<rendy_core::hal::pso::PipelineStage>,
dependencies: rendy_core::hal::memory::Dependencies,
barriers: impl IntoIterator<Item = rendy_core::hal::memory::Barrier<'b, B>>,
) {
rendy_core::hal::command::CommandBuffer::pipeline_barrier(
self.raw,
stages,
dependencies,
barriers,
)
}
pub unsafe fn push_constants<'b>(
&mut self,
layout: &B::PipelineLayout,
stages: rendy_core::hal::pso::ShaderStageFlags,
offset: u32,
constants: &[u32],
) {
rendy_core::hal::command::CommandBuffer::push_graphics_constants(
self.raw, layout, stages, offset, constants,
);
}
pub unsafe fn set_viewports<'b>(
&mut self,
first_viewport: u32,
viewports: impl IntoIterator<Item = &'b rendy_core::hal::pso::Viewport>,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_viewports(self.raw, first_viewport, viewports)
}
pub unsafe fn set_scissors<'b>(
&mut self,
first_scissor: u32,
rects: impl IntoIterator<Item = &'b rendy_core::hal::pso::Rect>,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_scissors(self.raw, first_scissor, rects)
}
pub unsafe fn set_stencil_reference(
&mut self,
faces: rendy_core::hal::pso::Face,
value: rendy_core::hal::pso::StencilValue,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_stencil_reference(self.raw, faces, value);
}
pub unsafe fn set_stencil_read_mask(
&mut self,
faces: rendy_core::hal::pso::Face,
value: rendy_core::hal::pso::StencilValue,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_stencil_read_mask(self.raw, faces, value);
}
pub unsafe fn set_stencil_write_mask(
&mut self,
faces: rendy_core::hal::pso::Face,
value: rendy_core::hal::pso::StencilValue,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_stencil_write_mask(self.raw, faces, value);
}
pub unsafe fn set_blend_constants(&mut self, color: rendy_core::hal::pso::ColorValue)
where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_blend_constants(self.raw, color);
}
pub unsafe fn set_depth_bounds(&mut self, bounds: std::ops::Range<f32>)
where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_depth_bounds(self.raw, bounds);
}
pub unsafe fn set_line_width(&mut self, width: f32)
where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_line_width(self.raw, width);
}
pub unsafe fn set_depth_bias(&mut self, depth_bias: rendy_core::hal::pso::DepthBias)
where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::set_depth_bias(self.raw, depth_bias);
}
pub fn reborrow<K>(&mut self) -> EncoderCommon<'_, B, K>
where
C: Supports<K>,
{
EncoderCommon {
capability: self.capability.supports().unwrap(),
raw: &mut *self.raw,
family: self.family,
}
}
}
#[derive(Debug)]
pub struct RenderPassEncoder<'a, B: rendy_core::hal::Backend> {
inner: EncoderCommon<'a, B, Graphics>,
}
impl<'a, B> std::ops::Deref for RenderPassEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
type Target = EncoderCommon<'a, B, Graphics>;
fn deref(&self) -> &EncoderCommon<'a, B, Graphics> {
&self.inner
}
}
impl<'a, B> std::ops::DerefMut for RenderPassEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
fn deref_mut(&mut self) -> &mut EncoderCommon<'a, B, Graphics> {
&mut self.inner
}
}
impl<'a, B> RenderPassEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
pub unsafe fn clear_attachments(
&mut self,
clears: impl IntoIterator<
Item = impl std::borrow::Borrow<rendy_core::hal::command::AttachmentClear>,
>,
rects: impl IntoIterator<Item = impl std::borrow::Borrow<rendy_core::hal::pso::ClearRect>>,
) {
rendy_core::hal::command::CommandBuffer::clear_attachments(self.inner.raw, clears, rects);
}
pub unsafe fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
rendy_core::hal::command::CommandBuffer::draw(self.inner.raw, vertices, instances)
}
pub unsafe fn draw_indexed(
&mut self,
indices: std::ops::Range<u32>,
base_vertex: i32,
instances: std::ops::Range<u32>,
) {
rendy_core::hal::command::CommandBuffer::draw_indexed(
self.inner.raw,
indices,
base_vertex,
instances,
)
}
pub unsafe fn draw_indirect(
&mut self,
buffer: &B::Buffer,
offset: u64,
draw_count: u32,
stride: u32,
) {
rendy_core::hal::command::CommandBuffer::draw_indirect(
self.inner.raw,
buffer,
offset,
draw_count,
stride,
)
}
pub unsafe fn draw_indexed_indirect(
&mut self,
buffer: &B::Buffer,
offset: u64,
draw_count: u32,
stride: u32,
) {
rendy_core::hal::command::CommandBuffer::draw_indexed_indirect(
self.inner.raw,
buffer,
offset,
draw_count,
stride,
)
}
pub fn reborrow(&mut self) -> RenderPassEncoder<'_, B> {
RenderPassEncoder {
inner: self.inner.reborrow(),
}
}
}
#[derive(Debug)]
pub struct RenderPassInlineEncoder<'a, B: rendy_core::hal::Backend> {
inner: RenderPassEncoder<'a, B>,
}
impl<'a, B> Drop for RenderPassInlineEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
fn drop(&mut self) {
unsafe { rendy_core::hal::command::CommandBuffer::end_render_pass(self.inner.inner.raw) }
}
}
impl<'a, B> std::ops::Deref for RenderPassInlineEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
type Target = RenderPassEncoder<'a, B>;
fn deref(&self) -> &RenderPassEncoder<'a, B> {
&self.inner
}
}
impl<'a, B> std::ops::DerefMut for RenderPassInlineEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
fn deref_mut(&mut self) -> &mut RenderPassEncoder<'a, B> {
&mut self.inner
}
}
impl<'a, B> RenderPassInlineEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
pub fn next_subpass_inline(self) -> RenderPassInlineEncoder<'a, B> {
unsafe {
rendy_core::hal::command::CommandBuffer::next_subpass(
self.inner.inner.raw,
rendy_core::hal::command::SubpassContents::Inline,
);
}
self
}
pub fn next_subpass_secondary(self) -> RenderPassSecondaryEncoder<'a, B> {
unsafe {
rendy_core::hal::command::CommandBuffer::next_subpass(
self.inner.inner.raw,
rendy_core::hal::command::SubpassContents::SecondaryBuffers,
);
}
unsafe {
let next = RenderPassSecondaryEncoder {
inner: std::ptr::read(&self.inner.inner),
};
std::mem::forget(self);
next
}
}
}
#[derive(Debug)]
pub struct RenderPassSecondaryEncoder<'a, B: rendy_core::hal::Backend> {
inner: EncoderCommon<'a, B, Graphics>,
}
impl<'a, B> Drop for RenderPassSecondaryEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
fn drop(&mut self) {
unsafe { rendy_core::hal::command::CommandBuffer::end_render_pass(self.inner.raw) }
}
}
impl<'a, B> RenderPassSecondaryEncoder<'a, B>
where
B: rendy_core::hal::Backend,
{
pub fn execute_commands(
&mut self,
submittables: impl IntoIterator<Item = impl Submittable<B, SecondaryLevel, RenderPassContinue>>,
) {
let family = self.inner.family;
unsafe {
rendy_core::hal::command::CommandBuffer::execute_commands(
self.inner.raw,
submittables.into_iter().map(|submit| {
assert_eq!(family, submit.family());
submit.raw()
}),
)
}
}
pub fn next_subpass_inline(self) -> RenderPassInlineEncoder<'a, B> {
unsafe {
rendy_core::hal::command::CommandBuffer::next_subpass(
self.inner.raw,
rendy_core::hal::command::SubpassContents::Inline,
);
let next = RenderPassInlineEncoder {
inner: RenderPassEncoder {
inner: std::ptr::read(&self.inner),
},
};
std::mem::forget(self);
next
}
}
pub fn next_subpass_secondary(self) -> RenderPassSecondaryEncoder<'a, B> {
unsafe {
rendy_core::hal::command::CommandBuffer::next_subpass(
self.inner.raw,
rendy_core::hal::command::SubpassContents::SecondaryBuffers,
);
}
self
}
}
#[derive(Debug)]
pub struct Encoder<'a, B: rendy_core::hal::Backend, C, L> {
inner: EncoderCommon<'a, B, C>,
level: L,
}
impl<'a, B, C, L> std::ops::Deref for Encoder<'a, B, C, L>
where
B: rendy_core::hal::Backend,
{
type Target = EncoderCommon<'a, B, C>;
fn deref(&self) -> &EncoderCommon<'a, B, C> {
&self.inner
}
}
impl<'a, B, C, L> std::ops::DerefMut for Encoder<'a, B, C, L>
where
B: rendy_core::hal::Backend,
{
fn deref_mut(&mut self) -> &mut EncoderCommon<'a, B, C> {
&mut self.inner
}
}
impl<'a, B, C> Encoder<'a, B, C, PrimaryLevel>
where
B: rendy_core::hal::Backend,
{
pub fn begin_render_pass_inline(
&mut self,
render_pass: &B::RenderPass,
framebuffer: &B::Framebuffer,
render_area: rendy_core::hal::pso::Rect,
clear_values: &[rendy_core::hal::command::ClearValue],
) -> RenderPassInlineEncoder<'_, B>
where
C: Supports<Graphics>,
{
self.capability.assert();
unsafe {
rendy_core::hal::command::CommandBuffer::begin_render_pass(
self.inner.raw,
render_pass,
framebuffer,
render_area,
clear_values,
rendy_core::hal::command::SubpassContents::Inline,
)
}
RenderPassInlineEncoder {
inner: RenderPassEncoder {
inner: self.inner.reborrow(),
},
}
}
pub fn begin_render_pass_secondary(
&mut self,
render_pass: &B::RenderPass,
framebuffer: &B::Framebuffer,
render_area: rendy_core::hal::pso::Rect,
clear_values: &[rendy_core::hal::command::ClearValue],
) -> RenderPassSecondaryEncoder<'_, B>
where
C: Supports<Graphics>,
{
self.capability.assert();
unsafe {
rendy_core::hal::command::CommandBuffer::begin_render_pass(
self.inner.raw,
render_pass,
framebuffer,
render_area,
clear_values,
rendy_core::hal::command::SubpassContents::SecondaryBuffers,
)
}
RenderPassSecondaryEncoder {
inner: self.inner.reborrow(),
}
}
pub fn execute_commands(
&mut self,
submittables: impl IntoIterator<Item = impl Submittable<B, SecondaryLevel>>,
) {
let family = self.inner.family;
unsafe {
rendy_core::hal::command::CommandBuffer::execute_commands(
self.inner.raw,
submittables.into_iter().map(|submit| {
assert_eq!(family, submit.family());
submit.raw()
}),
)
}
}
}
impl<'a, B, C, L> Encoder<'a, B, C, L>
where
B: rendy_core::hal::Backend,
{
pub fn level(&self) -> L
where
L: Level,
{
self.level
}
pub unsafe fn copy_buffer(
&mut self,
src: &B::Buffer,
dst: &B::Buffer,
regions: impl IntoIterator<Item = rendy_core::hal::command::BufferCopy>,
) where
C: Supports<Transfer>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::copy_buffer(self.inner.raw, src, dst, regions)
}
pub unsafe fn copy_buffer_to_image(
&mut self,
src: &B::Buffer,
dst: &B::Image,
dst_layout: rendy_core::hal::image::Layout,
regions: impl IntoIterator<Item = rendy_core::hal::command::BufferImageCopy>,
) where
C: Supports<Transfer>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::copy_buffer_to_image(
self.inner.raw,
src,
dst,
dst_layout,
regions,
)
}
pub unsafe fn copy_image(
&mut self,
src: &B::Image,
src_layout: rendy_core::hal::image::Layout,
dst: &B::Image,
dst_layout: rendy_core::hal::image::Layout,
regions: impl IntoIterator<Item = rendy_core::hal::command::ImageCopy>,
) where
C: Supports<Transfer>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::copy_image(
self.inner.raw,
src,
src_layout,
dst,
dst_layout,
regions,
)
}
pub unsafe fn blit_image(
&mut self,
src: &B::Image,
src_layout: rendy_core::hal::image::Layout,
dst: &B::Image,
dst_layout: rendy_core::hal::image::Layout,
filter: rendy_core::hal::image::Filter,
regions: impl IntoIterator<Item = rendy_core::hal::command::ImageBlit>,
) where
C: Supports<Graphics>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::blit_image(
self.inner.raw,
src,
src_layout,
dst,
dst_layout,
filter,
regions,
)
}
pub unsafe fn dispatch(&mut self, x: u32, y: u32, z: u32)
where
C: Supports<Compute>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::dispatch(self.inner.raw, [x, y, z])
}
pub unsafe fn dispatch_indirect(&mut self, buffer: &B::Buffer, offset: u64)
where
C: Supports<Compute>,
{
self.capability.assert();
rendy_core::hal::command::CommandBuffer::dispatch_indirect(self.inner.raw, buffer, offset)
}
}
impl<B, C, U, L, R> CommandBuffer<B, C, RecordingState<U>, L, R>
where
B: rendy_core::hal::Backend,
C: Capability,
L: Level,
{
pub fn encoder(&mut self) -> Encoder<'_, B, C, L> {
Encoder {
level: self.level,
inner: EncoderCommon {
capability: self.capability,
family: self.family,
raw: self.raw(),
},
}
}
}
impl<B, C, U, R> CommandBuffer<B, C, RecordingState<U, RenderPassContinue>, SecondaryLevel, R>
where
B: rendy_core::hal::Backend,
C: Supports<Graphics>,
{
pub fn render_pass_encoder(&mut self) -> RenderPassEncoder<'_, B> {
RenderPassEncoder {
inner: EncoderCommon {
capability: self.capability.supports().unwrap(),
family: self.family,
raw: self.raw(),
},
}
}
}