use std::cell::Cell;
use std::cmp;
use std::hash::{Hash, Hasher};
use crate::image::format::{
DepthRenderable, DepthStencilRenderable, FloatRenderable, IntegerRenderable, Multisamplable,
Multisample, RenderbufferFormat, StencilRenderable, TextureFormat, UnsignedIntegerRenderable,
};
use crate::image::renderbuffer::Renderbuffer;
use crate::image::texture_2d::LevelMut as Texture2DLevelMut;
use crate::image::texture_2d_array::LevelLayerMut as Texture2DArrayLevelLayerMut;
use crate::image::texture_3d::LevelLayerMut as Texture3DLevelLayerMut;
use crate::image::texture_cube::LevelFaceMut as TextureCubeLevelFaceMut;
use crate::rendering::attachment::AttachmentData;
use crate::rendering::load_op::LoadAction;
use crate::rendering::{
AsAttachment, AsMultisampleAttachment, ColorBufferEncoding, ColorBufferEncodingContext,
DepthAttachment, DepthStencilAttachment, DepthStencilBufferEncoding,
DepthStencilBufferEncodingContext, EncodeColorBuffer, EncodeDepthStencilBuffer,
EncodeMultisampleColorBuffer, EncodeMultisampleDepthStencilBuffer, FloatAttachment,
Framebuffer, GraphicsPipelineTarget, IntegerAttachment, LoadOp, MultisampleFramebuffer,
RenderPass, RenderPassContext, StencilAttachment, StoreOp, UnsignedIntegerAttachment,
};
use crate::runtime::single_threaded::ObjectIdGen;
use crate::runtime::state::{AttachmentSet, DepthStencilAttachmentDescriptor, DrawBuffer};
use crate::task::{ContextId, GpuTask};
pub unsafe trait AttachColorFloat: AsAttachment {}
unsafe impl<'a, T> AttachColorFloat for &'a mut T where T: AttachColorFloat {}
unsafe impl<'a, F> AttachColorFloat for Texture2DLevelMut<'a, F> where
F: TextureFormat + FloatRenderable
{
}
unsafe impl<'a, F> AttachColorFloat for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + FloatRenderable
{
}
unsafe impl<'a, F> AttachColorFloat for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + FloatRenderable
{
}
unsafe impl<'a, F> AttachColorFloat for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + FloatRenderable
{
}
unsafe impl<F> AttachColorFloat for Renderbuffer<F> where
F: RenderbufferFormat + FloatRenderable + 'static
{
}
pub unsafe trait AttachColorInteger: AsAttachment {}
unsafe impl<'a, T> AttachColorInteger for &'a mut T where T: AttachColorInteger {}
unsafe impl<'a, F> AttachColorInteger for Texture2DLevelMut<'a, F> where
F: TextureFormat + IntegerRenderable
{
}
unsafe impl<'a, F> AttachColorInteger for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + IntegerRenderable
{
}
unsafe impl<'a, F> AttachColorInteger for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + IntegerRenderable
{
}
unsafe impl<'a, F> AttachColorInteger for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + IntegerRenderable
{
}
unsafe impl<F> AttachColorInteger for Renderbuffer<F> where
F: RenderbufferFormat + IntegerRenderable + 'static
{
}
pub unsafe trait AttachColorUnsignedInteger: AsAttachment {}
unsafe impl<'a, T> AttachColorUnsignedInteger for &'a mut T where T: AttachColorUnsignedInteger {}
unsafe impl<'a, F> AttachColorUnsignedInteger for Texture2DLevelMut<'a, F> where
F: TextureFormat + UnsignedIntegerRenderable
{
}
unsafe impl<'a, F> AttachColorUnsignedInteger for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + UnsignedIntegerRenderable
{
}
unsafe impl<'a, F> AttachColorUnsignedInteger for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + UnsignedIntegerRenderable
{
}
unsafe impl<'a, F> AttachColorUnsignedInteger for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + UnsignedIntegerRenderable
{
}
unsafe impl<F> AttachColorUnsignedInteger for Renderbuffer<F> where
F: RenderbufferFormat + UnsignedIntegerRenderable + 'static
{
}
pub unsafe trait AttachDepthStencil: AsAttachment {}
unsafe impl<'a, T> AttachDepthStencil for &'a mut T where T: AttachDepthStencil {}
unsafe impl<'a, F> AttachDepthStencil for Texture2DLevelMut<'a, F> where
F: TextureFormat + DepthStencilRenderable
{
}
unsafe impl<'a, F> AttachDepthStencil for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + DepthStencilRenderable
{
}
unsafe impl<'a, F> AttachDepthStencil for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + DepthStencilRenderable
{
}
unsafe impl<'a, F> AttachDepthStencil for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + DepthStencilRenderable
{
}
unsafe impl<F> AttachDepthStencil for Renderbuffer<F> where
F: RenderbufferFormat + DepthStencilRenderable + 'static
{
}
pub unsafe trait AttachDepth: AsAttachment {}
unsafe impl<'a, T> AttachDepth for &'a mut T where T: AttachDepth {}
unsafe impl<'a, F> AttachDepth for Texture2DLevelMut<'a, F> where F: TextureFormat + DepthRenderable {}
unsafe impl<'a, F> AttachDepth for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + DepthRenderable
{
}
unsafe impl<'a, F> AttachDepth for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + DepthRenderable
{
}
unsafe impl<'a, F> AttachDepth for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + DepthRenderable
{
}
unsafe impl<F> AttachDepth for Renderbuffer<F> where
F: RenderbufferFormat + DepthRenderable + 'static
{
}
pub unsafe trait AttachStencil: AsAttachment {}
unsafe impl<'a, T> AttachStencil for &'a mut T where T: AttachStencil {}
unsafe impl<'a, F> AttachStencil for Texture2DLevelMut<'a, F> where
F: TextureFormat + StencilRenderable
{
}
unsafe impl<'a, F> AttachStencil for Texture2DArrayLevelLayerMut<'a, F> where
F: TextureFormat + StencilRenderable
{
}
unsafe impl<'a, F> AttachStencil for Texture3DLevelLayerMut<'a, F> where
F: TextureFormat + StencilRenderable
{
}
unsafe impl<'a, F> AttachStencil for TextureCubeLevelFaceMut<'a, F> where
F: TextureFormat + StencilRenderable
{
}
unsafe impl<F> AttachStencil for Renderbuffer<F> where
F: RenderbufferFormat + StencilRenderable + 'static
{
}
pub struct RenderTargetDescriptor<C, Ds> {
pub(crate) color_attachments: C,
pub(crate) depth_stencil_attachment: Ds,
pub(crate) color_attachment_count: u8,
pub(crate) context_id: RenderTargetContextId,
}
impl RenderTargetDescriptor<(), ()> {
pub fn new() -> Self {
RenderTargetDescriptor {
color_attachments: (),
depth_stencil_attachment: (),
color_attachment_count: 0,
context_id: RenderTargetContextId::new(),
}
}
}
impl<C> RenderTargetDescriptor<C, ()> {
pub fn attach_depth_stencil<Ds>(
self,
mut image: Ds,
load_op: LoadOp<(f32, i32)>,
store_op: StoreOp,
) -> RenderTargetDescriptor<C, DepthStencilAttachment<Ds>>
where
Ds: AttachDepthStencil,
{
let context_id = image.as_attachment().into_data().context_id;
RenderTargetDescriptor {
color_attachments: self.color_attachments,
depth_stencil_attachment: DepthStencilAttachment {
image,
load_op,
store_op,
},
color_attachment_count: self.color_attachment_count,
context_id: self.context_id.record("depth-stencil", context_id),
}
}
pub fn attach_depth<Ds>(
self,
mut image: Ds,
load_op: LoadOp<f32>,
store_op: StoreOp,
) -> RenderTargetDescriptor<C, DepthAttachment<Ds>>
where
Ds: AttachDepth,
{
let context_id = image.as_attachment().into_data().context_id;
RenderTargetDescriptor {
color_attachments: self.color_attachments,
depth_stencil_attachment: DepthAttachment {
image,
load_op,
store_op,
},
color_attachment_count: self.color_attachment_count,
context_id: self.context_id.record("depth-stencil", context_id),
}
}
pub fn attach_stencil<Ds>(
self,
mut image: Ds,
load_op: LoadOp<i32>,
store_op: StoreOp,
) -> RenderTargetDescriptor<C, StencilAttachment<Ds>>
where
Ds: AttachStencil,
{
let context_id = image.as_attachment().into_data().context_id;
RenderTargetDescriptor {
color_attachments: self.color_attachments,
depth_stencil_attachment: StencilAttachment {
image,
load_op,
store_op,
},
color_attachment_count: self.color_attachment_count,
context_id: self.context_id.record("depth-stencil", context_id),
}
}
}
macro_rules! impl_attach_render_target_color {
($count:tt, $label:tt, $($C:ident),*) => {
impl<$($C,)* Ds> RenderTargetDescriptor<($($C,)*), Ds> {
pub fn attach_color_float<C>(self, mut image: C, load_op: LoadOp<[f32; 4]>, store_op: StoreOp) -> RenderTargetDescriptor<($($C,)* FloatAttachment<C>,), Ds> where C: AttachColorFloat {
let context_id = image.as_attachment().into_data().context_id;
#[allow(non_snake_case)]
let ($($C,)*) = self.color_attachments;
RenderTargetDescriptor {
color_attachments: ($($C,)* FloatAttachment {
image,
load_op,
store_op
},),
depth_stencil_attachment: self.depth_stencil_attachment,
color_attachment_count: $count,
context_id: self.context_id.record($label, context_id)
}
}
pub fn attach_color_integer<C>(self, mut image: C, load_op: LoadOp<[i32; 4]>, store_op: StoreOp) -> RenderTargetDescriptor<($($C,)* IntegerAttachment<C>,), Ds> where C: AttachColorInteger {
let context_id = image.as_attachment().into_data().context_id;
#[allow(non_snake_case)]
let ($($C,)*) = self.color_attachments;
RenderTargetDescriptor {
color_attachments: ($($C,)* IntegerAttachment {
image,
load_op,
store_op
},),
depth_stencil_attachment: self.depth_stencil_attachment,
color_attachment_count: $count,
context_id: self.context_id.record($label, context_id)
}
}
pub fn attach_color_unsigned_integer<C>(self, mut image: C, load_op: LoadOp<[u32; 4]>, store_op: StoreOp) -> RenderTargetDescriptor<($($C,)* UnsignedIntegerAttachment<C>,), Ds> where C: AttachColorUnsignedInteger {
let context_id = image.as_attachment().into_data().context_id;
#[allow(non_snake_case)]
let ($($C,)*) = self.color_attachments;
RenderTargetDescriptor {
color_attachments: ($($C,)* UnsignedIntegerAttachment {
image,
load_op,
store_op
},),
depth_stencil_attachment: self.depth_stencil_attachment,
color_attachment_count: $count,
context_id: self.context_id.record($label, context_id)
}
}
}
}
}
impl_attach_render_target_color!(1, "color 0",);
impl_attach_render_target_color!(2, "color 1", C0);
impl_attach_render_target_color!(3, "color 2", C0, C1);
impl_attach_render_target_color!(4, "color 3", C0, C1, C2);
impl_attach_render_target_color!(5, "color 4", C0, C1, C2, C3);
impl_attach_render_target_color!(6, "color 5", C0, C1, C2, C3, C4);
impl_attach_render_target_color!(7, "color 6", C0, C1, C2, C3, C4, C5);
impl_attach_render_target_color!(8, "color 7", C0, C1, C2, C3, C4, C5, C6);
impl_attach_render_target_color!(9, "color 8", C0, C1, C2, C3, C4, C5, C6, C7);
impl_attach_render_target_color!(10, "color 9", C0, C1, C2, C3, C4, C5, C6, C7, C8);
impl_attach_render_target_color!(11, "color 10", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9);
impl_attach_render_target_color!(12, "color 11", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10);
impl_attach_render_target_color!(13, "color 12", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11);
impl_attach_render_target_color!(
14, "color 13", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12
);
impl_attach_render_target_color!(
15, "color 14", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13
);
impl_attach_render_target_color!(
16, "color 15", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14
);
pub unsafe trait AttachMultisampleColorFloat: AsMultisampleAttachment {}
unsafe impl<'a, T> AttachMultisampleColorFloat for &'a mut T where T: AttachMultisampleColorFloat {}
unsafe impl<F> AttachMultisampleColorFloat for Renderbuffer<Multisample<F>> where
F: RenderbufferFormat + Multisamplable + FloatRenderable + 'static
{
}
pub unsafe trait AttachMultisampleDepthStencil: AsMultisampleAttachment {}
unsafe impl<'a, T> AttachMultisampleDepthStencil for &'a mut T where T: AttachMultisampleDepthStencil
{}
unsafe impl<F> AttachMultisampleDepthStencil for Renderbuffer<Multisample<F>> where
F: RenderbufferFormat + Multisamplable + DepthStencilRenderable + 'static
{
}
pub unsafe trait AttachMultisampleDepth: AsMultisampleAttachment {}
unsafe impl<'a, T> AttachMultisampleDepth for &'a mut T where T: AttachMultisampleDepth {}
unsafe impl<F> AttachMultisampleDepth for Renderbuffer<Multisample<F>> where
F: RenderbufferFormat + Multisamplable + DepthRenderable + 'static
{
}
pub struct MultisampleRenderTargetDescriptor<C, Ds> {
pub(crate) color_attachments: C,
pub(crate) depth_stencil_attachment: Ds,
pub(crate) samples: u8,
pub(crate) color_attachment_count: u8,
pub(crate) context_id: RenderTargetContextId,
}
impl MultisampleRenderTargetDescriptor<(), ()> {
pub fn new(samples: u8) -> Self {
MultisampleRenderTargetDescriptor {
color_attachments: (),
depth_stencil_attachment: (),
samples,
color_attachment_count: 0,
context_id: RenderTargetContextId::new(),
}
}
}
impl<C> MultisampleRenderTargetDescriptor<C, ()> {
pub fn attach_depth_stencil<Ds>(
self,
mut image: Ds,
load_op: LoadOp<(f32, i32)>,
store_op: StoreOp,
) -> MultisampleRenderTargetDescriptor<C, DepthStencilAttachment<Ds>>
where
Ds: AttachMultisampleDepthStencil,
{
let attachment = image.as_multisample_attachment();
let image_samples = attachment.samples();
let context_id = attachment.into_data().context_id;
if image_samples != self.samples {
panic!(
"Descriptor expects {} samples, but image uses {} samples",
self.samples, image_samples
);
}
MultisampleRenderTargetDescriptor {
color_attachments: self.color_attachments,
depth_stencil_attachment: DepthStencilAttachment {
image,
load_op,
store_op,
},
samples: self.samples,
color_attachment_count: self.color_attachment_count,
context_id: self.context_id.record("depth-stencil", context_id),
}
}
pub fn attach_depth<Ds>(
self,
mut image: Ds,
load_op: LoadOp<f32>,
store_op: StoreOp,
) -> MultisampleRenderTargetDescriptor<C, DepthAttachment<Ds>>
where
Ds: AttachMultisampleDepth,
{
let attachment = image.as_multisample_attachment();
let image_samples = attachment.samples();
let context_id = attachment.into_data().context_id;
if image_samples != self.samples {
panic!(
"Descriptor expects {} samples, but image uses {} samples",
self.samples, image_samples
);
}
MultisampleRenderTargetDescriptor {
color_attachments: self.color_attachments,
depth_stencil_attachment: DepthAttachment {
image,
load_op,
store_op,
},
samples: self.samples,
color_attachment_count: self.color_attachment_count,
context_id: self.context_id.record("depth-stencil", context_id),
}
}
}
macro_rules! impl_attach_multisample_render_target_color {
($count:tt, $label:tt, $($C:ident),*) => {
impl<$($C,)* Ds> MultisampleRenderTargetDescriptor<($($C,)*), Ds> {
pub fn attach_color_float<C>(
self,
mut image: C,
load_op: LoadOp<[f32; 4]>,
store_op: StoreOp
) -> MultisampleRenderTargetDescriptor<($($C,)* FloatAttachment<C>,), Ds>
where C: AttachMultisampleColorFloat
{
let attachment = image.as_multisample_attachment();
let image_samples = attachment.samples();
let context_id = attachment.into_data().context_id;
if image_samples != self.samples {
panic!(
"Descriptor expects {} samples, but image uses {} samples",
self.samples,
image_samples
);
}
#[allow(non_snake_case)]
let ($($C,)*) = self.color_attachments;
MultisampleRenderTargetDescriptor {
color_attachments: ($($C,)* FloatAttachment {
image,
load_op,
store_op
},),
depth_stencil_attachment: self.depth_stencil_attachment,
samples: self.samples,
color_attachment_count: $count,
context_id: self.context_id.record($label, context_id)
}
}
}
}
}
impl_attach_multisample_render_target_color!(1, "color 0",);
impl_attach_multisample_render_target_color!(2, "color 1", C0);
impl_attach_multisample_render_target_color!(3, "color 2", C0, C1);
impl_attach_multisample_render_target_color!(4, "color 3", C0, C1, C2);
impl_attach_multisample_render_target_color!(5, "color 4", C0, C1, C2, C3);
impl_attach_multisample_render_target_color!(6, "color 5", C0, C1, C2, C3, C4);
impl_attach_multisample_render_target_color!(7, "color 6", C0, C1, C2, C3, C4, C5);
impl_attach_multisample_render_target_color!(8, "color 7", C0, C1, C2, C3, C4, C5, C6);
impl_attach_multisample_render_target_color!(9, "color 8", C0, C1, C2, C3, C4, C5, C6, C7);
impl_attach_multisample_render_target_color!(10, "color 9", C0, C1, C2, C3, C4, C5, C6, C7, C8);
impl_attach_multisample_render_target_color!(
11, "color 10", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9
);
impl_attach_multisample_render_target_color!(
12, "color 11", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10
);
impl_attach_multisample_render_target_color!(
13, "color 12", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11
);
impl_attach_multisample_render_target_color!(
14, "color 13", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12
);
impl_attach_multisample_render_target_color!(
15, "color 14", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13
);
impl_attach_multisample_render_target_color!(
16, "color 15", C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14
);
pub struct RenderTarget<C, Ds> {
pub(crate) color_attachments: C,
pub(crate) depth_stencil_attachment: Ds,
pub(crate) object_id: u64,
pub(crate) context_id: u64,
pub(crate) render_pass_id_gen: ObjectIdGen,
}
impl<C, Ds> PartialEq for RenderTarget<C, Ds> {
fn eq(&self, other: &Self) -> bool {
self.object_id == other.object_id
}
}
impl<C, Ds> Hash for RenderTarget<C, Ds> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.object_id.hash(state);
}
}
pub struct MultisampleRenderTarget<C, Ds> {
pub(crate) color_attachments: C,
pub(crate) depth_stencil_attachment: Ds,
pub(crate) samples: u8,
pub(crate) object_id: u64,
pub(crate) context_id: u64,
pub(crate) render_pass_id_gen: ObjectIdGen,
}
impl<C, Ds> PartialEq for MultisampleRenderTarget<C, Ds> {
fn eq(&self, other: &Self) -> bool {
self.object_id == other.object_id
}
}
impl<C, Ds> Hash for MultisampleRenderTarget<C, Ds> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.object_id.hash(state);
}
}
macro_rules! impl_create_render_pass {
($C0:ident $(,$C:ident)*) => {
#[allow(unused_parens)]
impl<$C0 $(,$C)*> RenderTarget<($C0, $($C,)*), ()>
where
$C0: EncodeColorBuffer, $($C: EncodeColorBuffer,)*
{
#[allow(non_snake_case, unused_mut, unused_parens)]
pub fn create_render_pass<F, T>(&mut self, f: F) -> RenderPass<T>
where
F: FnOnce(&Framebuffer<($C0::Buffer, $($C::Buffer,)*), ()>) -> T,
T: GpuTask<RenderPassContext>
{
let id = self.render_pass_id_gen.next();
let mut render_target = CustomRenderTargetData {
load_ops: [LoadAction::Load; 17],
store_ops: [StoreOp::Store; 17],
color_count: 0,
color_attachments: [
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
depth_stencil_attachment: DepthStencilAttachmentDescriptor::None,
};
let ($C0, $($C,)*) = &mut self.color_attachments;
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: 0,
};
let $C0 = $C0.encode_color_buffer(&mut context);
let mut width = $C0.image.width;
let mut height = $C0.image.height;
let $C0 = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C0;
render_target.load_ops[0] = load_action;
render_target.store_ops[0] = store_op;
render_target.color_attachments[0] = Some(image);
buffer
};
let mut color_count = 1;
$(
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: color_count as i32,
};
let $C = $C.encode_color_buffer(&mut context);
width = cmp::min(width, $C.image.width);
height = cmp::min(height, $C.image.height);
let $C = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C;
render_target.load_ops[color_count] = load_action;
render_target.store_ops[color_count] = store_op;
render_target.color_attachments[color_count] = Some(image);
buffer
};
color_count += 1;
)*
render_target.color_count = color_count;
let task = f(&Framebuffer {
color: ($C0, $($C,)*),
depth_stencil: (),
pipeline_target: GraphicsPipelineTarget {
dimensions: Some((width, height)),
context_id: self.context_id,
render_pass_id: id,
last_pipeline_task_id: Cell::new(0),
}
});
if let ContextId::Id(render_pass_id) = task.context_id() {
if render_pass_id != id {
panic!("The render pass task belongs to a different render pass.")
}
}
RenderPass {
id,
context_id: self.context_id,
render_target: RenderTargetData::Custom(render_target),
task
}
}
}
#[allow(unused_parens)]
impl<$C0 $(,$C)*> MultisampleRenderTarget<($C0, $($C,)*), ()>
where
$C0: EncodeMultisampleColorBuffer $(,$C: EncodeMultisampleColorBuffer)*
{
#[allow(non_snake_case, unused_mut, unused_parens)]
pub fn create_render_pass<F, T>(&mut self, f: F) -> RenderPass<T>
where
F: FnOnce(&MultisampleFramebuffer<($C0::Buffer, $($C::Buffer,)*), ()>) -> T,
T: GpuTask<RenderPassContext>
{
let id = self.render_pass_id_gen.next();
let mut render_target = CustomRenderTargetData {
load_ops: [LoadAction::Load; 17],
store_ops: [StoreOp::Store; 17],
color_count: 0,
color_attachments: [
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
depth_stencil_attachment: DepthStencilAttachmentDescriptor::None,
};
let ($C0, $($C,)*) = &mut self.color_attachments;
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: 0,
};
let $C0 = $C0.encode_multisample_color_buffer(&mut context);
let mut width = $C0.image.width;
let mut height = $C0.image.height;
let $C0 = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C0;
render_target.load_ops[0] = load_action;
render_target.store_ops[0] = store_op;
render_target.color_attachments[0] = Some(image);
buffer
};
let mut color_count = 1;
$(
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: color_count as i32,
};
let $C = $C.encode_multisample_color_buffer(&mut context);
width = cmp::min(width, $C.image.width);
height = cmp::min(height, $C.image.height);
let $C = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C;
render_target.load_ops[color_count] = load_action;
render_target.store_ops[color_count] = store_op;
render_target.color_attachments[color_count] = Some(image);
buffer
};
color_count += 1;
)*
render_target.color_count = color_count;
let task = f(&MultisampleFramebuffer {
color: ($C0, $($C,)*),
depth_stencil: (),
samples: self.samples,
pipeline_target: GraphicsPipelineTarget {
dimensions: Some((width, height)),
context_id: self.context_id,
render_pass_id: id,
last_pipeline_task_id: Cell::new(0),
}
});
if let ContextId::Id(render_pass_id) = task.context_id() {
if render_pass_id != id {
panic!("The render pass task belongs to a different render pass.")
}
}
RenderPass {
id,
context_id: self.context_id,
render_target: RenderTargetData::Custom(render_target),
task
}
}
}
}
}
impl_create_render_pass!(C0);
impl_create_render_pass!(C0, C1);
impl_create_render_pass!(C0, C1, C2);
impl_create_render_pass!(C0, C1, C2, C3);
impl_create_render_pass!(C0, C1, C2, C3, C4);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14);
impl_create_render_pass!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15);
macro_rules! impl_create_render_pass_depth_stencil {
($($C:ident),*) => {
#[allow(unused_parens)]
impl<$($C,)* Ds> RenderTarget<($($C,)*), Ds>
where
$($C: EncodeColorBuffer,)*
Ds: EncodeDepthStencilBuffer
{
#[allow(non_snake_case, unused_parens)]
pub fn create_render_pass<F, T>(&mut self, f: F) -> RenderPass<T>
where
F: FnOnce(&Framebuffer<($($C::Buffer,)*), Ds::Buffer>) -> T,
T: GpuTask<RenderPassContext>
{
let id = self.render_pass_id_gen.next();
let mut context = DepthStencilBufferEncodingContext {
render_pass_id: id,
};
let DepthStencilBufferEncoding {
load_action,
store_op,
depth_stencil_type,
image,
buffer,
..
} = self.depth_stencil_attachment.encode_depth_stencil_buffer(&mut context);
#[allow(unused_mut)]
let mut width = image.width;
#[allow(unused_mut)]
let mut height = image.height;
let mut render_target = CustomRenderTargetData {
load_ops: [LoadAction::Load; 17],
store_ops: [StoreOp::Store; 17],
color_count: 0,
color_attachments: [
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
depth_stencil_attachment: depth_stencil_type.descriptor(image),
};
render_target.load_ops[16] = load_action;
render_target.store_ops[16] = store_op;
let ($($C,)*) = &mut self.color_attachments;
#[allow(unused_mut)]
let mut color_count = 0;
$(
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: color_count as i32,
};
let $C = $C.encode_color_buffer(&mut context);
width = cmp::min(width, $C.image.width);
height = cmp::min(height, $C.image.height);
let $C = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C;
render_target.load_ops[color_count] = load_action;
render_target.store_ops[color_count] = store_op;
render_target.color_attachments[color_count] = Some(image);
buffer
};
color_count += 1;
)*
render_target.color_count = color_count;
let task = f(&Framebuffer {
color: ($($C,)*),
depth_stencil: buffer,
pipeline_target: GraphicsPipelineTarget {
dimensions: Some((width, height)),
context_id: self.context_id,
render_pass_id: id,
last_pipeline_task_id: Cell::new(0),
}
});
if let ContextId::Id(render_pass_id) = task.context_id() {
if render_pass_id != id {
panic!("The render pass task belongs to a different render pass.")
}
}
RenderPass {
id,
context_id: self.context_id,
render_target: RenderTargetData::Custom(render_target),
task
}
}
}
#[allow(unused_parens)]
impl<$($C,)* Ds> MultisampleRenderTarget<($($C,)*), Ds>
where
$($C: EncodeMultisampleColorBuffer,)*
Ds: EncodeMultisampleDepthStencilBuffer
{
#[allow(non_snake_case, unused_parens)]
pub fn create_render_pass<F, T>(&mut self, f: F) -> RenderPass<T>
where
F: FnOnce(&MultisampleFramebuffer<($($C::Buffer,)*), Ds::Buffer>) -> T,
T: GpuTask<RenderPassContext>
{
let id = self.render_pass_id_gen.next();
let mut context = DepthStencilBufferEncodingContext {
render_pass_id: id,
};
let DepthStencilBufferEncoding {
load_action,
store_op,
depth_stencil_type,
image,
buffer,
..
} = self.depth_stencil_attachment.encode_multisample_depth_stencil_buffer(&mut context);
#[allow(unused_mut)]
let mut width = image.width;
#[allow(unused_mut)]
let mut height = image.height;
let mut render_target = CustomRenderTargetData {
load_ops: [LoadAction::Load; 17],
store_ops: [StoreOp::Store; 17],
color_count: 0,
color_attachments: [
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
depth_stencil_attachment: depth_stencil_type.descriptor(image),
};
render_target.load_ops[16] = load_action;
render_target.store_ops[16] = store_op;
let ($($C,)*) = &mut self.color_attachments;
#[allow(unused_mut)]
let mut color_count = 0;
$(
let mut context = ColorBufferEncodingContext {
render_pass_id: id,
buffer_index: color_count as i32,
};
let $C = $C.encode_multisample_color_buffer(&mut context);
width = cmp::min(width, $C.image.width);
height = cmp::min(height, $C.image.height);
let $C = {
let ColorBufferEncoding {
load_action,
store_op,
image,
buffer,
..
} = $C;
render_target.load_ops[color_count] = load_action;
render_target.store_ops[color_count] = store_op;
render_target.color_attachments[color_count] = Some(image);
buffer
};
color_count += 1;
)*
render_target.color_count = color_count;
let task = f(&MultisampleFramebuffer {
color: ($($C,)*),
depth_stencil: buffer,
samples: self.samples,
pipeline_target : GraphicsPipelineTarget {
dimensions: Some((width, height)),
context_id: self.context_id,
render_pass_id: id,
last_pipeline_task_id: Cell::new(0),
}
});
if let ContextId::Id(render_pass_id) = task.context_id() {
if render_pass_id != id {
panic!("The render pass task belongs to a different render pass.")
}
}
RenderPass {
id,
context_id: self.context_id,
render_target: RenderTargetData::Custom(render_target),
task
}
}
}
}
}
impl_create_render_pass_depth_stencil!();
impl_create_render_pass_depth_stencil!(C0);
impl_create_render_pass_depth_stencil!(C0, C1);
impl_create_render_pass_depth_stencil!(C0, C1, C2);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12);
impl_create_render_pass_depth_stencil!(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13);
impl_create_render_pass_depth_stencil!(
C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14
);
impl_create_render_pass_depth_stencil!(
C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15
);
pub(crate) enum RenderTargetContextId {
Any,
Single(&'static str, u64),
Mixed {
first: (&'static str, u64),
second: &'static str,
},
}
impl RenderTargetContextId {
pub(crate) fn new() -> Self {
RenderTargetContextId::Any
}
pub(crate) fn record(self, label: &'static str, context_id: u64) -> Self {
match self {
RenderTargetContextId::Any => RenderTargetContextId::Single(label, context_id),
RenderTargetContextId::Single(first_label, first_id) => {
if context_id != first_id {
RenderTargetContextId::Mixed {
first: (first_label, first_id),
second: label,
}
} else {
self
}
}
_ => self,
}
}
pub(crate) fn verify(&self, context_id: u64) {
match self {
RenderTargetContextId::Single(label, id) => {
if context_id != *id {
panic!("The {} attachment belongs to a different context.", label)
}
}
RenderTargetContextId::Mixed {
first: (first_label, first_id),
second: second_label,
} => {
if context_id != *first_id {
panic!(
"The {} attachment belongs to a different context.",
first_label
)
} else {
panic!(
"The {} attachment belongs to a different context.",
second_label
)
}
}
_ => (),
}
}
}
#[derive(Clone)]
pub(crate) enum RenderTargetData {
Default,
Custom(CustomRenderTargetData),
}
#[derive(Clone)]
pub(crate) struct CustomRenderTargetData {
pub(crate) load_ops: [LoadAction; 17],
pub(crate) store_ops: [StoreOp; 17],
pub(crate) color_count: usize,
pub(crate) color_attachments: [Option<AttachmentData>; 16],
pub(crate) depth_stencil_attachment: DepthStencilAttachmentDescriptor,
}
impl CustomRenderTargetData {
pub(crate) fn draw_buffers(&self) -> &[DrawBuffer] {
const DRAW_BUFFERS_SEQUENTIAL: [DrawBuffer; 16] = [
DrawBuffer::Color0,
DrawBuffer::Color1,
DrawBuffer::Color2,
DrawBuffer::Color3,
DrawBuffer::Color4,
DrawBuffer::Color5,
DrawBuffer::Color6,
DrawBuffer::Color7,
DrawBuffer::Color8,
DrawBuffer::Color9,
DrawBuffer::Color10,
DrawBuffer::Color11,
DrawBuffer::Color12,
DrawBuffer::Color13,
DrawBuffer::Color14,
DrawBuffer::Color15,
];
&DRAW_BUFFERS_SEQUENTIAL[0..self.color_count]
}
}
impl Hash for CustomRenderTargetData {
fn hash<H>(&self, hasher: &mut H)
where
H: Hasher,
{
self.color_attachments().hash(hasher);
self.depth_stencil_attachment().hash(hasher);
}
}
impl AttachmentSet for CustomRenderTargetData {
fn color_attachments(&self) -> &[Option<AttachmentData>] {
&self.color_attachments[0..self.color_count]
}
fn depth_stencil_attachment(&self) -> &DepthStencilAttachmentDescriptor {
&self.depth_stencil_attachment
}
}