GPWiki.org
GPWiki.org
It is currently Wed Jun 19, 2013 4:32 pm

All times are UTC




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: dx7 drawtext normality?
PostPosted: Thu Apr 16, 2009 10:05 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
I've decided to redo my font engine, as I think it's slow and it's running the way I truely need it to. While building it out, I decided to do a base test of DT on a blank dx7 core engine. Using the Public FontBuffer As New StdFont for the font data.

This is a 800x600x16bit. I've noticed some weirdness which maybe just the way the dx7 drawtext functions. In the example below, nothing is running in the game loop except the FPS counter and the drawtext function to draw the attached. I know many ppl say, ignore FPS as a measure of speed, but how can you? 15FPS will produce a game that can not be played, so that alone is a measure of speed.

In this screenshot I have the following enabled.
http://img301.imageshack.us/img301/6144/33803421.jpg

FontBuffer.Bold = False
FontBuffer.Size = 9
FontBuffer.Name = UCase("Verdana")
msurfBack.SetFont FontBuffer

In this screenshot I have the following commented out.
http://img261.imageshack.us/img261/1276/60988484.jpg

'FontBuffer.Bold = False
'FontBuffer.Size = 9
'FontBuffer.Name = UCase("Verdana")
'msurfBack.SetFont FontBuffer

I've noticed a huge increase in FPS. If this is normal functionality, then I will just accept it and move on.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 16, 2009 10:45 pm 
Corpse Bride
User avatar

Joined: Tue Jul 01, 2008 11:44 pm
Posts: 2217
Location: England
It's good to do little tests like this imo. When you get a feel for the performance of certain chunks of code, it trains your intuition, so that in the future, you get to know how your program will perform before you've even written it.



So how often are those quoted bits being called? per character? per row? per frame? just once before the loop begins?

If it's seldom, then it may just be the slow rendering time of truetype fonts over bitmap fonts.

Otherwise, it may be that whenever the font is set, dx might spend a little time creating a bitmap font from the truetype. So the font only needs to be set when font is changed, not every time something is written.


But it is a surprising outcome for what are supposed to be state-of-the-art drawing methods.

_________________
I ain't pushing no moon buttons.


Top
 Profile  
 
 Post subject: Fonts slow
PostPosted: Thu Apr 16, 2009 10:46 pm 
Novice

Joined: Fri Jun 13, 2008 11:46 am
Posts: 6
I found the fonts terrible slow too in DirectX8.
So i ended up rolling a simple system for bitmapped fonts.
Researching the problem i concluded that part of the problem is that the GDI does the font rendering - which should also be the case in dx7.

_________________
DxIce Engine


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 16, 2009 11:51 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
The .drawtext method is called every loop. Here is the simple code to produce the above output. The setup above (setfont, etc) is called before the loop is even started, so it's a 1-time-config.

Code:

 Do While mblnRunning
 msurfBack.BltColorFill mrectScreen, 0 'clear the screen with black
 FPS 'get the current FPS
 
 A = "row,1,80,81,82,83,84,85,86,87,88,89,90,91,92" & _
 ",93,94,95,96,97,98,99,100,101,102,103,104,105,106," & _
 "107,108,109,-> Stop"
 For I = 1 To 50
 msurfBack.DrawText 0, I * 13, "* " & A, False
 Next I

 msurfFront.Flip Nothing, 0 'display the update
 DoEvents
 Loop



It really makes me sad that something as simple as this can cause a 3D card to crawl. My card is by no means state-of-the-art, but it runs doom3 pretty nicely with features turned on at 800x600.

I thought graphic cards had functions for displaying text, I appears the only way to get good speed is to go bitmap and even then, it's good practice to convert all the text that you will use commonly to textures instead of re-rendering it in real time.

Very disappointed...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 17, 2009 5:32 am 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
After Redesigning and coding a bitmap font engine from scatch. This is the results of the initial test. This is 800x600x32bit using a bare bone Dx7 engine. I have 3 sizes and the following chars are supported, I'm not adding any other support for now. The core engine runs around 1500FPS with no render coding.

I'm sad at the results. What I want to know, can someone post a similar result and FPS so I can see if this is valid or just worthless doing this? You don't have to do 3 different font sizes, but it would be nice to see 3 lines of the following chars. I just want to compare my engine to others doing the following test.

Using Custom Bitmap Fontsheet (major improvement over drawtext)
http://img246.imageshack.us/img246/9646 ... tscopy.jpg

Using DrawText (yuk 4x fps)
http://img15.imageshack.us/img15/8736/67074702.jpg

Using Custom Engine, full palette (2x fps)
http://img208.imageshack.us/img208/9646 ... tscopy.jpg

:(


Top
 Profile  
 
 Post subject: DrawText() is crap
PostPosted: Fri Apr 17, 2009 9:29 pm 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
Hey Neruos,

I ran into this issue a looooong time ago, and I remember quite vividly how frustrating this part of the development was. Best advice I can give you, is drop the DrawText effort, and move on to just drawing your own bitmapped font. As you've seen, it's by far the fastest drawing method available, even though it's a pain to implement.

Once you have your bitmap made (I would suggest a long row of characters), you can create an array that contains the x coordinates of the beginning and the end of each character in the bitmap. Draw all the text to a temporary surface and then draw that surface to your backbuffer, then flip. Best performance i've been able to get with any sort of text w/ vb + dd7.

You can improve performance by getting the size of the bitmap down as small as possible (cram the letters together) and use seperate bitmaps for different size fonts. This is the best way I've ever found to draw text in dd7. Annoying but it works.

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject: Re: DrawText() is crap
PostPosted: Fri Apr 17, 2009 9:43 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
Hey Neruos,

I ran into this issue a looooong time ago, and I remember quite vividly how frustrating this part of the development was. Best advice I can give you, is drop the DrawText effort, and move on to just drawing your own bitmapped font. As you've seen, it's by far the fastest drawing method available, even though it's a pain to implement.

Once you have your bitmap made (I would suggest a long row of characters), you can create an array that contains the x coordinates of the beginning and the end of each character in the bitmap. Draw all the text to a temporary surface and then draw that surface to your backbuffer, then flip. Best performance i've been able to get with any sort of text w/ vb + dd7.

You can improve performance by getting the size of the bitmap down as small as possible (cram the letters together) and use seperate bitmaps for different size fonts. This is the best way I've ever found to draw text in dd7. Annoying but it works.


The custom engine functions (does as you said) on that logic. In the screenshots above, that is all ran under the font engine (which is based on bitmap font palette file and a .xml that houses all the font details). The engine is currently processing 2256 letters (textures) at 2x something FPS.


Top
 Profile  
 
 Post subject: Re: DrawText() is crap
PostPosted: Fri Apr 17, 2009 10:21 pm 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
Cypher wrote:
Hey Neruos,

I ran into this issue a looooong time ago, and I remember quite vividly how frustrating this part of the development was. Best advice I can give you, is drop the DrawText effort, and move on to just drawing your own bitmapped font. As you've seen, it's by far the fastest drawing method available, even though it's a pain to implement.

Once you have your bitmap made (I would suggest a long row of characters), you can create an array that contains the x coordinates of the beginning and the end of each character in the bitmap. Draw all the text to a temporary surface and then draw that surface to your backbuffer, then flip. Best performance i've been able to get with any sort of text w/ vb + dd7.

You can improve performance by getting the size of the bitmap down as small as possible (cram the letters together) and use seperate bitmaps for different size fonts. This is the best way I've ever found to draw text in dd7. Annoying but it works.


The custom engine functions (does as you said) on that logic. In the screenshots above, that is all ran under the font engine (which is based on bitmap font palette file and a .xml that houses all the font details). The engine is currently processing 2256 letters (textures) at 2x something FPS.


I dont know anything about that engine, but mine could fill the screen with random letters at about 100FPS with nothing else being drawn. After the tile engine, the gui, the particles (very basic system), the sound effects, music, etc, the whole deal ran at about 50 fps on a low end machine compared to today's standards.

As others have said in previous threads, don't worry about FPS. Write out your game loop in segments

while ( game != null ) {

doInput();
doTiles();
doSprites();
doSoundFX();
doParticles();

}

that way, in the end you can profile each individual section and see where your bottlenecks are.

The best advice I have ever been given as a programmer: Get it to work. Then get it to work better.

Finish your game, then worry about performance issues. :-)

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject: Re: DrawText() is crap
PostPosted: Fri Apr 17, 2009 10:32 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
I dont know anything about that engine, but mine could fill the screen with random letters at about 100FPS with nothing else being drawn. After the tile engine, the gui, the particles (very basic system), the sound effects, music, etc, the whole deal ran at about 50 fps on a low end machine compared to today's standards.

As others have said in previous threads, don't worry about FPS. Write out your game loop in segments

while ( game != null ) {

doInput();
doTiles();
doSprites();
doSoundFX();
doParticles();

}

that way, in the end you can profile each individual section and see where your bottlenecks are.

The best advice I have ever been given as a programmer: Get it to work. Then get it to work better.

Finish your game, then worry about performance issues. :-)


The engine above does this.

Full screen fill up
http://img529.imageshack.us/img529/5184 ... scopyh.jpg


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 17, 2009 10:52 pm 
Corpse Bride
User avatar

Joined: Tue Jul 01, 2008 11:44 pm
Posts: 2217
Location: England
that font looks like the zx spectrums :lol

(that's a good thing btw)

_________________
I ain't pushing no moon buttons.


Top
 Profile  
 
 Post subject: Re: DrawText() is crap
PostPosted: Fri Apr 17, 2009 11:11 pm 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
Cypher wrote:
I dont know anything about that engine, but mine could fill the screen with random letters at about 100FPS with nothing else being drawn. After the tile engine, the gui, the particles (very basic system), the sound effects, music, etc, the whole deal ran at about 50 fps on a low end machine compared to today's standards.

As others have said in previous threads, don't worry about FPS. Write out your game loop in segments

while ( game != null ) {

doInput();
doTiles();
doSprites();
doSoundFX();
doParticles();

}

that way, in the end you can profile each individual section and see where your bottlenecks are.

The best advice I have ever been given as a programmer: Get it to work. Then get it to work better.

Finish your game, then worry about performance issues. :-)


The engine above does this.

Full screen fill up
http://img529.imageshack.us/img529/5184 ... scopyh.jpg


9 FPS, ouch. That's pretty bad. How does the logic in that engine run?

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 17, 2009 11:20 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Logic as such..

font.small.xml (houses all the font details and points to the font file)
font.small.bmp (256x256 texture of the fonts in 32bit)

Create & Initialize DX Core, Primary, Buffer
Run EngineFontInitialize() { parses .xml's, creates surfaces, etc }
Run EngineStart { main loop, calls EngineFontDraw(stuff) }

EngineFontDraw(stuff) {
based on "stuff", pulls the rects that match the keys from the surface and then draws each letter to the buffer.
}

thats it.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 17, 2009 11:38 pm 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
Logic as such..

font.small.xml (houses all the font details and points to the font file)
font.small.bmp (256x256 texture of the fonts in 32bit)

Create & Initialize DX Core, Primary, Buffer
Run EngineFontInitialize() { parses .xml's, creates surfaces, etc }
Run EngineStart { main loop, calls EngineFontDraw(stuff) }

EngineFontDraw(stuff) {
based on "stuff", pulls the rects that match the keys from the surface and then draws each letter to the buffer.
}

thats it.


Can you post the source for EngineFontDraw()? I'm assuming it takes in a string and figures out the bitmapped versions?

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 17, 2009 11:45 pm 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
neruos wrote:
Logic as such..

font.small.xml (houses all the font details and points to the font file)
font.small.bmp (256x256 texture of the fonts in 32bit)

Create & Initialize DX Core, Primary, Buffer
Run EngineFontInitialize() { parses .xml's, creates surfaces, etc }
Run EngineStart { main loop, calls EngineFontDraw(stuff) }

EngineFontDraw(stuff) {
based on "stuff", pulls the rects that match the keys from the surface and then draws each letter to the buffer.
}

thats it.


Can you post the source for EngineFontDraw()? I'm assuming it takes in a string and figures out the bitmapped versions?



Function Engine_Render_Font(ByVal tmpFontSize As Integer, ByVal tmpFontColor As Integer, ByVal TmpText As String, ByVal tmpX As Integer, ByVal tmpY As Integer, tmpRect As RECT, ByVal tmpKerning As Integer, Optional tmpCenter As Boolean)

Right now, for the full screen print, im just going thru all the letters per line.

Result = msurfBack.BltFast(tmpPad, tmpLine + 15, MyFontsSurface(FontSize.Small).fSurface, MyFonts(FontSize.Small, FontColor.fWhite).FontRect(I), DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT)

I = key I want


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 12:13 am 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
Cypher wrote:
neruos wrote:
Logic as such..

font.small.xml (houses all the font details and points to the font file)
font.small.bmp (256x256 texture of the fonts in 32bit)

Create & Initialize DX Core, Primary, Buffer
Run EngineFontInitialize() { parses .xml's, creates surfaces, etc }
Run EngineStart { main loop, calls EngineFontDraw(stuff) }

EngineFontDraw(stuff) {
based on "stuff", pulls the rects that match the keys from the surface and then draws each letter to the buffer.
}

thats it.


Can you post the source for EngineFontDraw()? I'm assuming it takes in a string and figures out the bitmapped versions?



Function Engine_Render_Font(ByVal tmpFontSize As Integer, ByVal tmpFontColor As Integer, ByVal TmpText As String, ByVal tmpX As Integer, ByVal tmpY As Integer, tmpRect As RECT, ByVal tmpKerning As Integer, Optional tmpCenter As Boolean)

Right now, for the full screen print, im just going thru all the letters per line.

Result = msurfBack.BltFast(tmpPad, tmpLine + 15, MyFontsSurface(FontSize.Small).fSurface, MyFonts(FontSize.Small, FontColor.fWhite).FontRect(I), DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT)

I = key I want


Ah, that's why. You're drawing hundreds of surfaces every frame redundantly. In an standard implementation, you're going to want to setup non-redundant drawing mechanisms, so that you only re-draw what needs to be re-drawn.

Second point; draw your text to a separate surface and hold that in memory so you can draw just that one surface to the back buffer when you need it. Things that you use often in your game, for example; the player's name. It's always going to be the same, so draw the player's name to it's own surface one letter at a time, and keep that whole surface with the entire player's name in memory. If you need to redraw that player's name at any point, just draw that one surface, not each individual letter.

In this example, try drawing an entire screen's worth of text to one surface, then draw that surface to the back buffer every frame, instead of each individual letter every frame. You'll see a nice boost to performance. Now expand on that. Draw a floating sprite over your text, and write an algorithm to determine what part of your back buffer you need to redraw. Then take that piece of your text surface, and blt that where it needs to go... now you are only drawing over pixels that need to be refreshed, and leaving the rest alone. THAT, will save you tons of fps to use elsewhere.

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 12:23 am 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
Ah, that's why. You're drawing hundreds of surfaces every frame redundantly. In an standard implementation, you're going to want to setup non-redundant drawing mechanisms, so that you only re-draw what needs to be re-drawn.

Second point; draw your text to a separate surface and hold that in memory so you can draw just that one surface to the back buffer when you need it. Things that you use often in your game, for example; the player's name. It's always going to be the same, so draw the player's name to it's own surface one letter at a time, and keep that whole surface with the entire player's name in memory. If you need to redraw that player's name at any point, just draw that one surface, not each individual letter.

In this example, try drawing an entire screen's worth of text to one surface, then draw that surface to the back buffer every frame, instead of each individual letter every frame. You'll see a nice boost to performance. Now expand on that. Draw a floating sprite over your text, and write an algorithm to determine what part of your back buffer you need to redraw. Then take that piece of your text surface, and blt that where it needs to go... now you are only drawing over pixels that need to be refreshed, and leaving the rest alone. THAT, will save you tons of fps to use elsewhere.


You are correct, there will be some text caching, but for sake of conversation (I know I'm drawing alot, I added the number some where around 2200 (8x8) sprites per loop), each of those had to change, then text caching is redundant. I will have to cache text, just based on the performance of this test, I can no use this method alone for displaying text.

I just want to get some acknowledgement that this method is the standard for filebased font textures. Before I move forward in the guts of caching and more logic. If there is another method of doing this in dx7, I'm open to it. But for now, I think this is as good as it gets. :(


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 12:28 am 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
If there is another method of doing this in dx7, I'm open to it. But for now, I think this is as good as it gets. :(


In the many years I have been toying with vb6 + dd7, I have found no other way that can provide a reasonable amount of performance. DrawText() is WAY too slow to be used for anything productive, imo. I used to use it merely as a debugging tool because it was easy to comment out. :-)

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 12:39 am 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
neruos wrote:
If there is another method of doing this in dx7, I'm open to it. But for now, I think this is as good as it gets. :(


In the many years I have been toying with vb6 + dd7, I have found no other way that can provide a reasonable amount of performance. DrawText() is WAY too slow to be used for anything productive, imo. I used to use it merely as a debugging tool because it was easy to comment out. :-)


I do the samething. :)

I'm just wondering, would there be a Dx8-Dx10 that will do the example thing of this thread but faster? File based font, I'm really not sure how much faster dx8-dx10 would do it? I mean, this is supposed to be at the card level, not the driver?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 2:24 am 
411 Operator

Joined: Tue Feb 21, 2006 12:32 am
Posts: 481
Location: California, USA
neruos wrote:
I do the samething. :)

I'm just wondering, would there be a Dx8-Dx10 that will do the example thing of this thread but faster? File based font, I'm really not sure how much faster dx8-dx10 would do it? I mean, this is supposed to be at the card level, not the driver?


I stopped using DirectX at 7, so I can't comment on other methods.

I don't know about getting down to the card level straight from your code... that defeats the purpose of abstraction layers (osi model). Your code interfaces with DirectX which interfaces with the hardware drivers which interfaces with the hardware. It doesn't really matter which part of the code you want to run on video hardware... it's up to the user's hardware to support that, not you. If I remember correctly, there is a way to force surfaces to load into video memory, as opposed to system memory... but I thought that all surfaces automatically try to load into video memory my default... can't remember. It's been awhile. :-D

_________________
The only difference between genius and psychosis is that society accepts the genius.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 18, 2009 2:46 am 
Ankle Nibbler

Joined: Sun Mar 22, 2009 10:55 pm
Posts: 130
Cypher wrote:
neruos wrote:
I do the samething. :)

I'm just wondering, would there be a Dx8-Dx10 that will do the example thing of this thread but faster? File based font, I'm really not sure how much faster dx8-dx10 would do it? I mean, this is supposed to be at the card level, not the driver?


I stopped using DirectX at 7, so I can't comment on other methods.

I don't know about getting down to the card level straight from your code... that defeats the purpose of abstraction layers (osi model). Your code interfaces with DirectX which interfaces with the hardware drivers which interfaces with the hardware. It doesn't really matter which part of the code you want to run on video hardware... it's up to the user's hardware to support that, not you. If I remember correctly, there is a way to force surfaces to load into video memory, as opposed to system memory... but I thought that all surfaces automatically try to load into video memory my default... can't remember. It's been awhile. :-D


You are right, I worded it incorrect, I mean.

The blitting is done at the card level (the driver just tells the hardware what to do, the hardware does the actual work). That is the point of directx, to put what I want into a langauge that any card can support as long as they meet the directx versions and my code uses that version.

More so, if I used D3D7 to draw a simple 100x100x100 cube and did the same on D3D10, the render time should be the same or near same (if both tests were on the same hardware).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group