#![doc = include_str!("../README.md")]
use std::ffi::CStr;
use anyhow::{Context, Result};
use windows::{
core::{IUnknown, Interface, Param, Type, PCSTR},
Win32::Graphics::Direct3D12,
};
mod bindings;
pub use bindings::Amd::Ext::D3D::AmdExtD3DCreateInfo;
use bindings::Amd::Ext::D3D::{IAmdExtD3DDevice1, IAmdExtD3DFactory, PFNAmdExtD3DCreateInterface};
#[derive(Clone, Debug)]
pub struct AmdExtD3DDevice {
amd_device_object: IAmdExtD3DDevice1,
}
impl AmdExtD3DDevice {
pub unsafe fn new(device: &IUnknown) -> Result<Self> {
let lib =
libloading::Library::new("amdxc64.dll").context("Could not open `amdxc64.dll`")?;
let amd_create_interface = lib
.get::<PFNAmdExtD3DCreateInterface>(b"AmdExtD3DCreateInterface\0")
.context("Could not find `AmdExtD3DCreateInterface` symbol in `amdxc64.dll`")?
.context("Symbol value (pointer) is NULL")?;
let mut result__ = ::std::ptr::null_mut();
let amd_factory: IAmdExtD3DFactory = (amd_create_interface)(
std::mem::transmute_copy(device),
&IAmdExtD3DFactory::IID,
&mut result__,
)
.and_then(|| Type::from_abi(result__))
.context("While creating `IAmdExtD3DFactory`")?;
let amd_device_object = amd_factory
.CreateInterface(device)
.context("While creating `IAmdExtD3DDevice1`")?;
Ok(Self { amd_device_object })
}
pub unsafe fn create_graphics_pipeline_state<T: Interface>(
&self,
amd_ext_create_info: &AmdExtD3DCreateInfo,
graphics_pipeline_state_desc: &Direct3D12::D3D12_GRAPHICS_PIPELINE_STATE_DESC,
) -> Result<T> {
self.amd_device_object
.CreateGraphicsPipelineState(amd_ext_create_info, graphics_pipeline_state_desc)
.context("While calling `CreateGraphicsPipelineState`")
}
pub unsafe fn push_marker(
&self,
gfx_cmd_list: impl Param<Direct3D12::ID3D12GraphicsCommandList>,
marker: &CStr,
) {
self.amd_device_object
.PushMarker(gfx_cmd_list, PCSTR::from_raw(marker.as_ptr().cast()))
}
pub unsafe fn pop_marker(
&self,
gfx_cmd_list: impl Param<Direct3D12::ID3D12GraphicsCommandList>,
) {
self.amd_device_object.PopMarker(gfx_cmd_list)
}
pub unsafe fn set_marker(
&self,
gfx_cmd_list: impl Param<Direct3D12::ID3D12GraphicsCommandList>,
marker: &CStr,
) {
self.amd_device_object
.SetMarker(gfx_cmd_list, PCSTR::from_raw(marker.as_ptr().cast()))
}
}