dxwr 0.4.3

Direct3D12 and DXGI wrapper library
Documentation
use super::*;
use std::mem::ManuallyDrop;
use windows::Win32::Graphics::Direct3D12::*;

pub trait ResourceBarrier {
    fn as_raw(&self) -> &D3D12_RESOURCE_BARRIER;
}

#[derive(Clone)]
pub struct TransitionBarrier(D3D12_RESOURCE_BARRIER);

impl TransitionBarrier {
    #[inline]
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self(D3D12_RESOURCE_BARRIER {
            Type: D3D12_RESOURCE_BARRIER_TYPE_TRANSITION,
            Anonymous: D3D12_RESOURCE_BARRIER_0 {
                Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER::default()),
            },
            ..Default::default()
        })
    }

    #[inline]
    pub fn resource(mut self, resource: &Resource) -> Self {
        unsafe {
            let barrier = D3D12_RESOURCE_BARRIER {
                Type: self.0.Type,
                Flags: self.0.Flags,
                Anonymous: D3D12_RESOURCE_BARRIER_0 {
                    Transition: ManuallyDrop::new(D3D12_RESOURCE_TRANSITION_BARRIER {
                        pResource: ManuallyDrop::new(Some(resource.handle().clone())),
                        Subresource: self.0.Anonymous.Transition.Subresource,
                        StateBefore: self.0.Anonymous.Transition.StateBefore,
                        StateAfter: self.0.Anonymous.Transition.StateAfter,
                    }),
                },
            };
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Transition).pResource);
            ManuallyDrop::drop(&mut self.0.Anonymous.Transition);
            Self(barrier)
        }
    }

    #[inline]
    pub fn subresource(mut self, subresource: u32) -> Self {
        unsafe {
            (*self.0.Anonymous.Transition).Subresource = subresource;
            self
        }
    }

    #[inline]
    pub fn state_before(mut self, state: D3D12_RESOURCE_STATES) -> Self {
        unsafe {
            (*self.0.Anonymous.Transition).StateBefore = state;
            self
        }
    }

    #[inline]
    pub fn state_after(mut self, state: D3D12_RESOURCE_STATES) -> Self {
        unsafe {
            (*self.0.Anonymous.Transition).StateAfter = state;
            self
        }
    }

    #[inline]
    pub fn flags(mut self, flags: D3D12_RESOURCE_BARRIER_FLAGS) -> Self {
        self.0.Flags = flags;
        self
    }
}

impl Drop for TransitionBarrier {
    fn drop(&mut self) {
        unsafe {
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Transition).pResource);
            ManuallyDrop::drop(&mut self.0.Anonymous.Transition);
        }
    }
}

impl ResourceBarrier for TransitionBarrier {
    fn as_raw(&self) -> &D3D12_RESOURCE_BARRIER {
        &self.0
    }
}

impl std::fmt::Debug for TransitionBarrier {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let b = &self.0;
        unsafe {
            write!(
                f,
                "TransitionBarrier {{ resource: {:?}, subresource: {:?}, state_before: {:?}, state_after: {:?} }}",
                b.Anonymous.Transition.pResource,
                b.Anonymous.Transition.Subresource,
                b.Anonymous.Transition.StateBefore,
                b.Anonymous.Transition.StateAfter
            )
        }
    }
}

#[derive(Clone)]
pub struct AliasingBarrier(D3D12_RESOURCE_BARRIER);

impl AliasingBarrier {
    #[inline]
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self(D3D12_RESOURCE_BARRIER {
            Type: D3D12_RESOURCE_BARRIER_TYPE_ALIASING,
            Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
            Anonymous: D3D12_RESOURCE_BARRIER_0 {
                Aliasing: ManuallyDrop::new(D3D12_RESOURCE_ALIASING_BARRIER::default()),
            },
        })
    }

    #[inline]
    pub fn resource_before(mut self, resource: &Resource) -> Self {
        unsafe {
            let barrier = D3D12_RESOURCE_BARRIER {
                Type: self.0.Type,
                Flags: self.0.Flags,
                Anonymous: D3D12_RESOURCE_BARRIER_0 {
                    Aliasing: ManuallyDrop::new(D3D12_RESOURCE_ALIASING_BARRIER {
                        pResourceBefore: ManuallyDrop::new(Some(resource.handle().clone())),
                        pResourceAfter: ManuallyDrop::new(ManuallyDrop::take(
                            &mut (*self.0.Anonymous.Aliasing).pResourceAfter,
                        )),
                    }),
                },
            };
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Aliasing).pResourceBefore);
            ManuallyDrop::drop(&mut self.0.Anonymous.Aliasing);
            Self(barrier)
        }
    }

    #[inline]
    pub fn resource_after(mut self, resource: &Resource) -> Self {
        unsafe {
            let barrier = D3D12_RESOURCE_BARRIER {
                Type: self.0.Type,
                Flags: self.0.Flags,
                Anonymous: D3D12_RESOURCE_BARRIER_0 {
                    Aliasing: ManuallyDrop::new(D3D12_RESOURCE_ALIASING_BARRIER {
                        pResourceBefore: ManuallyDrop::new(ManuallyDrop::take(
                            &mut (*self.0.Anonymous.Aliasing).pResourceBefore,
                        )),
                        pResourceAfter: ManuallyDrop::new(Some(resource.handle().clone())),
                    }),
                },
            };
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Aliasing).pResourceAfter);
            ManuallyDrop::drop(&mut self.0.Anonymous.Aliasing);
            Self(barrier)
        }
    }

    #[inline]
    pub fn flags(mut self, flags: D3D12_RESOURCE_BARRIER_FLAGS) -> Self {
        self.0.Flags = flags;
        self
    }
}

impl Drop for AliasingBarrier {
    fn drop(&mut self) {
        unsafe {
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Aliasing).pResourceBefore);
            ManuallyDrop::drop(&mut (*self.0.Anonymous.Aliasing).pResourceAfter);
            ManuallyDrop::drop(&mut self.0.Anonymous.Aliasing);
        }
    }
}

impl ResourceBarrier for AliasingBarrier {
    fn as_raw(&self) -> &D3D12_RESOURCE_BARRIER {
        &self.0
    }
}

impl std::fmt::Debug for AliasingBarrier {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let b = &self.0;
        unsafe {
            write!(
                f,
                "AliasingBarrier {{ resource_before: {:?}, resource_after: {:?} }}",
                b.Anonymous.Aliasing.pResourceBefore, b.Anonymous.Aliasing.pResourceAfter
            )
        }
    }
}

#[derive(Clone)]
pub struct UavBarrier(D3D12_RESOURCE_BARRIER);

impl UavBarrier {
    #[inline]
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self(D3D12_RESOURCE_BARRIER {
            Type: D3D12_RESOURCE_BARRIER_TYPE_UAV,
            Flags: D3D12_RESOURCE_BARRIER_FLAG_NONE,
            Anonymous: D3D12_RESOURCE_BARRIER_0 {
                UAV: ManuallyDrop::new(D3D12_RESOURCE_UAV_BARRIER::default()),
            },
        })
    }

    #[inline]
    pub fn resource(mut self, resource: &Resource) -> Self {
        let barrier = D3D12_RESOURCE_BARRIER {
            Type: self.0.Type,
            Flags: self.0.Flags,
            Anonymous: D3D12_RESOURCE_BARRIER_0 {
                UAV: ManuallyDrop::new(D3D12_RESOURCE_UAV_BARRIER {
                    pResource: ManuallyDrop::new(Some(resource.handle().clone())),
                }),
            },
        };
        unsafe {
            ManuallyDrop::drop(&mut (*self.0.Anonymous.UAV).pResource);
            ManuallyDrop::drop(&mut self.0.Anonymous.UAV);
        }
        Self(barrier)
    }

    #[inline]
    pub fn flags(mut self, flags: D3D12_RESOURCE_BARRIER_FLAGS) -> Self {
        self.0.Flags = flags;
        self
    }
}

impl Drop for UavBarrier {
    fn drop(&mut self) {
        unsafe {
            ManuallyDrop::drop(&mut (*self.0.Anonymous.UAV).pResource);
            ManuallyDrop::drop(&mut self.0.Anonymous.UAV);
        }
    }
}

impl ResourceBarrier for UavBarrier {
    fn as_raw(&self) -> &D3D12_RESOURCE_BARRIER {
        &self.0
    }
}

impl std::fmt::Debug for UavBarrier {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let b = &self.0;
        unsafe {
            write!(
                f,
                "UavBarrier {{ resource: {:?} }}",
                b.Anonymous.UAV.pResource,
            )
        }
    }
}