DirectX use in 4DO

General forum for 4DO
Johnny
Site Admin
Posts: 119
Joined: Thu Oct 27, 2011 1:50 pm

DirectX use in 4DO

Postby Johnny » Wed Nov 09, 2011 7:37 am

I could use some feedback from any DirectX experts out there regarding how I'm using it in 4DO (hopefully this means you, incrediclint!)

The reasons I'm using DirectX are to keep blit load off the CPU and to achieve VSync. I've chosen to code to DirectX9 so that I can support windows XP. I could have also looked into OpenGL, but since I was already using SlimDX for DirectInput, I figured DirectX might as well come along for the ride.

Here's what I did, along with the uncertainties I hit along the way in comments.

Code: Select all

         
                     /////////////////////////////////////////
            // Initialize direct3d 9
            this.direct3D = new Direct3D();

            var presentParams = new PresentParameters();
            presentParams.Windowed = true;
            presentParams.SwapEffect = SwapEffect.Discard; // I've no idea if any of these is better than any other.
            presentParams.DeviceWindowHandle = this.Handle;
         
            // I calculated the maximum size by enumerating all the devices on the system
            // (i.e. all the monitors). I don't understand if this was a bad idea. Would I
            // be able to change all this on the window resize without issue? Would that
            // be more standard practice? I was assuming this trick would allow me to
            // resize more quickly. "Full Screen" in 4DO is really just a maximized window.
            presentParams.BackBufferWidth = maxSize.Width;
            presentParams.BackBufferHeight = maxSize.Height;

            // I have seen someone post a 4DO crash report on this line. I believe this will
            // throw an error if their machine doesn't support hardware acceleration. Ultimately
            // I worry there must be a better way of determining this without having a big
            // try/catch around everything. Is there a way to query system capabilities?
            this.device = new Device(this.direct3D, 0, DeviceType.Hardware, this.Handle, CreateFlags.HardwareVertexProcessing, presentParams);

            this.device.SetRenderState(RenderState.Lighting, false);

            // I had a heck of a time finding a pixel format that wouldn't just crash here.
            // Additionally, certain video cards did not "correctly" support this texture
            // when it wasn't a power-of-two. I have forced the textures to power-of-two
            // to attempt to support these scenarios. Is this normal?
            this.texture = new Texture(this.device, textureWidth, textureHeight, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
            var desc = this.texture.GetLevelDescription(0);


Later, I end up creating a triangle strip (with 2 triangles) to draw the bitmap to the device. I'm not sure if what I'm doing is overkill. I'm very curious to know if there's some other, more obvious mechanism for what I'm trying to do.
incrediclint
Posts: 16
Joined: Mon Oct 31, 2011 6:22 pm

Re: DirectX use in 4DO

Postby incrediclint » Thu Nov 10, 2011 3:11 am

Code: Select all

presentParams.SwapEffect = SwapEffect.Discard; // I've no idea if any of these is better than any other.


This is probably the best choice. This allows the device to choose the best method to use to move content from the frame buffer to the front buffer.

Basically, the device itself will switch between copying the frame buffer to the the front buffer for windowed mode and flipping the pointers to the buffers for fullscreen.

Code: Select all

// I calculated the maximum size by enumerating all the devices on the system
// (i.e. all the monitors). I don't understand if this was a bad idea. Would I
// be able to change all this on the window resize without issue? Would that
// be more standard practice? I was assuming this trick would allow me to
// resize more quickly. "Full Screen" in 4DO is really just a maximized window.
presentParams.BackBufferWidth = maxSize.Width;
presentParams.BackBufferHeight = maxSize.Height;


I've not done a whole lot of windowed DX programming, mostly stuck to full screen. I'm not sure I understand what you mean.

Code: Select all

// I have seen someone post a 4DO crash report on this line. I believe this will
// throw an error if their machine doesn't support hardware acceleration. Ultimately
// I worry there must be a better way of determining this without having a big
// try/catch around everything. Is there a way to query system capabilities?
this.device = new Device(this.direct3D, 0, DeviceType.Hardware, this.Handle,


IDirect3D9::GetDeviceCaps is what you want to use for this. Once you test for all the capabilities you can create a HEL (hardware emulation) device instead if they don't have hardware acceleration, but I can't imagine anyone trying to run any emulator on a system that doesn't have hardware acceleration.

Code: Select all

// I had a heck of a time finding a pixel format that wouldn't just crash here.
// Additionally, certain video cards did not "correctly" support this texture
// when it wasn't a power-of-two. I have forced the textures to power-of-two
// to attempt to support these scenarios. Is this normal?
this.texture = new Texture(this.device, textureWidth, textureHeight, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);


I'm pretty sure the pixel format needs to be the same as the desktops in windowed mode. It is normal for some cards to not support textures that aren't a power of two. I can't remember why, or which, but generally you want to stick to the power of two rule no matter what.

Later, I end up creating a triangle strip (with 2 triangles) to draw the bitmap to the device. I'm not sure if what I'm doing is overkill. I'm very curious to know if there's some other, more obvious mechanism for what I'm trying to do.


This really doesn't matter in my opinion. Whatever method you use to create the poly that you render to won't make much, if any at all difference in performance since your only creating a single rectangle to render onto anyway anyway. Direct2D (directx 10+) does the very same thing, create a poly to render to, and use an orthographic camera to do 2D. Direct2D just takes the tedium out of creating your own 2d D3D library. (Which most have already done anyway.)
incrediclint
Posts: 16
Joined: Mon Oct 31, 2011 6:22 pm

Re: DirectX use in 4DO

Postby incrediclint » Tue Nov 22, 2011 5:12 am

BTW, SwapFrameEvent is the same as FrameTrigger, but for non multi-task mode. Just gives an easy way to use multiple buffers. (Double/Triple buffering). It gets triggered for the same reason FrameTrigger does.. so you know when the frame is done in non multi-task.

Doesn't help performance wise on the xbox though :|
Johnny
Site Admin
Posts: 119
Joined: Thu Oct 27, 2011 1:50 pm

Re: DirectX use in 4DO

Postby Johnny » Wed Nov 30, 2011 4:01 pm

Thanks for the help incrediclint.

It's sobering to find that the solution I've coded up there isn't too crazy. It sounds like I won't need to make many changes there.

I noticed that the two triangles created a slight visual glitch. If you scale the 4DO window (and don't snap to clean increments), you can tell that there's a single pixel "slip" in the middle of the image down the hypotenuse of the triangles. Like a tectonic fault line (but no gap). This problem led me to believe I'm missing something fundamental.

Also, I'm wondering if HEL would work for the edge cases I'm attempting to support. Certain environments (like virtual machines or accessing a machine through RDP) don't support hardware acceleration, so I want to add an escape route for those systems. I would be able to introduce the basic, non-directx windows GDI solution. But, the code would be a lot simpler if I can just use the HEL instead. I don't know how the performance will compare to the GDI solution; the GDI solution was already struggling to keep up (mainly just due to the size of the software blits).
incrediclint
Posts: 16
Joined: Mon Oct 31, 2011 6:22 pm

Re: DirectX use in 4DO

Postby incrediclint » Wed Nov 30, 2011 4:48 pm

HEL performance is pretty horrid, but it might not actually be too bad since the GPU isn't really being stressed that much anyway. With the GPU only rendering a single poly with a single texture, the HEL might be fine.

I'm not sure how it would perform compared to GDI but I can't imagine it'd be worse.

Return to “General Forum”

Who is online

Users browsing this forum: No registered users and 5 guests