Minimal Initialization

Published June 12, 2009
Advertisement
I was fooling around with SlimDX the other day and decided to try to make the nicest looking minimal initialization program that I could. We've been adding little utility classes to help make things smoother, so the end result is, in my opinion, quite pretty to look at.

Direct3D9:
using System;using System.Drawing;using SlimDX;using SlimDX.Direct3D9;using SlimDX.Windows;namespace Sample{    static class Program    {        [STAThread]        static void Main()        {            var form = new RenderForm("SlimDX Comparison");            var device = new Device(new Direct3D(), 0, DeviceType.Hardware, form.Handle, CreateFlags.HardwareVertexProcessing, new PresentParameters()            {                BackBufferWidth = form.ClientSize.Width,                BackBufferHeight = form.ClientSize.Height            });            MessagePump.Run(form, () =>            {                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);                device.BeginScene();                device.EndScene();                device.Present();            });            foreach (var item in ObjectTable.Objects)                item.Dispose();        }    }}


The C++ equivalent is, as you might imagine, quite disgusting by comparison:
#include #include #pragma comment(lib, "d3d9.lib")LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	switch (message)	{	case WM_DESTROY:		PostQuitMessage(0);		return 0;	case WM_PAINT:		ValidateRect(hWnd, 0);		return 0;	}	return DefWindowProc(hWnd, message, wParam, lParam);}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){	WNDCLASSEX wcex;	wcex.cbSize = sizeof(WNDCLASSEX);	wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	wcex.lpfnWndProc = WndProc;	wcex.cbClsExtra = 0;	wcex.cbWndExtra = 0;	wcex.hInstance = hInstance;	wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);	wcex.hCursor = LoadCursor(hInstance, IDC_ARROW);	wcex.hbrBackground = reinterpret_cast(GetStockObject(WHITE_BRUSH));	wcex.lpszMenuName = NULL;	wcex.lpszClassName = L"TestWindowClass";	wcex.hIconSm = wcex.hIcon;	RegisterClassEx(&wcex);	HWND hWnd = CreateWindow(L"TestWindowClass", L"SlimDX Comparison", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, 0, 0, hInstance, 0);	RECT rect = {0, 0, 800, 600};	AdjustWindowRect(&rect, GetWindowLong(hWnd, GWL_STYLE), FALSE);	SetWindowPos(hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);	ShowWindow(hWnd, SW_SHOW);	UpdateWindow(hWnd);	LPDIRECT3D9 d3d = Direct3DCreate9(D3D_SDK_VERSION);	if (!d3d)	{		MessageBox(NULL, L"Direct3DCreate9 - Failed", 0, 0);		return 0;	}	D3DPRESENT_PARAMETERS pp;	pp.BackBufferCount = 1;	pp.BackBufferFormat = D3DFMT_X8R8G8B8;	pp.BackBufferWidth = 800;	pp.BackBufferHeight = 600;	pp.MultiSampleType = D3DMULTISAMPLE_NONE;	pp.MultiSampleQuality = 0;	pp.Windowed = TRUE;	pp.SwapEffect = D3DSWAPEFFECT_DISCARD;	pp.hDeviceWindow = hWnd;	pp.EnableAutoDepthStencil = TRUE;	pp.AutoDepthStencilFormat = D3DFMT_D24X8;	pp.Flags = 0;	pp.FullScreen_RefreshRateInHz = 0;	pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;	LPDIRECT3DDEVICE9 device;	HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &device);	if (FAILED(hr))	{		d3d->Release();		MessageBox(NULL, L"CreateDevice - Failed", 0, 0);		return 0;	}	MSG msg;	while (1)	{		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))		{			if (msg.message == WM_QUIT)				break;			TranslateMessage(&msg);			DispatchMessage (&msg);		}		else		{			device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0);			device->BeginScene();			device->EndScene();			device->Present(0, 0, 0, 0);		}	}	device->Release();	d3d->Release();	return msg.wParam;}


This is one using our latest addition of Direct3D11. The D3D10 version looks quite similar to this.
using System;using SlimDX;using SlimDX.Direct3D11;using SlimDX.DXGI;using SlimDX.Windows;namespace Demo{    static class Program    {        [STAThread]        static void Main()        {            var form = new RenderForm();            var desc = new SwapChainDescription()            {                BufferCount = 1,                ModeDescription = new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, new Rational(60, 1), Format.B8G8R8A8_UNorm),                IsWindowed = true,                OutputHandle = form.Handle,                SampleDescription = new SampleDescription(1, 0),                SwapEffect = SwapEffect.Discard,                Usage = Usage.RenderTargetOutput            };            SwapChain swapChain;            SlimDX.Direct3D11.Device device;            SlimDX.Direct3D11.Device.CreateWithSwapChain(null, DriverType.Reference, DeviceCreationFlags.Debug, desc, out device, out swapChain);            var context = new DeviceContext(device);            var renderView = new RenderTargetView(device, swapChain.GetBuffer2D
>(0));

context.OutputMerger.SetTargets(renderView);
context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height));

MessagePump.Run(form, () =>
{
context.ClearRenderTargetView(renderView, new Color4(0.0f, 0.5f, 1.0f));
swapChain.Present(0, PresentFlags.None);
});

foreach (var item in ObjectTable.Objects)
item.Dispose();
}
}
}



I've been tossing around the idea of making these into project templates for Visual Studio. Thoughts?
0 likes 12 comments

Comments

ViLiO
BOMP!
June 12, 2009 05:21 PM
Mike.Popoloski
BOMP!
June 12, 2009 05:32 PM
Drilian
BOMP!
June 12, 2009 05:47 PM
MaulingMonkey
[6/12/2009 2:47:00 PM] <MikeP> MaulingMonkey: convert these to ruby for us: http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=458883
[6/12/2009 2:47:09 PM] <MikeP> IronRuby that is :D

I'm still using VS2008, and VS lacks IronRuby integration at the moment. However, using the Ruby.Console project (ir.exe) we can run this from the command line:

require 'System'
require 'System.Drawing'
require 'C:\tools\slimdx\build\x86\Release\SlimDX.dll' # I don't have SlimDX installed in my GAC

include System;
include System::Drawing;
include SlimDX;
include SlimDX::Direct3D9;
include SlimDX::Windows;

form = RenderForm.new("SlimDX Comparison")

device = Device.new(Direct3D.new, 0, DeviceType.hardware, form.handle, CreateFlags.hardware_vertex_processing, PresentParameters.new.instance_eval {
    back_buffer_width  = form.client_size.width
    back_buffer_height = form.client_size.height
    self
})

MessagePump.run(form, lambda {
    device.clear(ClearFlags.target | ClearFlags.z_buffer, Color.black, 1.0, 0)
    device.begin_scene
    device.end_scene
    device.present
})

ObjectTable.Objects.each { |item| item.dispose }




It seems the current state of IronRuby is able to deal with the sample completely unmangled as well:

require 'System'
require 'System.Drawing'
require 'C:\tools\slimdx\build\x86\Release\SlimDX.dll' # I don't have SlimDX installed in my GAC

include System;
include System::Drawing;
include SlimDX;
include SlimDX::Direct3D9;
include SlimDX::Windows;

form = RenderForm.new("SlimDX Comparison")

device = Device.new(Direct3D.new(), 0, DeviceType.Hardware, form.Handle, CreateFlags.HardwareVertexProcessing, PresentParameters.new.instance_eval {
    BackBufferWidth  = form.ClientSize.Width
    BackBufferHeight = form.ClientSize.Height
    self
})

MessagePump.run(form, lambda {
    device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0, 0)
    device.BeginScene()
    device.EndScene()
    device.Present()
})

ObjectTable.Objects.each { |item| item.Dispose() }

June 12, 2009 06:11 PM
Promit
Working VB 9 version, as close as I can get it:

Imports System
Imports System.Drawing

Imports SlimDX
Imports SlimDX.Direct3D9
Imports SlimDX.Windows

Module Module1

    Sub Main()
        Dim form As New RenderForm
        form.Show()
        Dim device As New Device(New Direct3D(), 0, DeviceType.Hardware, form.Handle, CreateFlags.HardwareVertexProcessing, _
        New PresentParameters With { _
            .BackBufferWidth = form.ClientSize.Width, _
            .BackBufferHeight = form.ClientSize.Height _
        })

        MessagePump.Run(form, Function() MainLoop(device))

        For Each item In ObjectTable.Objects
            item.Dispose()
        Next
    End Sub

    Function MainLoop(ByVal device As Device) As Boolean
        device.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.Black, 1.0F, 0)
        device.BeginScene()

        device.EndScene()
        device.Present()
        Return True
    End Function
End Module

June 12, 2009 06:29 PM
Daerax
untested quick mechanical translation. 98.76% sure it works.
open System
open SlimDX.Windows
open System.Windows.Forms
open System.Drawing
open SlimDX
open SlimDX.Direct3D9

let form = new RenderForm("SlimDX Comparison")
let device = new Device(new Direct3D() , 0,  DeviceType.Hardware ,form.Handle, CreateFlags.HardwareVertexProcessing 
                               ,new PresentParameters(BackBufferWidth  = form.ClientSize.Width, BackBufferHeight = form.ClientSize.Height))
                               
MessagePump.Run ( form , fun () -> 
                           device.Clear(ClearFlags.Target ||| ClearFlags.ZBuffer, Color.Black, 1.0f, 0)
                           device.BeginScene()

                           device.EndScene()
                           device.Present())
                           
[<STAThread>]
do Application.Run(form)

for item in ObjectTable.Objects do
    item.Dispose ()


June 13, 2009 01:17 AM
Mike.Popoloski
What language is that? It looks similar to F#, but I'm not quite sure it's the same. Rotaerk from #gamedev gave me this version:


open System
open System.Drawing

open SlimDX
open SlimDX.Direct3D9
open SlimDX.Windows

[<STAThread>]
let main () =
    let form = new RenderForm "SlimDX Comparison"
    let device =
        new Device (
            new Direct3D (), 0, DeviceType.Hardware, form.Handle, CreateFlags.HardwareVertexProcessing,
            PresentParameters (
                BackBufferWidth = form.ClientSize.Width,
                BackBufferHeight = form.ClientSize.Height
            )
        )
    
    let mainLoop () =
        device.Clear (ClearFlags.Target ||| ClearFlags.ZBuffer, Color4 Color.Black, 1.0f, 0) |> ignore
        device.BeginScene () |> ignore
        device.EndScene () |> ignore
        device.Present () |> ignore
    
    MessagePump.Run (form, MainLoop mainLoop)

    ObjectTable.Objects |> Seq.iter (fun o -> o.Dispose ())

main ()

June 13, 2009 11:08 AM
Daerax
Yep its F# too. F# gives warnings when functions which dont return unit are not assigned and are then sequenced. Piping ( |> ) into ignore gets rid of those warning but i didn't do that. I use a simple for loop instead of Sequence iter function.

Errors in the code i gave it seems would be that Color.Black must be given to some Color4 class. and in MessagePump.Run argument 2 instead of fun () -> SlimDX stuff , MainLoop ( fun () -> slimDXStuff), where I assume MainLoop is some class. In lieu of a main function, appliaction.run will start the event loop.
June 13, 2009 11:37 AM
Mike.Popoloski
Hmmm. What's that other language you were using... Nemerle? What would it look like in that?
June 13, 2009 11:59 AM
Daerax
I was going to test the new build but a couple of minutes into the svn download I remembered that it takes what 6 minutes to build? Probably longer on my strained machine. And more importantly I did not install the C++ compiler part of visual studio on my machine. heh.

Nemerle syntax is pretty close to C#'s. The braces are optional, I took em out. Anyways in Nemerle it would look like (Im assuming that MainLoop wont be required since Color4 was not when I tried device.clear on latest release, plus Nemerle lambda expressions and classes tend to interop cleanly with C#):


#pragma indent

using System
using SlimDX.Windows
using System.Drawing
using SlimDX
using SlimDX.Direct3D9

module Program
  [STAThread]
  Main() : void 
            def form = RenderForm("SlimDX Comparison")
            def presentParams =  PresentParameters()
            presentParams.BackBufferWidth = form.ClientSize.Width ;presentParams.BackBufferHeight = form.ClientSize.Height
            def device = Device(Direct3D(), 0, DeviceType.Hardware,form.Handle, CreateFlags.HardwareVertexProcessing, presentParams)            

            MessagePump.Run(form, () =>
            {
                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
                device.BeginScene();

                device.EndScene();
                device.Present();
            })

            foreach (item in ObjectTable.Objects)
                item.Dispose() 

June 13, 2009 12:51 PM
Mike.Popoloski
Hmm, that does look a lot like C#. Our build times aren't that bad anymore; we've cut down on them a lot using PCHs and renaming specific files.
June 13, 2009 03:31 PM
STufaro
I wonder if the June 2009 DirectX SDK will ever be released. That way you guys can put out another release and I don't have to build SlimDX myself (it would hurt my computer's brain) and I can play with these cool new toys.
June 26, 2009 06:42 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement

Latest Entries

New Blog

2022 views

Progress Update

1550 views

Start of Project

1513 views

New Job

2220 views

The Downward Spiral

2879 views

Job Interviews

1480 views
Advertisement