d3d11 0.3.3

Safe(r) bindings to the D3D11 API
Documentation
use crate::{impl_device_child, verify_ffi_struct};
use d3d11_ffi::Direct3D11::*;

pub use d3d11_ffi::Direct3D11::D3D11_QUERY_DATA_TIMESTAMP_DISJOINT;

pub trait Asynchronous: Sized {
    fn to_ffi_async(&self) -> ID3D11Asynchronous;
    fn from_ffi_async(resource: ID3D11Asynchronous) -> Option<Self>;
}

#[macro_export]
macro_rules! impl_asynchronous {
    ($name:ident) => {
        impl_device_child!($name);
        impl $crate::query::Asynchronous for $name {
            fn to_ffi_async(&self) -> ID3D11Asynchronous {
                self.0.clone().into()
            }

            fn from_ffi_async(resource: ID3D11Asynchronous) -> Option<Self> {
                use d3d11_ffi::core::Interface;
                resource.cast().ok().map(Self)
            }
        }
    };
}

#[repr(transparent)]
#[derive(Clone)]
pub struct Query(pub(crate) ID3D11Query);
impl_asynchronous!(Query);

#[repr(transparent)]
#[derive(Clone)]
pub struct Predicate(pub(crate) ID3D11Predicate);
impl_asynchronous!(Predicate);

#[repr(transparent)]
#[derive(Clone)]
pub struct Counter(pub(crate) ID3D11Counter);
impl_asynchronous!(Counter);

#[repr(C)]
#[derive(Clone, Debug)]
pub struct QueryDesc {
    pub query: QueryType,
    pub misc_flags: u32, // TODO: Bitflags
}
verify_ffi_struct!(QueryDesc, D3D11_QUERY_DESC);

impl QueryDesc {
    pub fn new(query: QueryType, misc_flags: u32) -> Self {
        Self { query, misc_flags }
    }

    pub fn event() -> Self {
        Self::new(QueryType::Event, 0)
    }

    pub fn timestamp() -> Self {
        Self::new(QueryType::Timestamp, 0)
    }

    pub fn timestamp_disjoint() -> Self {
        Self::new(QueryType::TimestampDisjoint, 0)
    }

    pub fn occlusion() -> Self {
        Self::new(QueryType::Occlusion, 0)
    }

    /// # Parameters
    /// - `hint`: If true, tells the hardware that if it is not yet sure if something is hidden or not to draw it anyway.
    ///
    /// Note that predication data cannot be returned to your application via [`crate::DeviceContext::get_data`] when using this flag.
    pub fn occlusion_predicate(hint: bool) -> Self {
        Self::new(
            QueryType::OcclusionPredicate,
            if hint {
                D3D11_QUERY_MISC_PREDICATEHINT.0 as u32
            } else {
                0
            },
        )
    }
}

#[repr(i32)]
#[derive(Clone, Debug)]
pub enum QueryType {
    Event = D3D11_QUERY_EVENT.0,
    Occlusion = D3D11_QUERY_OCCLUSION.0,
    OcclusionPredicate = D3D11_QUERY_OCCLUSION_PREDICATE.0,
    PipelineStatistics = D3D11_QUERY_PIPELINE_STATISTICS.0,
    SoOverflowPredicate = D3D11_QUERY_SO_OVERFLOW_PREDICATE.0,
    SoOverflowPredicateStream0 = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0.0,
    SoOverflowPredicateStream1 = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1.0,
    SoOverflowPredicateStream2 = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2.0,
    SoOverflowPredicateStream3 = D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3.0,
    SoStatistics = D3D11_QUERY_SO_STATISTICS.0,
    SoStatisticsStream0 = D3D11_QUERY_SO_STATISTICS_STREAM0.0,
    SoStatisticsStream1 = D3D11_QUERY_SO_STATISTICS_STREAM1.0,
    SoStatisticsStream2 = D3D11_QUERY_SO_STATISTICS_STREAM2.0,
    SoStatisticsStream3 = D3D11_QUERY_SO_STATISTICS_STREAM3.0,
    Timestamp = D3D11_QUERY_TIMESTAMP.0,
    TimestampDisjoint = D3D11_QUERY_TIMESTAMP_DISJOINT.0,
}