#![deny(missing_docs)]
#[cfg(any(target_os = "macos", target_os = "ios"))]
compile_error!("RenderDoc does not support this platform.");
#[macro_use]
extern crate bitflags;
extern crate libloading;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate renderdoc_derive;
extern crate renderdoc_sys;
#[cfg(feature = "glutin")]
extern crate glutin;
#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(target_os = "windows")]
extern crate wio;
pub use self::entry::{ApiVersion, V100, V110, V111, V112, V120, V130, V140};
use std::marker::PhantomData;
use std::os::raw::{c_ulonglong, c_void};
use std::u32;
#[cfg(feature = "glutin")]
use glutin::VirtualKeyCode;
#[cfg(windows)]
use winapi::shared::guiddef::GUID;
#[cfg(windows)]
use wio::com::ComPtr;
pub mod api;
pub mod entry;
pub mod prelude;
#[cfg(windows)]
pub const SHADER_MAGIC_DEBUG_VALUE_STRUCT: GUID = GUID {
Data1: 0xeab25520,
Data2: 0x6670,
Data3: 0x4865,
Data4: [0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff],
};
pub const SHADER_MAGIC_DEBUG_VALUE_BYTE_ARRAY: &[u8] = &[
0x20, 0x55, 0xb2, 0xea, 0x70, 0x66, 0x65, 0x48, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff,
];
pub const SHADER_MAGIC_DEBUG_VALUE_TRUNCATED: c_ulonglong = 0x4856670eab25520;
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum CaptureOption {
AllowVSync = 0,
AllowFullscreen = 1,
ApiValidation = 2,
CaptureCallstacks = 3,
CaptureCallstacksOnlyDraws = 4,
DelayForDebugger = 5,
VerifyMapWrites = 6,
HookIntoChildren = 7,
RefAllResources = 8,
SaveAllInitials = 9,
CaptureAllCmdLists = 10,
DebugOutputMute = 11,
AllowUnsupportedVendorExtensions = 12,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct DevicePointer(pub(crate) *const c_void);
impl From<*const c_void> for DevicePointer {
fn from(ptr: *const c_void) -> Self {
DevicePointer(ptr)
}
}
impl From<*mut c_void> for DevicePointer {
fn from(ptr: *mut c_void) -> Self {
DevicePointer(ptr)
}
}
#[cfg(windows)]
impl From<winapi::shared::windef::HGLRC> for DevicePointer {
fn from(ctx: winapi::shared::windef::HGLRC) -> Self {
DevicePointer(ctx as *mut _ as *const c_void)
}
}
#[cfg(windows)]
impl From<*mut winapi::um::d3d11::ID3D11Device> for DevicePointer {
fn from(ctx: *mut winapi::um::d3d11::ID3D11Device) -> Self {
DevicePointer(ctx as *mut _ as *const c_void)
}
}
#[cfg(windows)]
impl From<ComPtr<winapi::um::d3d11::ID3D11Device>> for DevicePointer {
fn from(ctx: ComPtr<winapi::um::d3d11::ID3D11Device>) -> Self {
unsafe { DevicePointer(ctx.as_raw() as *mut _ as *const c_void) }
}
}
#[cfg(windows)]
impl From<*mut winapi::um::d3d12::ID3D12Device> for DevicePointer {
fn from(ctx: *mut winapi::um::d3d12::ID3D12Device) -> Self {
DevicePointer(ctx as *mut _ as *const c_void)
}
}
#[cfg(windows)]
impl From<ComPtr<winapi::um::d3d12::ID3D12Device>> for DevicePointer {
fn from(ctx: ComPtr<winapi::um::d3d12::ID3D12Device>) -> Self {
unsafe { DevicePointer(ctx.as_raw() as *mut _ as *const c_void) }
}
}
#[cfg(feature = "glutin")]
impl<'a, T: glutin::ContextCurrentState> From<&'a glutin::Context<T>> for DevicePointer {
fn from(ctx: &'a glutin::Context<T>) -> Self {
use glutin::os::ContextTraitExt;
#[cfg(unix)]
unsafe {
use glutin::os::unix::RawHandle;
match ctx.raw_handle() {
RawHandle::Glx(glx) => DevicePointer::from(glx),
_ => panic!("RenderDoc only supports GLX contexts on Unix!"),
}
}
#[cfg(windows)]
unsafe {
use glutin::os::windows::RawHandle;
match ctx.raw_handle() {
RawHandle::Wgl(wgl) => DevicePointer::from(wgl),
_ => panic!("RenderDoc only supports WGL contexts on Windows!"),
}
}
}
}
#[allow(missing_docs)]
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum InputButton {
Key0 = 0x30,
Key1 = 0x31,
Key2 = 0x32,
Key3 = 0x33,
Key4 = 0x34,
Key5 = 0x35,
Key6 = 0x36,
Key7 = 0x37,
Key8 = 0x38,
Key9 = 0x39,
A = 0x41,
B = 0x42,
C = 0x43,
D = 0x44,
E = 0x45,
F = 0x46,
G = 0x47,
H = 0x48,
I = 0x49,
J = 0x4A,
K = 0x4B,
L = 0x4C,
M = 0x4D,
N = 0x4E,
O = 0x4F,
P = 0x50,
Q = 0x51,
R = 0x52,
S = 0x53,
T = 0x54,
U = 0x55,
V = 0x56,
W = 0x57,
X = 0x58,
Y = 0x59,
Z = 0x5A,
NonPrintable = 0x100,
Divide,
Multiply,
Subtract,
Plus,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Home,
End,
Insert,
Delete,
PageUp,
PageDn,
Backspace,
Tab,
PrtScrn,
Pause,
Max,
}
#[cfg(feature = "glutin")]
impl From<glutin::VirtualKeyCode> for InputButton {
fn from(code: glutin::VirtualKeyCode) -> InputButton {
match code {
VirtualKeyCode::Key1 => InputButton::Key1,
VirtualKeyCode::Key2 => InputButton::Key2,
VirtualKeyCode::Key3 => InputButton::Key3,
VirtualKeyCode::Key4 => InputButton::Key4,
VirtualKeyCode::Key5 => InputButton::Key5,
VirtualKeyCode::Key6 => InputButton::Key6,
VirtualKeyCode::Key7 => InputButton::Key7,
VirtualKeyCode::Key8 => InputButton::Key8,
VirtualKeyCode::Key9 => InputButton::Key9,
VirtualKeyCode::Key0 => InputButton::Key0,
VirtualKeyCode::A => InputButton::A,
VirtualKeyCode::B => InputButton::B,
VirtualKeyCode::C => InputButton::C,
VirtualKeyCode::D => InputButton::D,
VirtualKeyCode::E => InputButton::E,
VirtualKeyCode::F => InputButton::F,
VirtualKeyCode::G => InputButton::G,
VirtualKeyCode::H => InputButton::H,
VirtualKeyCode::I => InputButton::I,
VirtualKeyCode::J => InputButton::J,
VirtualKeyCode::K => InputButton::K,
VirtualKeyCode::L => InputButton::L,
VirtualKeyCode::M => InputButton::M,
VirtualKeyCode::N => InputButton::N,
VirtualKeyCode::O => InputButton::O,
VirtualKeyCode::P => InputButton::P,
VirtualKeyCode::Q => InputButton::Q,
VirtualKeyCode::R => InputButton::R,
VirtualKeyCode::S => InputButton::S,
VirtualKeyCode::T => InputButton::T,
VirtualKeyCode::U => InputButton::U,
VirtualKeyCode::V => InputButton::V,
VirtualKeyCode::W => InputButton::W,
VirtualKeyCode::X => InputButton::X,
VirtualKeyCode::Y => InputButton::Y,
VirtualKeyCode::Z => InputButton::Z,
VirtualKeyCode::Divide => InputButton::Divide,
VirtualKeyCode::Multiply => InputButton::Multiply,
VirtualKeyCode::Subtract => InputButton::Subtract,
VirtualKeyCode::Add => InputButton::Plus,
VirtualKeyCode::F1 => InputButton::F1,
VirtualKeyCode::F2 => InputButton::F2,
VirtualKeyCode::F3 => InputButton::F3,
VirtualKeyCode::F4 => InputButton::F4,
VirtualKeyCode::F5 => InputButton::F5,
VirtualKeyCode::F6 => InputButton::F6,
VirtualKeyCode::F7 => InputButton::F7,
VirtualKeyCode::F8 => InputButton::F8,
VirtualKeyCode::F9 => InputButton::F9,
VirtualKeyCode::F10 => InputButton::F10,
VirtualKeyCode::F11 => InputButton::F11,
VirtualKeyCode::F12 => InputButton::F12,
VirtualKeyCode::Home => InputButton::Home,
VirtualKeyCode::End => InputButton::End,
VirtualKeyCode::Insert => InputButton::Insert,
VirtualKeyCode::Delete => InputButton::Delete,
VirtualKeyCode::PageUp => InputButton::PageUp,
VirtualKeyCode::PageDown => InputButton::PageDn,
VirtualKeyCode::Back => InputButton::Backspace,
VirtualKeyCode::Tab => InputButton::Tab,
VirtualKeyCode::Snapshot => InputButton::PrtScrn,
VirtualKeyCode::Pause => InputButton::Pause,
_ => InputButton::Max,
}
}
}
bitflags! {
pub struct OverlayBits: u32 {
const ENABLED = 0x1;
const FRAME_RATE = 0x2;
const FRAME_NUMBER = 0x4;
const CAPTURE_LIST = 0x8;
const DEFAULT = (0x1 | 0x2 | 0x4 | 0x8);
const ALL = u32::MAX;
const NONE = u32::MIN;
}
}
pub type WindowHandle = *const c_void;
#[derive(Debug, RenderDoc)]
#[renderdoc_convert(V100, V110, V111, V112, V120, V130, V140)]
pub struct RenderDoc<V: ApiVersion>(V::Entry, PhantomData<*mut ()>);
impl<V: ApiVersion> RenderDoc<V> {
pub fn new() -> Result<RenderDoc<V>, String> {
let api = V::load()?;
Ok(RenderDoc(api, PhantomData))
}
pub unsafe fn raw_api(&self) -> V::Entry {
self.0.clone()
}
}
#[cfg(test)]
mod tests {
use super::api::*;
use super::*;
#[test]
fn get_set_capture_option_f32() {
let mut rd: RenderDoc<V110> = RenderDoc::new().expect("Failed to init");
let delay = rd.get_capture_option_f32(CaptureOption::DelayForDebugger);
assert_eq!(delay, 0.0f32);
rd.set_capture_option_f32(CaptureOption::DelayForDebugger, 2.5f32);
let delay = rd.get_capture_option_f32(CaptureOption::DelayForDebugger);
assert_eq!(delay, 2.0f32);
}
#[test]
fn get_set_capture_option_u32() {
let rd: RenderDoc<V110> = RenderDoc::new().expect("Failed to init");
let vsync = rd.get_capture_option_u32(CaptureOption::AllowVSync);
assert_eq!(vsync, 1u32);
let is_full = rd.get_capture_option_u32(CaptureOption::AllowFullscreen);
assert_eq!(is_full, 1u32);
let api_val_mode = rd.get_capture_option_u32(CaptureOption::ApiValidation);
let debug_mode = rd.get_capture_option_u32(CaptureOption::ApiValidation);
assert_eq!(api_val_mode, 0u32);
assert_eq!(api_val_mode, debug_mode);
let cc = rd.get_capture_option_u32(CaptureOption::CaptureCallstacks);
assert_eq!(cc, 0u32);
let cc_draw = rd.get_capture_option_u32(CaptureOption::CaptureCallstacksOnlyDraws);
assert_eq!(cc_draw, 0u32);
let ver_map = rd.get_capture_option_u32(CaptureOption::VerifyMapWrites);
assert_eq!(ver_map, 0u32);
let hook_in = rd.get_capture_option_u32(CaptureOption::HookIntoChildren);
assert_eq!(hook_in, 0u32);
let ref_all = rd.get_capture_option_u32(CaptureOption::RefAllResources);
assert_eq!(ref_all, 0u32);
let intls = rd.get_capture_option_u32(CaptureOption::SaveAllInitials);
assert_eq!(intls, 1u32);
let cmds = rd.get_capture_option_u32(CaptureOption::CaptureAllCmdLists);
assert_eq!(cmds, 0u32);
let is_muted = rd.get_capture_option_u32(CaptureOption::DebugOutputMute);
assert_eq!(is_muted, 1u32);
}
}