• entries
    58
  • comments
    218
  • views
    114353

Minimal Initialization

Sign in to follow this  

525 views

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?
Sign in to follow this  


12 Comments


Recommended Comments

[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() }

Share this comment


Link to comment
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

Share this comment


Link to comment
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 ()


Share this comment


Link to comment
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 ()

Share this comment


Link to comment
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.

Share this comment


Link to comment
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()

Share this comment


Link to comment
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.

Share this comment


Link to comment
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.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now