Quick and Dirty fps display

Started by
16 comments, last by zennehoy 22 years, 9 months ago
Does anyone have a quick and dirty way to write the fps onto a dx8 device? I just need it for debugging, and am looking for something simple that I can just comment out when I don''t need it anymore. I have code to get the fps into a word, but I need to write that to the display. THx.
Advertisement
When you say you can get the fps into a word, does that mean into a char array? If so, good, if not, well, use the itoa or some other such function. Once you have you lovely formatted string, you can use this for a quick and easy display information. Warning! It will probably drop your FPS anyway.. try writing it to a file or something once every 100 frames - maybe faster...


  int Draw_Text_GDI(char *text, int x,int y,COLORREF color, int size, char *font, LPDIRECTDRAWSURFACE7 lpdds, int underline){// this function draws the sent text on the sent surface // using color index as the color in the paletteHFONT my_font;		//the font informationHFONT old_font;HDC xdc; // the working dc//initialise the fontmy_font = CreateFont(size,0,0,0,0,0,underline,0,0,0,0,0,0, font);// get the dc from surfaceif (lpdds->GetDC(&xdc)!=DD_OK)   return(0);// set the colors for the text upSetTextColor(xdc, color);//select our custom fontold_font = (HFONT)SelectObject(xdc, my_font);// set background mode to transparent so black isn''t copiedSetBkMode(xdc, TRANSPARENT);// draw the text aTextOut(xdc,x,y,text,strlen(text));//restore the old fontSelectObject(xdc, old_font);//delete our fontDeleteObject(my_font);// release the dclpdds->ReleaseDC(xdc);// return successreturn(1);} // end Draw_Text_GDI  


That should suffice until you get your bitmap based text engine up and running ... you _are_ making a bitmap font engine... aren''t you???

cheers


ps this code works in DX7. I have no idea about DX8... but the process should be very similar.
I would recommend not doing it the way described above (no offense). The reason is that using the GDI to draw is very slow compared to other methods. And although it''s just for debugging, there''s no point in looking at artificially low rates. I believe the above method was indeed the quickest and dirtiest in DX7, but:

A texture based font is already implemented in DX8 - look at CD3DFont. If for some reason it doesn''t suit you, look at the source code for CD3DFont and reproduce it to fit your needs. Basically, it uses GDI (once) to draw a font to a texture and then uses that texture to do some fast rendering. Should be much faster than GDI.

Here''s a line of my code:
m_pPerformanceFont->DrawText(2, 0, D3DCOLOR_ARGB(255,255,255,255), m_strFPS);
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
Your could dump the FPS to a file (or your debug output file), or use D3DXSprite and a bitmap containing digits 0 to 9.
My D3DXSprite wrapper and app has the stuff to do this, download it at:

  Game Download  ZeroOne Realm

  Downloads:  ZeroOne Realm

Yup, I agree with CrazedGenius here - NEVER use GDI calls (or any code which does - some of the D3DX calls do) to display your framerate or anything else where you want good performance.

The problem is that when you GetDC for a surface, internally it calls Lock() - which flushes all pending rendering on the chip and also spins the CPU waiting for the chip to finish the flush.

After that it writes to the locked memory using the CPU - the locked memory is video memory so you''re going to be limited by the AGP bus speed, and to an extent by the cache. (Although VRAM does get the benefit of WC burst writes IIRC).

Even worse, often video cards store pixels in memory in a different order than you think (known as "swizzling" - re-ordering pixels to allow faster hardware access to memory) - when you lock the surface (or GetDC does) the data must be converted from the internal device format into one you can use (ie. into traditional RGB data). It must also be re-swizzled when Unlock()ed.

Worse still, the GDI text drawing routines are setup for scaling outline fonts, doing colour masking operations on them, handling output to other forms of DC (such as a printer), antialiasing etc - which isn''t good if you want to display a bitmap font fast

As you can guess all of this can kill performance - I''ve seen cases where a simple GetDC/TextOut/ReleaseDC took approximately 20fps off an app which was really running at 60fps (ie. the onscreen framerate counter said 40fps, I removed the GDI calls and used IPEAK to get the true frame rate and got 60fps!).

Best way by far is to do it yourself - draw a small font to a single texture (say 256x256) either offline or when the application starts up. Then when you need to draw the text draw a list of indexed screenspace quads (D3DTLVERTEX), one for each character you want to display - this will work very nicely with hardware acceleration, and give you the flexibility to use coloured fonts etc.

--
Simon O''''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Hmm I feel I must reply. First of all, zennehoy asekd for a quick and dirty way to show the fps. I think I qualified there:

quick: just copy and paste the code =)
dirty: it uses GDI

Anyway, I am at a loss to work out HOW GDI slows down my game, because, well, it doesn''t! I run my fullscreen DX7 game with quite a few GDI functions - arcs, ellipses, mathematically Complex stuff I would assume, and even that text function - but my frame rate remains over 100. I turn it off and get the same FPS. Wierd, hey? The thing that REALLY slows the game down is D3D7, when I render about 4000 triangles per frame.. but I wouldn''t think that would be too much, especially when they are small...
Thanks for the info.
I have been using GDI functions to display text before, but I have since moved on to D3D8, where it is not nearly as simple to get the DC as in DD8. SO! Thanks Freshya for the code, but I fear I won''t be able to use it. Unless someone comes up with a better idea, I''ll just dump the framerate into a file. Not as nice as having it on screen, but it will do. I really want to get the 3d graphics part on its way before I start work on a bitmap-based text routine.
To Freshya - Yes, for DX7, your method is perfect as a "quick and Dirty" way. My only explanation for your performance is that perhaps (???) you are doing things in such a way that your incremental cost of rendering the GDI stuff is negligible - if you are locking for the text drawing, then your shape drawing might not cost much more (???) For you D3D issues, try using MadOnion''s benchmark for High Polygon scenes. Their numbers are very close to what I get in my code. You can use them to see if you are doing something suboptimally. 4000 triangles per frame at 100 fps = 400000 tri/s, which seems really low depending on your hardware.

To zennehoy: Before writing files, look at the C3DFont class. It''s in the SDK, and basically takes 3-4 lines of code to use:

When you initialize:
//Create the font

Per Frame:
//figure out your frame rate
//display the rate - very similar to TextOut!

Cleaning up:
//destroy the font

Super easy!

Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
CrazedGenius: I doubt it''s my hardware that''s at fault (32mb GF2, 128mb RAM, 900mHz Athlon) but maybe the fact that they have vertex alpha, colour keyed textures, offset texture grabs, and each quad is part of a different triangle strip... that could be the problem ... although they are TL vertices so that should speed things up somewhat...
Aha.. semi-solved the problem:

Converted each particle to a fan, cuts down from 16 vertices to 6 (don''t ask me WHAT I was thinking when I wrote the routine...)

As you might guess.. there was a slight speed improvement...

Still, it shouldn''t have been running that slow, however inefficient a coder I may be =)

This topic is closed to new replies.

Advertisement