~raph/dx11-toy

9660d3737afbe511ca230cf5df65bd466f1f3477 — Raph Levien 2 years ago f6f5bed
Start wiring d3d11

WIP
5 files changed, 88 insertions(+), 5 deletions(-)

M Cargo.toml
A src/d3d11.rs
A src/dxgi.rs
M src/main.rs
A src/util.rs
M Cargo.toml => Cargo.toml +1 -1
@@ 7,5 7,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
winapi = { version = "0.3.7", features = ["libloaderapi", "winuser"] }
winapi = { version = "0.3.7", features = ["d3d11", "dxgi1_2", "libloaderapi", "winerror", "winuser"] }
wio = "0.2.2"

A src/d3d11.rs => src/d3d11.rs +35 -0
@@ 0,0 1,35 @@
use std::ptr::null_mut;

use winapi::um::{d3d11, d3dcommon};

use wio::com::ComPtr;

use crate::util::{wrap, Error};

pub struct D3D11Device(ComPtr<d3d11::ID3D11Device>);
pub struct D3D11DeviceContext(ComPtr<d3d11::ID3D11DeviceContext>);

impl D3D11Device {
    // This function only supports a fraction of available options.
    pub fn create() -> Result<(D3D11Device, D3D11DeviceContext), Error> {
        unsafe {
            let mut ptr = null_mut();
            let mut ctx_ptr = null_mut();
            let hr = d3d11::D3D11CreateDevice(
                null_mut(), /* adapter */
                d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
                null_mut(), /* module */
                d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT,
                null_mut(), /* feature levels */
                0,
                d3d11::D3D11_SDK_VERSION,
                &mut ptr,
                null_mut(), /* feature level */
                &mut ctx_ptr,
            );
            let device = wrap(hr, ptr, D3D11Device)?;
            let device_ctx = wrap(hr, ctx_ptr, D3D11DeviceContext)?;
            Ok((device, device_ctx))
        }
    }
}

A src/dxgi.rs => src/dxgi.rs +23 -0
@@ 0,0 1,23 @@
use std::ptr::null_mut;

use winapi::shared::{dxgi, dxgi1_2};
use winapi::Interface;

use wio::com::ComPtr;

use crate::util::{wrap, Error};

pub struct DXGIFactory2(ComPtr<dxgi1_2::IDXGIFactory2>);

impl DXGIFactory2 {
    pub fn create() -> Result<DXGIFactory2, Error> {
        unsafe {
            let mut ptr = null_mut();
            let hr = dxgi::CreateDXGIFactory1(
                &dxgi1_2::IDXGIFactory2::uuidof(),
                &mut ptr as *mut _ as *mut _,
            );
            wrap(hr, ptr, DXGIFactory2)
        }
    }
}

M src/main.rs => src/main.rs +10 -4
@@ 4,6 4,10 @@ use winapi::um::{errhandlingapi, wingdi, winuser};

use wio::wide::ToWide;

mod d3d11;
mod dxgi;
mod util;

fn main() {
    unsafe {
        let class_name = "dx11".to_wide_null();


@@ 22,8 26,7 @@ fn main() {
            lpszMenuName: null(),
            lpszClassName: class_name.as_ptr(),
        };
        let class_atom = winuser::RegisterClassW(&class);
        println!("class atom = {}", class_atom);
        let _class_atom = winuser::RegisterClassW(&class);
        let hwnd = winuser::CreateWindowExW(
            0,
            class_name.as_ptr(),


@@ 38,11 41,14 @@ fn main() {
            null_mut(),
            null_mut(),
        );
        println!("hwnd = {:?}, {:x}", hwnd, errhandlingapi::GetLastError());

        let (d3d_device, d3d_device_context) = d3d11::D3D11Device::create().unwrap();
        let dxgi_factory = dxgi::DXGIFactory2::create().unwrap();

        loop {
            let mut msg = std::mem::zeroed();
            if winuser::GetMessageW(&mut msg, null_mut(), 0, 0) == 0 {
            // Note: we filter on hwnd so we get an error when the window is closed.
            if winuser::GetMessageW(&mut msg, hwnd, 0, 0) <= 0 {
                break;
            }
            winuser::TranslateMessage(&mut msg);

A src/util.rs => src/util.rs +19 -0
@@ 0,0 1,19 @@
use winapi::shared::winerror::{HRESULT, SUCCEEDED};
use winapi::Interface;

use wio::com::ComPtr;

#[derive(Debug)]
pub struct Error(HRESULT);

pub unsafe fn wrap<T, U, F>(hr: HRESULT, ptr: *mut T, f: F) -> Result<U, Error>
where
    F: Fn(ComPtr<T>) -> U,
    T: Interface,
{
    if SUCCEEDED(hr) {
        Ok(f(ComPtr::from_raw(ptr)))
    } else {
        Err(Error(hr))
    }
}