use crate::wgpu::{
backend::WGPUBackend, buffer::Buffer, buffers::BindGroup, material::RenderPipeline,
render_pass::IndexFormat, texture_format::TextureFormat,
};
pub struct RenderBundleEncoderBuilder<'a> {
label: Option<&'a str>,
color_formats: Vec<Option<TextureFormat>>,
depth_stencil_format: Option<TextureFormat>,
depth_read_only: bool,
stencil_read_only: bool,
sample_count: u32,
}
impl<'a> Default for RenderBundleEncoderBuilder<'a> {
fn default() -> Self {
Self {
label: None,
color_formats: Vec::new(),
depth_stencil_format: None,
depth_read_only: false,
stencil_read_only: false,
sample_count: 1,
}
}
}
impl<'a> RenderBundleEncoderBuilder<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn label(mut self, label: impl Into<Option<&'a str>>) -> Self {
self.label = label.into();
self
}
pub fn color_formats(mut self, formats: Vec<Option<TextureFormat>>) -> Self {
self.color_formats = formats;
self
}
pub fn depth_stencil_format(mut self, format: TextureFormat) -> Self {
self.depth_stencil_format = Some(format);
self
}
pub fn depth_read_only(mut self, read_only: bool) -> Self {
self.depth_read_only = read_only;
self
}
pub fn stencil_read_only(mut self, read_only: bool) -> Self {
self.stencil_read_only = read_only;
self
}
pub fn sample_count(mut self, count: u32) -> Self {
self.sample_count = count;
self
}
fn validate(&self) {
if self.color_formats.is_empty() && self.depth_stencil_format.is_none() {
tracing::warn!(
"RenderBundleEncoderBuilder: no color_formats and no depth_stencil_format — \
this bundle has no attachments to execute against; did you forget to call \
.color_formats(...)?"
);
}
}
pub fn build(self, backend: &'a WGPUBackend) -> RenderBundleEncoder<'a> {
self.validate();
let color_formats: Vec<Option<wgpu::TextureFormat>> =
self.color_formats.iter().map(|f| f.map(Into::into)).collect();
let depth_stencil = self.depth_stencil_format.map(|format| wgpu::RenderBundleDepthStencil {
format: format.into(),
depth_read_only: self.depth_read_only,
stencil_read_only: self.stencil_read_only,
});
let raw = backend.device.create_render_bundle_encoder(&wgpu::RenderBundleEncoderDescriptor {
label: self.label,
color_formats: &color_formats,
depth_stencil,
sample_count: self.sample_count,
multiview: None,
});
RenderBundleEncoder::new(raw)
}
}
pub struct RenderBundleEncoder<'a> {
raw: wgpu::RenderBundleEncoder<'a>,
}
impl<'a> RenderBundleEncoder<'a> {
pub(crate) fn new(raw: wgpu::RenderBundleEncoder<'a>) -> Self {
Self { raw }
}
pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
self.raw.set_pipeline(pipeline.raw());
}
pub fn set_bind_group(&mut self, index: u32, bind_group: &'a BindGroup, offsets: &[u32]) {
self.raw.set_bind_group(index, Some(bind_group.raw()), offsets);
}
pub fn set_vertex_buffer(&mut self, slot: u32, buffer: &'a Buffer) {
self.raw.set_vertex_buffer(slot, buffer.raw().slice(..));
}
pub fn set_index_buffer(&mut self, buffer: &'a Buffer, format: IndexFormat) {
self.raw.set_index_buffer(buffer.raw().slice(..), format.into());
}
pub fn draw(&mut self, vertices: std::ops::Range<u32>, instances: std::ops::Range<u32>) {
self.raw.draw(vertices, instances);
}
pub fn draw_indexed(
&mut self,
indices: std::ops::Range<u32>,
base_vertex: i32,
instances: std::ops::Range<u32>,
) {
self.raw.draw_indexed(indices, base_vertex, instances);
}
pub fn finish(self, label: Option<&str>) -> RenderBundle {
RenderBundle(self.raw.finish(&wgpu::RenderBundleDescriptor { label }))
}
}
pub struct RenderBundle(wgpu::RenderBundle);
impl RenderBundle {
pub(crate) fn raw(&self) -> &wgpu::RenderBundle {
&self.0
}
}