dxplr 0.0.11

Rust wrapper around D3D12 and DXGI
Documentation
use crate::d3d11::IDeviceContext;
use crate::dxgi::{ISwapChain, SwapChain};
use crate::result::{hresult, HResult};
use crate::{impl_bitflag_operators, impl_interface, Interface};
use com_ptr::ComPtr;
use winapi::shared::dxgi::*;
use winapi::um::d3d11::*;
use winapi::um::d3d11sdklayers::*;
use winapi::Interface as _;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DebugFeature(u32);
#[allow(non_upper_case_globals)]
impl DebugFeature {
    pub const FlushPerRenderOp: Self = Self(D3D11_DEBUG_FEATURE_FLUSH_PER_RENDER_OP);
    pub const FinishPerRenderOp: Self = Self(D3D11_DEBUG_FEATURE_FINISH_PER_RENDER_OP);
    pub const PresentPerRenderOp: Self = Self(D3D11_DEBUG_FEATURE_PRESENT_PER_RENDER_OP);
    pub const AlwaysDiscardOfferedResource: Self =
        Self(D3D11_DEBUG_FEATURE_ALWAYS_DISCARD_OFFERED_RESOURCE);
    pub const NeverDiscardOfferedResource: Self =
        Self(D3D11_DEBUG_FEATURE_NEVER_DISCARD_OFFERED_RESOURCE);
    pub const AvoidBehaviorChangingDebugAids: Self =
        Self(D3D11_DEBUG_FEATURE_AVOID_BEHAVIOR_CHANGING_DEBUG_AIDS);
    pub const DisableTiledResourceMappingTrackingAndValidation: Self =
        Self(D3D11_DEBUG_FEATURE_DISABLE_TILED_RESOURCE_MAPPING_TRACKING_AND_VALIDATION);
}
impl_bitflag_operators!(DebugFeature);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum MessageCategory {
    ApplicationDefined = D3D11_MESSAGE_CATEGORY_APPLICATION_DEFINED,
    Miscellaneous = D3D11_MESSAGE_CATEGORY_MISCELLANEOUS,
    Initialization = D3D11_MESSAGE_CATEGORY_INITIALIZATION,
    Cleanup = D3D11_MESSAGE_CATEGORY_CLEANUP,
    Compilation = D3D11_MESSAGE_CATEGORY_COMPILATION,
    StateCreation = D3D11_MESSAGE_CATEGORY_STATE_CREATION,
    StateSetting = D3D11_MESSAGE_CATEGORY_STATE_SETTING,
    StateGetting = D3D11_MESSAGE_CATEGORY_STATE_GETTING,
    ResourceManipulation = D3D11_MESSAGE_CATEGORY_RESOURCE_MANIPULATION,
    Execution = D3D11_MESSAGE_CATEGORY_EXECUTION,
    Shader = D3D11_MESSAGE_CATEGORY_SHADER,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageID(pub u32);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum MessageSeverity {
    Corruption = D3D11_MESSAGE_SEVERITY_CORRUPTION,
    Error = D3D11_MESSAGE_SEVERITY_ERROR,
    Warning = D3D11_MESSAGE_SEVERITY_WARNING,
    Info = D3D11_MESSAGE_SEVERITY_INFO,
    Message = D3D11_MESSAGE_SEVERITY_MESSAGE,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct RLDOFlags(u32);
#[allow(non_upper_case_globals)]
impl RLDOFlags {
    pub const Summary: Self = Self(D3D11_RLDO_SUMMARY);
    pub const Detail: Self = Self(D3D11_RLDO_DETAIL);
    pub const IgnoreInternal: Self = Self(D3D11_RLDO_IGNORE_INTERNAL);
}
impl_bitflag_operators!(RLDOFlags);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct ShaderTrackingOptions(u32);
#[allow(non_upper_case_globals)]
impl ShaderTrackingOptions {
    pub const Ignore: Self = Self(D3D11_SHADER_TRACKING_OPTION_IGNORE);
    pub const TrackUninitialized: Self = Self(D3D11_SHADER_TRACKING_OPTION_TRACK_UNINITIALIZED);
    pub const TrackRAW: Self = Self(D3D11_SHADER_TRACKING_OPTION_TRACK_RAW);
    pub const TrackWAR: Self = Self(D3D11_SHADER_TRACKING_OPTION_TRACK_WAR);
    pub const TrackWAW: Self = Self(D3D11_SHADER_TRACKING_OPTION_TRACK_WAW);
    pub const AllowSame: Self = Self(D3D11_SHADER_TRACKING_OPTION_ALLOW_SAME);
    pub const TrackAtomicConsistency: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_TRACK_ATOMIC_CONSISTENCY);
    pub const TrackRAWAcrossThreadGroups: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_TRACK_RAW_ACROSS_THREADGROUPS);
    pub const TrackWARAcrossThreadGroups: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_TRACK_WAR_ACROSS_THREADGROUPS);
    pub const TrackWAWAcrossThreadGroups: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_TRACK_WAW_ACROSS_THREADGROUPS);
    pub const TrackAtomicConsistencyAcrossThreadGroups: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_TRACK_ATOMIC_CONSISTENCY_ACROSS_THREADGROUPS);
    pub const UAVSpecificFlags: Self = Self(D3D11_SHADER_TRACKING_OPTION_UAV_SPECIFIC_FLAGS);
    pub const AllHazards: Self = Self(D3D11_SHADER_TRACKING_OPTION_ALL_HAZARDS);
    pub const AllHazardsAllowingSame: Self =
        Self(D3D11_SHADER_TRACKING_OPTION_ALL_HAZARDS_ALLOWING_SAME);
    pub const AllOptions: Self = Self(D3D11_SHADER_TRACKING_OPTION_ALL_OPTIONS);
}
impl_bitflag_operators!(ShaderTrackingOptions);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum ShaderTrackingResourceType {
    None = D3D11_SHADER_TRACKING_RESOURCE_TYPE_NONE,
    UAVDeviceMemory = D3D11_SHADER_TRACKING_RESOURCE_TYPE_UAV_DEVICEMEMORY,
    NonUAVDeviceMemory = D3D11_SHADER_TRACKING_RESOURCE_TYPE_NON_UAV_DEVICEMEMORY,
    AllDeviceMemory = D3D11_SHADER_TRACKING_RESOURCE_TYPE_ALL_DEVICEMEMORY,
    GroupSharedMemory = D3D11_SHADER_TRACKING_RESOURCE_TYPE_GROUPSHARED_MEMORY,
    AllSharedMemory = D3D11_SHADER_TRACKING_RESOURCE_TYPE_ALL_SHARED_MEMORY,
    GroupSharedNonUAV = D3D11_SHADER_TRACKING_RESOURCE_TYPE_GROUPSHARED_NON_UAV,
    All = D3D11_SHADER_TRACKING_RESOURCE_TYPE_ALL,
}

#[derive(Debug, Clone)]
pub struct InfoQueueFilter {
    allow_list: InfoQueueFilterDesc,
    deny_list: InfoQueueFilterDesc,
}

#[derive(Debug, Clone)]
pub struct InfoQueueFilterDesc {
    category_list: Vec<MessageCategory>,
    severity_list: Vec<MessageSeverity>,
    id_list: Vec<MessageID>,
}

#[derive(Debug, Clone)]
pub struct Message {
    category: MessageCategory,
    severity: MessageSeverity,
    id: MessageID,
    description: String,
}

pub trait IDebug: Interface {
    fn get_feature_mask(&self) -> Option<DebugFeature>;
    fn get_present_per_render_op_delay(&self) -> u32;
    fn get_swap_chain(&self) -> Result<SwapChain, HResult>;
    fn report_live_device_objects(&self, flags: RLDOFlags) -> Result<(), HResult>;
    fn set_feature_mask(&self, mask: Option<DebugFeature>) -> Result<(), HResult>;
    fn set_present_per_render_op_delay(&self, milliseconds: u32) -> Result<(), HResult>;
    fn set_swap_chain(&self, swap_chain: &impl ISwapChain) -> Result<(), HResult>;
    fn validate_context(&self, context: &impl IDeviceContext) -> Result<(), HResult>;
    fn validate_context_for_dispatch(&self, context: &impl IDeviceContext) -> Result<(), HResult>;
}
#[derive(Debug, Clone)]
pub struct Debug(ComPtr<ID3D11Debug>);
macro_rules! impl_debug {
    ($s: ident, $interface: ident) => {
        impl_interface!($s, $interface);
        impl IDebug for $s {
            fn get_feature_mask(&self) -> Option<DebugFeature> {
                unsafe {
                    let mask = self.0.GetFeatureMask();
                    if mask == 0 {
                        None
                    } else {
                        Some(DebugFeature(mask))
                    }
                }
            }
            fn get_present_per_render_op_delay(&self) -> u32 {
                unsafe { self.0.GetPresentPerRenderOpDelay() }
            }
            fn get_swap_chain(&self) -> Result<SwapChain, HResult> {
                unsafe {
                    Ok(SwapChain(ComPtr::new(|| {
                        let mut obj = std::ptr::null_mut();
                        let res = self.0.GetSwapChain(&mut obj);
                        hresult(obj, res)
                    })?))
                }
            }
            fn report_live_device_objects(&self, flags: RLDOFlags) -> Result<(), HResult> {
                unsafe {
                    let res = self.0.ReportLiveDeviceObjects(flags.0);
                    hresult((), res)
                }
            }
            fn set_feature_mask(&self, mask: Option<DebugFeature>) -> Result<(), HResult> {
                unsafe {
                    let res = self.0.SetFeatureMask(mask.map_or(0, |m| m.0));
                    hresult((), res)
                }
            }
            fn set_present_per_render_op_delay(&self, milliseconds: u32) -> Result<(), HResult> {
                unsafe {
                    let res = self.0.SetPresentPerRenderOpDelay(milliseconds);
                    hresult((), res)
                }
            }
            fn set_swap_chain(&self, swap_chain: &impl ISwapChain) -> Result<(), HResult> {
                unsafe {
                    let res = self
                        .0
                        .SetSwapChain(swap_chain.as_ptr() as *mut IDXGISwapChain);
                    hresult((), res)
                }
            }
            fn validate_context(&self, context: &impl IDeviceContext) -> Result<(), HResult> {
                unsafe {
                    let res = self
                        .0
                        .ValidateContext(context.as_ptr() as *mut ID3D11DeviceContext);
                    hresult((), res)
                }
            }
            fn validate_context_for_dispatch(
                &self,
                context: &impl IDeviceContext,
            ) -> Result<(), HResult> {
                unsafe {
                    let res = self
                        .0
                        .ValidateContextForDispatch(context.as_ptr() as *mut ID3D11DeviceContext);
                    hresult((), res)
                }
            }
        }
    };
}
impl_debug!(Debug, ID3D11Debug);