Feal87's Blog

Just another programming weblog.

Posts Tagged ‘ARGBtoRGBA’

Interoperability between DirectX9 and DirectX10

Posted by feal87 on May 27, 2009

One of the first things i’ve looked up when I was starting to write my game engine was to check what the actual APIs had to offer and if a MultiAPI engine was a reasonable or useful idea. (I’ll make a separate post to explain how I designed the engine)

After some searching, I decided that for compatibility sake I had to support not only the latest bleeding edge technology DirectX10, but also DirectX9. This because DirectX10 for several reason was not available on Windows XP systems.

Well, the dice was thrown and the developing began at steady rate, after a week or two I stumbled on a particular situation that I want to share with everyone hoping that it may help someone who is going through the same problem.

At that time I was developing a test game, the classical remake of Arkanoid in 2D that I think everyone do as first test project. While the main engine was working, I had to choose what and how to draw the objects on the screen. The classical arkanoid is divided basically in 3 distinct areas. The player, the ball and the bricks. 

Pong2D Screenshot
Pong2D Screenshot

While the first two posed no problem and could be drawed stand-alone, the bricks posed some problems.
DirectX is an API built to take advantage of large stacks of objects drawn together with a single Draw call. Doing 120 different draw call for the bricks (the level area is 15 bricks as width and 8 bricks as height) was quite overkill and would have damaged the performance of a, otherwise, so simple game. The idea I developed was to have a big texture to contains all the bricks and update the texture each time the status of the bricks changed. (updating obviously only the part changed)

Well, the surprise (and the reason of this post) come after developing everything and starting the test phase.
While in DirectX9 mode the game worked fine, in DirectX10 mode something strange occurred. After the first update of the texture, the color of the bricks changed completely while maintaining their structure… (The blue become red and some other changes)

After some debugging I found out that DirectX10 DOES NOT support ANY raw format supported by DirectX9 for texture. While DirectX9 used a format ARGB, DirectX10 (or well, DXGI) supported only RGBA. Also, the System.Drawing.Bitmap class (based over GDI+) i was using to update the texture was no more good as it support only ARGB too.

How to go around this problem? There was three way to go around this problem :

1) Convert (swirl) the data on the CPU before launching the update of the texture and retaining this way all the old code.
2) Convert (swirl) the data before drawing on the GPU via pixel shader.
2) Create a new class that import and manages the textures differently between DirectX9 and DirectX10 while maintaining a common face to the framework.

While the first idea was quite fast to develop it was tremendously SLOW (to update a 720×400 image it took 5 ms using unsafe pointers and over 12 ms with Marshalling) so it was discarded right away.
The second idea was discarded right away too because at that time I was still using the default Sprite interface that does not allow personal shaders instead of a textured-quad solution. (I’ll return on this on another post)

Leaved with no choice I programmed the third choice and the BitmapAlternative class born anew.

BitmapAlternative class diagram
BitmapAlternative class diagram

The BitmapAlternative class is basically a class that permits draw and management of images in either ARGB or RGBA format. The main point of making this class was to offer a single abstract way to get the texture data and update safely and I think it is the best solution to cover this kind of problem. 

Here is is a short peek at the actual code of the class (only the contructor and the members)

public class BitmapAlternative
{
    public Int32 Width { get; set; }
    public Int32 Height { get; set; }
    public Int32 Stride { get { return Width * 4; } }
    public byte[] Data;
   
    public BitmapAlternative(Bitmap source)
    {
        Width = source.Width;
        Height = source.Height;
        #if DX10
           Data = ImageFunctions.ARGB32ToABGR32(source);
        #else
           Data = ImageFunctions.GetBytes(source);
        #endif
    }
}

The moral of this story? Well, there is no moral. 😀 
I just wanted to tell a story and hopefully save some people time figuring out and trying various ways to interoperate  DirectX9 and DirectX10 while using textures.

Ferreri Alessio

P.S. I heard that in the next DXGI 1.1 there will be support in DirectX10 for the plain old DirectX9 texture format. Maybe they found out about their error? 😉

Advertisements

Posted in General | Tagged: , , , , | 1 Comment »