~raph/dx11-toy

c3700a740541b643731c4c68f11b3cde6f5950cf — Raph Levien 2 years ago be579a7 master
Move shaders into file

Also a bit of fiddling with buffers, making it easier to use
precompiled shaders.
3 files changed, 47 insertions(+), 29 deletions(-)

A shaders/shaders.hlsl
M src/d3d11.rs
M src/main.rs
A shaders/shaders.hlsl => shaders/shaders.hlsl +9 -0
@@ 0,0 1,9 @@
float4 vs_main( float4 pos : POSITION ) : SV_POSITION
{
	return pos;
}

float4 ps_main() : SV_TARGET
{
	return float4(1.0f, 1.0f, 1.0f, 1.0f);
}

M src/d3d11.rs => src/d3d11.rs +22 -9
@@ 1,3 1,4 @@
use std::ops::Deref;
use std::ptr::{null, null_mut};

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


@@ 95,12 96,12 @@ impl D3D11Device {
        }
    }

    pub fn create_vertex_shader(&self, shader: &D3DBlob) -> Result<D3D11VertexShader, Error> {
    pub fn create_vertex_shader(&self, shader: &[u8]) -> Result<D3D11VertexShader, Error> {
        unsafe {
            let mut ptr = null_mut();
            let hr = self.0.CreateVertexShader(
                shader.0.GetBufferPointer(),
                shader.0.GetBufferSize(),
                shader.as_ptr() as *const _,
                shader.len(),
                null_mut(),
                &mut ptr,
            );


@@ 108,12 109,12 @@ impl D3D11Device {
        }
    }

    pub fn create_pixel_shader(&self, shader: &D3DBlob) -> Result<D3D11PixelShader, Error> {
    pub fn create_pixel_shader(&self, shader: &[u8]) -> Result<D3D11PixelShader, Error> {
        unsafe {
            let mut ptr = null_mut();
            let hr = self.0.CreatePixelShader(
                shader.0.GetBufferPointer(),
                shader.0.GetBufferSize(),
                shader.as_ptr() as *const _,
                shader.len(),
                null_mut(),
                &mut ptr,
            );


@@ 124,7 125,7 @@ impl D3D11Device {
    pub fn create_input_layout(
        &self,
        descs: &[d3d11::D3D11_INPUT_ELEMENT_DESC],
        bytecode: &D3DBlob,
        bytecode: &[u8],
    ) -> Result<D3D11InputLayout, Error> {
        unsafe {
            assert!(descs.len() <= 0xffff_ffff);


@@ 132,8 133,8 @@ impl D3D11Device {
            let hr = self.0.CreateInputLayout(
                descs.as_ptr(),
                descs.len() as u32,
                bytecode.0.GetBufferPointer(),
                bytecode.0.GetBufferSize(),
                bytecode.as_ptr() as *const _,
                bytecode.len(),
                &mut ptr,
            );
            wrap(hr, ptr, D3D11InputLayout)


@@ 234,3 235,15 @@ impl D3DBlob {
        }
    }
}

impl Deref for D3DBlob {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        unsafe {
            let ptr = self.0.GetBufferPointer();
            let size = self.0.GetBufferSize();
            std::slice::from_raw_parts(ptr as *const _, size as usize)
        }
    }
}

M src/main.rs => src/main.rs +16 -20
@@ 1,6 1,7 @@
use std::ptr::{null, null_mut};

use winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD;
use winapi::shared::dxgi::DXGI_SWAP_EFFECT_SEQUENTIAL;
// compatibility is good.
use winapi::shared::{dxgi1_2, dxgiformat, dxgitype, minwindef};
use winapi::shared::dxgiformat::DXGI_FORMAT_R32G32B32_FLOAT;
use winapi::um::d3dcommon::D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;


@@ 15,19 16,8 @@ mod util;

use d3d11::D3DBlob;

const VERTEX_SHADER_HLSL: &str = r#"
float4 main( float4 pos : POSITION ) : SV_POSITION
{
	return pos;
}
"#;
const SHADER_HLSL: &str = include_str!("../shaders/shaders.hlsl");

const PIXEL_SHADER_HLSL: &str = r#"
float4 main() : SV_TARGET
{
	return float4(1.0f, 1.0f, 1.0f, 1.0f);
}
"#;

fn main() {
    unsafe {


@@ 79,18 69,19 @@ fn main() {
            },
            Scaling: dxgi1_2::DXGI_SCALING_STRETCH,
            Stereo: minwindef::FALSE,
            // Note: FLIP_DISCARD is Windows 8 only; negotiate
            SwapEffect: DXGI_SWAP_EFFECT_FLIP_DISCARD,
            // Note: consider using flip-mode for higher performance. However,
            // compatibility is good.
            SwapEffect: DXGI_SWAP_EFFECT_SEQUENTIAL,
        };
        let mut swap_chain = dxgi_factory
            .create_swapchain_for_hwnd(&d3d_device, hwnd, &desc)
            .unwrap();

        let vertex_shader_bc =
            D3DBlob::compile_shader(VERTEX_SHADER_HLSL, "vs_5_0", "main", 0).unwrap();
            D3DBlob::compile_shader(SHADER_HLSL, "vs_5_0", "vs_main", 0).unwrap();
        let vertex_shader = d3d_device.create_vertex_shader(&vertex_shader_bc).unwrap();
        let pixel_shader_bc =
            D3DBlob::compile_shader(PIXEL_SHADER_HLSL, "ps_5_0", "main", 0).unwrap();
            D3DBlob::compile_shader(SHADER_HLSL, "ps_5_0", "ps_main", 0).unwrap();
        let pixel_shader = d3d_device.create_pixel_shader(&pixel_shader_bc).unwrap();

        let ieds = [


@@ 144,15 135,20 @@ fn main() {
        device_context.ia_set_primitive_topology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        device_context.draw(3, 0);

        swap_chain.present(1, 0).unwrap();
        // Show window after first present to avoid flash of background color.
        // Defer window show to avoid flash of background color.
        //
        // With blit-model, the show has to happen before the present, otherwise
        // the contents will be missing. With flip-model, it can happen after. The
        // range of locations with no flash seems broad, so this seems like a good
        // and simple compromise.
        //
        // I did some research and found that this is very conservative, lots of
        // other combinations eliminate the flash, including just creating the
        // d3d11 factory before creating the window (and using WS_VISIBLE). But
        // this seems robust and doesn't seem to have a significant downside.
        winuser::ShowWindow(hwnd, winuser::SW_SHOWNORMAL);

        swap_chain.present(1, 0).unwrap();
 
        loop {
            let mut msg = std::mem::zeroed();
            // Note: we filter on hwnd so we get an error when the window is closed.