Feal87's Blog

Just another programming weblog.

Remake of ID3DX10Font / ID3DXFont

Posted by feal87 on June 1, 2009

Continuing from where I left at the previous post, I’ll talk about another necessary remake I’ve done for my game engine. As you probably know, the D3DX library contains other than the sprite drawing class, a text drawing class called ID3DX10Font / ID3DXFont. It is based over GDI and use the Sprite class for drawing the text.

As I have deleted the sprite class from my engine references thanks to the SpriteAlternative class, I needed an alternative for the text writing class. Another reason of the remake was that for unknown reason the results of the SAME identical text drawed with the DirectX9 and DirectX10 class was quite different in style.
I had quite a few ways to implement the class :

1) Using GDI/GDI+ create a texture with all the gliphs needed by the text I’m writing and write the characters one by one using different texture coordinates.
2) Using Precreated Bitmap Fonts
3) Using GDI+ to create the textures with the whole text needed and use a cache system to prevent useless recreation of the same texture.

The first method is the same as the basic class offered by D3DX, while it is quite performant, it use a LOT of CPU power (at least on my Core 2 Duo 2.00 ghz) and it is quite intricated (lots of directx calls).
The second method is the method most used by games all over the world, but it not very flexible. Having a different bitmap font for each type of size/style/font is nice if you have to create a particular game and stops there, but with an engine is better to give flexibility even at the cost of speed sometimes.
The third method, the one i choose, is VERY good for static text and still optimal for changing text. Other than that, this method have a very low CPU usage. (the graphics is generated once and just drawed the rest of the times just like any texture with the SpriteAlternative class).

After lots of brainstorming and work the FontAlternative class was born.

Font Alternative Class Diagram

Font Alternative Class Diagram

I’ve created 2 classes, the first, CachedText, is the class that contains the details of a text cached in the system, the second, FontAlternative, is the actual font class.
Let’s analyze the members of the two classes :

CachedText :

1) Colore – Color of the text.
2) Dimensioni – Size of the rectangle where i’m writing.
3) Font – Font using for the drawing. (System.Drawing.Font)
4) Text – Text to draw.
5) Texture – Texture ready to be drawed.

FontAlternative :

1) CacheTesti – A dynamic cache that contains a series of texts already drawed by the system and ready to be drawed again.
2) ClearCache – Clear the texts cache.
3) MeasureString – Return the size of the rect needed to draw a string with a certain font.
4) UnloadContent – Clear the cache and dispose of the various resources used. (it is executed on the various situation where the device is lost/reset etc…)
5) Draw – Search a text inside the cache. If not found it create a new cache entry and then draws it. If found it just draws it.
6) DrawCached – Draw a passed cached text directly.

Font Alternative Usage

Font Alternative Usage

Using the new class is pretty simple :

1) First we start the SpriteAlternative engine which this class is based on.
2) Check if we have the reference to the cached text.
3a) If no, we call the FontAlternative.Draw() that search in its cache for the text and if not found create a new cache entry and returns it.
4a) Save the cache reference returned from the FontAlternative.Draw() function.
3b) Draw using the FontAlternative.DrawCached() that draws directly the texture.
5) Close the SpriteAlternative engine.

The results from this change? Well, while the speed is not changed that much (0.070 ms gain over a 3,5 ms application), the CPU gain was massive (over 15% of less CPU power used by the same app) and now I have full control over my application. (the only thing i still use of the D3DX default class library is the effects framework (and i have plans for that :D))
I suggest anyone starting to create an engine to have a shot in these remakes because they will save you lots of headcache later on.

I still don’t know what we’ll talk next time, but I hope you’ll anyway look forward to it.
See ya 😉

Advertisements

12 Responses to “Remake of ID3DX10Font / ID3DXFont”

  1. derGhostrider said

    Hi!

    Do you offer your SpriteAlternative, CachedText and FontAlternative Classes for download?

    I am in need of a very fast way to write one value between 20 to 100 times on the screen.

    With DirectX 9 under WinXP my application was able to render more than 5000 frames per second.
    I created one Sprite and reused it.

    Since I switched to SlimDX to get my program running under Windows Vista and Windows 7 the framerate dropped to values between 1700 and 2000 fps.

    Today I changed from DX9 to DX10 because I hoped that it might speed the program up but it did not change anything at all.
    On the contrary: I had to stop using the sprite because when I try to use it the text is not visible anymore (?) and I really dont know why.
    So right now I am rendering with SlimDX and a “null” Sprite.

    text.Draw(null, string.Format(“{0:00}.{1:000}”, Sekunden, Millisekunden), new Rectangle(PosLeft, vertikal, Breite, Höhe), DX10.FontDrawFlags.Left, ColorToUInt(FontColor));

    When the number of texts rise the performance drops… 😦

    Any idea, help or tip would be highly appreciated.
    If your classes are faster than this plain method I would appreciate it very much if you could send them to me.

    • feal87 said

      Yep, my classes are faster than the common Sprite alternative on most case (and use less CPU), but rely heavily on my engine implementation and is pretty useless to post them.
      Try remaking them following my advice based on your engine, it should be an interesting and rewarding activity. (I doubt you can take more than 3-4 days to remake them)

      Anyway using null as parameter in the call you’ve shown makes the system use an internal sprite object slowing down the draw. (its better to have an unique Sprite class for your whole application)

      • feal87 said

        Ah another note, please remember that FPS are not linear.

        5000 fps = 0.012 ms
        2000 fps = 0.030 ms

        0.018 ms its not that big difference.

  2. derGhostrider said

    It’s pretty obvious that a unique sprite would speed things up, but this is not working for me because the text is not visible.

    Even if the absolute difference is not that big, the procentual difference is huge! For common tasks this does not matter at all, but I use my software for measurements and time is a critical parameter.

    Maybe I should try to migrate to OpenGL or unmanaged DirectX.
    SlimDX is “easy” but does not satisfy in terms of performance.

    The problem is that I am not a hell of programmer… I teached myself to use C# and to program DirectX just for this very special application. So right now I am pretty happy that there is “something” displayed by my program but I fear that I am not able to realize my own SpriteAlternative class in a reasonable time.

    Thanks for your reply. Nevertheless I’ll have to try to find another alternative for my program to speed it up again.

    • feal87 said

      SlimDX is nothing more than a mere wrapper over DirectX, the difference isn’t big in speed. I’ve said it again, but don’t take FPS as a parameter of comparing cause its a non-linear factor, but take the milliseconds needed to draw the scene (from Present to Present).

      But, make this test if you don’t trust me, if you try to increase the number of text showed in your app more and more the FPS-loss would be less, less, less, less until the “speed” of unmanaged DirectX would be pretty similiar to the SlimDX one (1-2 FPS of difference IMHO on a 60 FPS app, nothing more)

      P.S. All this is ASSUMING you are writing the same optimized code in unmanaged DirectX and SlimDX.

  3. derGhostrider said

    Well, the problem that I see is:
    – The first version of the program that was only usable on WinXP (without SlimDX!) was several times faster than the actual program. It ran only in a true full screen mode.
    – After I switched to SlimDX the performance dropped to 1/3 of the original speed. I had to use a full-screen-sized window instead of true full screen mode to render as I encountered non recoverable device lost scenarios.
    – Now I switched to SlimDX and DX10 so that I can set “.Windowed = false” again, but that does not have the same effect as it had on WinXP. I still need to create a Form to get a OutputHandle where the SwapChain renders to and the performance is not increased as it was on the old WinXP version. 😦

    – To sum it up: I want to regain the old performance or even surpass it by a little margin. The code itself is now better as it was in the past. So it should be possible to speed up this program to reach the performance the non-SlimDX Version on XP has.

    All I can find are examples that handle ALT-Enter events and set the “.Windowed = true” parameter to “.Windowed = false” but these examples always need to resize the form that is the rendertarget… That’s no real “fullscreen” mode. Or: It’s as bad as my solution already is.

    I don’t need any Form or Window. I don’t need the possibility to switch to a windowed mode. I just need a plain full screen display, blanked to my color of choice that displays some texts several thousand times a second.

    I am really a plain beginner and don’t even know how to express it better so that “good programmers” understand what I mean…
    Isn’t there a way to create a real “fullscreen” RenderTarget without a window or form?
    Right now it “feels” as if I am only drawing into a maximized frameless window. 😦

    When I tried to replace some of my “null”-Sprites with my unique Sprite, the framerate stayed constant! So there is something else that slows down the application and I can’t find the reason. :-/ *sigh*

    • feal87 said

      I’m going to out for an hour or two, when i’m back if I have some time I’ll answer you about the fullscreen mode that is an argument a little tricky. (Otherwise you’ll have to wait till tomorrow)
      Anyway yes, using windowed mode instead of fullscreen change the speed especially on low-speed applications (where the FPS is high cause of the non linearity of the FPS parameter) cause DirectX in FullScreen Mode Flip the swapchain instead of Blitting it. (in an example Arkanoid (created by me long ago) I have 700 FPS in windowed mode while 1050 FPS in fullscreen mode)
      Remember that if you use a big fullscreen window the backbuffer size will be bigger. The bigger the backbuffer, the more pixels needed to be drawn, the more slow the app will go.

      To be able to compare ALL THE PARAMETERS HAVE TO BE THE SAME. (including game loop and the rest of the code…I hope you’re not using the Sample Framework included in SlimDX. That’s not optimized for speed, but only for making simple demos. Read the game loop post for some ideas.)

      Anyway don’t worry, everyone started as plain beginner. Its question of time and dedication to get experience.

      • derGhostrider said

        If you are interested to take a quick look I may email (parts of) the source code to you. It’s somehow awful and almost all annotations are in German, but you might be able to see the “worst mistakes”… Right now I try to iron out some problems that are brand new:
        “protected override void OnClick(EventArgs e)” {…}
        doesn’t work any more…

      • derGhostrider said

        Small Update:
        Just clearing the screen, and drawing 1x Text (to show the Framerate) results in approximately 2500fps.
        That’s too low for almost “nothing” to do.

        And I still can’t figure out why my small end routine does not work anymore:
        protected override void OnClick(EventArgs e)
        {
        this.Dispose();
        this.OnClick(e);
        }
        It’s still the same and has not changed. No routine “protected override …” is loaded! Something has to be wrong here…

      • derGhostrider said

        Last Update for today:

        I figured out why the protected overrides did not work. Fixing this issue caused many other problems that I have to fix now as the tool isn’t working anymore.
        Sometimes it’s really frustrating to get the WHOLE program working.

      • derGhostrider said

        It’s me once again!

        I created my own eventHandler to catch key strokes and MouseClicks.

        All that is left is the “performance issue”.

        BTW: During the last 6 hours I optimized a lot but it did not improve anything in terms of speed.

    • feal87 said

      Upload an executable and the source of the app with only the FPS text and i’ll tell you if there are some problems. (Upload it here http://filebin.ca/ and post here the link)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: