mod encoder;
mod level;
mod reset;
mod state;
mod submit;
mod usage;
use {
crate::{
capability::{Capability, Supports},
family::FamilyId,
},
gfx_hal::Backend,
};
pub use self::{encoder::*, level::*, reset::*, state::*, submit::*, usage::*};
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct CommandBuffer<B: Backend, C, S, L = PrimaryLevel, R = NoIndividualReset> {
#[derivative(Debug = "ignore")]
raw: std::ptr::NonNull<B::CommandBuffer>,
capability: C,
state: S,
level: L,
reset: R,
family: FamilyId,
relevant: relevant::Relevant,
}
family_owned!(CommandBuffer<B, C, S, L, R>);
unsafe impl<B, C, S, L, R> Send for CommandBuffer<B, C, S, L, R>
where
B: Backend,
B::CommandBuffer: Send,
C: Send,
S: Send,
L: Send,
R: Send,
FamilyId: Send,
relevant::Relevant: Send,
{
}
unsafe impl<B, C, S, L, R> Sync for CommandBuffer<B, C, S, L, R>
where
B: Backend,
B::CommandBuffer: Sync,
C: Sync,
S: Sync,
L: Sync,
R: Sync,
FamilyId: Sync,
relevant::Relevant: Sync,
{
}
impl<B, C, S, L, R> CommandBuffer<B, C, S, L, R>
where
B: Backend,
{
pub(crate) unsafe fn from_raw(
raw: B::CommandBuffer,
capability: C,
state: S,
level: L,
reset: R,
family: FamilyId,
) -> Self {
CommandBuffer {
raw: std::ptr::NonNull::new_unchecked(Box::into_raw(Box::new(raw))),
capability,
state,
level,
reset,
family,
relevant: relevant::Relevant,
}
}
pub unsafe fn change_state<U>(self, f: impl FnOnce(S) -> U) -> CommandBuffer<B, C, U, L, R> {
CommandBuffer {
raw: self.raw,
capability: self.capability,
state: f(self.state),
level: self.level,
reset: self.reset,
family: self.family,
relevant: self.relevant,
}
}
pub fn capability(&self) -> C
where
C: Capability,
{
self.capability
}
pub fn family(&self) -> FamilyId {
self.family
}
pub fn with_queue_type(self) -> CommandBuffer<B, gfx_hal::QueueType, S, L, R>
where
C: Capability,
{
CommandBuffer {
raw: self.raw,
capability: self.capability.into_queue_type(),
state: self.state,
level: self.level,
reset: self.reset,
family: self.family,
relevant: self.relevant,
}
}
pub fn with_capability<U>(self) -> Result<CommandBuffer<B, U, S, L, R>, Self>
where
C: Supports<U>,
{
if let Some(capability) = self.capability.supports() {
Ok(CommandBuffer {
raw: self.raw,
capability: capability,
state: self.state,
level: self.level,
reset: self.reset,
family: self.family,
relevant: self.relevant,
})
} else {
Err(self)
}
}
}
pub unsafe trait BeginInfo<'a, B: Backend, L> {
type PassRelation: RenderPassRelation<L>;
fn inheritance_info(self) -> gfx_hal::command::CommandBufferInheritanceInfo<'a, B>;
}
unsafe impl<'a, B, L> BeginInfo<'a, B, L> for ()
where
B: Backend,
L: Level,
{
type PassRelation = OutsideRenderPass;
fn inheritance_info(self) -> gfx_hal::command::CommandBufferInheritanceInfo<'a, B> {
gfx_hal::command::CommandBufferInheritanceInfo::default()
}
}
unsafe impl<'a, B> BeginInfo<'a, B, SecondaryLevel> for gfx_hal::pass::Subpass<'a, B>
where
B: Backend,
{
type PassRelation = RenderPassContinue;
fn inheritance_info(self) -> gfx_hal::command::CommandBufferInheritanceInfo<'a, B> {
gfx_hal::command::CommandBufferInheritanceInfo {
subpass: Some(self),
framebuffer: None,
..gfx_hal::command::CommandBufferInheritanceInfo::default()
}
}
}
unsafe impl<'a, B, F> BeginInfo<'a, B, SecondaryLevel>
for (gfx_hal::pass::Subpass<'a, B>, Option<&'a F>)
where
B: Backend,
F: std::borrow::Borrow<B::Framebuffer>,
{
type PassRelation = RenderPassContinue;
fn inheritance_info(self) -> gfx_hal::command::CommandBufferInheritanceInfo<'a, B> {
gfx_hal::command::CommandBufferInheritanceInfo {
subpass: Some(self.0),
framebuffer: self.1.map(F::borrow),
..gfx_hal::command::CommandBufferInheritanceInfo::default()
}
}
}
unsafe impl<'a, B, F> BeginInfo<'a, B, SecondaryLevel> for (gfx_hal::pass::Subpass<'a, B>, &'a F)
where
B: Backend,
F: std::borrow::Borrow<B::Framebuffer>,
{
type PassRelation = RenderPassContinue;
fn inheritance_info(self) -> gfx_hal::command::CommandBufferInheritanceInfo<'a, B> {
gfx_hal::command::CommandBufferInheritanceInfo {
subpass: Some(self.0),
framebuffer: Some(self.1.borrow()),
..gfx_hal::command::CommandBufferInheritanceInfo::default()
}
}
}
impl<B, C, L, R> CommandBuffer<B, C, InitialState, L, R>
where
B: Backend,
{
pub fn begin<'a, U, P>(
mut self,
usage: U,
info: impl BeginInfo<'a, B, L, PassRelation = P>,
) -> CommandBuffer<B, C, RecordingState<U, P>, L, R>
where
U: Usage,
P: RenderPassRelation<L>,
{
let pass_relation = P::default();
unsafe {
gfx_hal::command::RawCommandBuffer::begin(
self.raw(),
usage.flags() | pass_relation.flags(),
info.inheritance_info(),
);
self.change_state(|_| RecordingState(usage, pass_relation))
}
}
}
impl<'a, B, C, U, P, L, R> CommandBuffer<B, C, RecordingState<U, P>, L, R>
where
B: Backend,
{
pub fn finish(mut self) -> CommandBuffer<B, C, ExecutableState<U, P>, L, R> {
unsafe {
gfx_hal::command::RawCommandBuffer::finish(self.raw());
self.change_state(|s| ExecutableState(s.0, s.1))
}
}
}
impl<B, C, N, L, R> CommandBuffer<B, C, PendingState<N>, L, R>
where
B: Backend,
{
pub unsafe fn mark_complete(self) -> CommandBuffer<B, C, N, L, R> {
self.change_state(|PendingState(state)| state)
}
}
impl<B, C, S, L> CommandBuffer<B, C, S, L, IndividualReset>
where
B: Backend,
S: Resettable,
{
pub fn reset(self) -> CommandBuffer<B, C, InitialState, L, IndividualReset> {
unsafe { self.change_state(|_| InitialState) }
}
}
impl<B, C, S, L> CommandBuffer<B, C, S, L>
where
B: Backend,
S: Resettable,
{
pub unsafe fn mark_reset(self) -> CommandBuffer<B, C, InitialState, L> {
self.change_state(|_| InitialState)
}
}
impl<B, C, S, L, R> CommandBuffer<B, C, S, L, R>
where
B: Backend,
S: Resettable,
{
pub fn into_raw(self) -> B::CommandBuffer {
self.relevant.dispose();
unsafe {
*Box::from_raw(self.raw.as_ptr())
}
}
pub fn raw(&mut self) -> &mut B::CommandBuffer {
unsafe {
self.raw.as_mut()
}
}
}