use std::{marker::PhantomData, ops::Range, sync::Arc, thread};
use crate::context::DynContext;
use crate::*;
#[derive(Debug)]
pub(crate) struct RenderPassInner {
pub(crate) data: Box<Data>,
pub(crate) context: Arc<C>,
}
impl Drop for RenderPassInner {
fn drop(&mut self) {
if !thread::panicking() {
self.context.render_pass_end(self.data.as_mut());
}
}
}
#[derive(Debug)]
pub struct RenderPass<'encoder> {
pub(crate) inner: RenderPassInner,
pub(crate) encoder_guard: PhantomData<&'encoder ()>,
}
impl<'encoder> RenderPass<'encoder> {
pub fn forget_lifetime(self) -> RenderPass<'static> {
RenderPass {
inner: self.inner,
encoder_guard: PhantomData,
}
}
pub fn set_bind_group<'a>(
&mut self,
index: u32,
bind_group: impl Into<Option<&'a BindGroup>>,
offsets: &[DynamicOffset],
) {
let bg = bind_group.into().map(|x| x.data.as_ref());
DynContext::render_pass_set_bind_group(
&*self.inner.context,
self.inner.data.as_mut(),
index,
bg,
offsets,
)
}
pub fn set_pipeline(&mut self, pipeline: &RenderPipeline) {
DynContext::render_pass_set_pipeline(
&*self.inner.context,
self.inner.data.as_mut(),
pipeline.data.as_ref(),
)
}
pub fn set_blend_constant(&mut self, color: Color) {
DynContext::render_pass_set_blend_constant(
&*self.inner.context,
self.inner.data.as_mut(),
color,
)
}
pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'_>, index_format: IndexFormat) {
DynContext::render_pass_set_index_buffer(
&*self.inner.context,
self.inner.data.as_mut(),
buffer_slice.buffer.data.as_ref(),
index_format,
buffer_slice.offset,
buffer_slice.size,
)
}
pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'_>) {
DynContext::render_pass_set_vertex_buffer(
&*self.inner.context,
self.inner.data.as_mut(),
slot,
buffer_slice.buffer.data.as_ref(),
buffer_slice.offset,
buffer_slice.size,
)
}
pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
DynContext::render_pass_set_scissor_rect(
&*self.inner.context,
self.inner.data.as_mut(),
x,
y,
width,
height,
);
}
pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) {
DynContext::render_pass_set_viewport(
&*self.inner.context,
self.inner.data.as_mut(),
x,
y,
w,
h,
min_depth,
max_depth,
);
}
pub fn set_stencil_reference(&mut self, reference: u32) {
DynContext::render_pass_set_stencil_reference(
&*self.inner.context,
self.inner.data.as_mut(),
reference,
);
}
pub fn insert_debug_marker(&mut self, label: &str) {
DynContext::render_pass_insert_debug_marker(
&*self.inner.context,
self.inner.data.as_mut(),
label,
);
}
pub fn push_debug_group(&mut self, label: &str) {
DynContext::render_pass_push_debug_group(
&*self.inner.context,
self.inner.data.as_mut(),
label,
);
}
pub fn pop_debug_group(&mut self) {
DynContext::render_pass_pop_debug_group(&*self.inner.context, self.inner.data.as_mut());
}
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
DynContext::render_pass_draw(
&*self.inner.context,
self.inner.data.as_mut(),
vertices,
instances,
)
}
pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
DynContext::render_pass_draw_indexed(
&*self.inner.context,
self.inner.data.as_mut(),
indices,
base_vertex,
instances,
);
}
pub fn draw_indirect(&mut self, indirect_buffer: &Buffer, indirect_offset: BufferAddress) {
DynContext::render_pass_draw_indirect(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
);
}
pub fn draw_indexed_indirect(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: BufferAddress,
) {
DynContext::render_pass_draw_indexed_indirect(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
);
}
pub fn execute_bundles<'a, I: IntoIterator<Item = &'a RenderBundle>>(
&mut self,
render_bundles: I,
) {
let mut render_bundles = render_bundles.into_iter().map(|rb| rb.data.as_ref());
DynContext::render_pass_execute_bundles(
&*self.inner.context,
self.inner.data.as_mut(),
&mut render_bundles,
)
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn multi_draw_indirect(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: BufferAddress,
count: u32,
) {
DynContext::render_pass_multi_draw_indirect(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
count,
);
}
pub fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: BufferAddress,
count: u32,
) {
DynContext::render_pass_multi_draw_indexed_indirect(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
count,
);
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: BufferAddress,
count_buffer: &Buffer,
count_offset: BufferAddress,
max_count: u32,
) {
DynContext::render_pass_multi_draw_indirect_count(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
count_buffer.data.as_ref(),
count_offset,
max_count,
);
}
pub fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &Buffer,
indirect_offset: BufferAddress,
count_buffer: &Buffer,
count_offset: BufferAddress,
max_count: u32,
) {
DynContext::render_pass_multi_draw_indexed_indirect_count(
&*self.inner.context,
self.inner.data.as_mut(),
indirect_buffer.data.as_ref(),
indirect_offset,
count_buffer.data.as_ref(),
count_offset,
max_count,
);
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) {
DynContext::render_pass_set_push_constants(
&*self.inner.context,
self.inner.data.as_mut(),
stages,
offset,
data,
);
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
DynContext::render_pass_write_timestamp(
&*self.inner.context,
self.inner.data.as_mut(),
query_set.data.as_ref(),
query_index,
)
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn begin_occlusion_query(&mut self, query_index: u32) {
DynContext::render_pass_begin_occlusion_query(
&*self.inner.context,
self.inner.data.as_mut(),
query_index,
);
}
pub fn end_occlusion_query(&mut self) {
DynContext::render_pass_end_occlusion_query(&*self.inner.context, self.inner.data.as_mut());
}
}
impl<'encoder> RenderPass<'encoder> {
pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) {
DynContext::render_pass_begin_pipeline_statistics_query(
&*self.inner.context,
self.inner.data.as_mut(),
query_set.data.as_ref(),
query_index,
);
}
pub fn end_pipeline_statistics_query(&mut self) {
DynContext::render_pass_end_pipeline_statistics_query(
&*self.inner.context,
self.inner.data.as_mut(),
);
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LoadOp<V> {
Clear(V),
Load,
}
impl<V: Default> Default for LoadOp<V> {
fn default() -> Self {
Self::Clear(Default::default())
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum StoreOp {
#[default]
Store,
Discard,
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Operations<V> {
pub load: LoadOp<V>,
pub store: StoreOp,
}
impl<V: Default> Default for Operations<V> {
#[inline]
fn default() -> Self {
Self {
load: LoadOp::<V>::default(),
store: StoreOp::default(),
}
}
}
#[derive(Clone, Debug)]
pub struct RenderPassTimestampWrites<'a> {
pub query_set: &'a QuerySet,
pub beginning_of_pass_write_index: Option<u32>,
pub end_of_pass_write_index: Option<u32>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(RenderPassTimestampWrites<'_>: Send, Sync);
#[derive(Clone, Debug)]
pub struct RenderPassColorAttachment<'tex> {
pub view: &'tex TextureView,
pub resolve_target: Option<&'tex TextureView>,
pub ops: Operations<Color>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(RenderPassColorAttachment<'_>: Send, Sync);
#[derive(Clone, Debug)]
pub struct RenderPassDepthStencilAttachment<'tex> {
pub view: &'tex TextureView,
pub depth_ops: Option<Operations<f32>>,
pub stencil_ops: Option<Operations<u32>>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment<'_>: Send, Sync);
#[derive(Clone, Debug, Default)]
pub struct RenderPassDescriptor<'a> {
pub label: Label<'a>,
pub color_attachments: &'a [Option<RenderPassColorAttachment<'a>>],
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachment<'a>>,
pub timestamp_writes: Option<RenderPassTimestampWrites<'a>>,
pub occlusion_query_set: Option<&'a QuerySet>,
}
#[cfg(send_sync)]
static_assertions::assert_impl_all!(RenderPassDescriptor<'_>: Send, Sync);