|
Author Topic:   Function 'arrays'
Cthulhu
Member
posted April 10, 2000 02:50 PM            
I've thought replacing few if's with arrays of function pointers. For example:

if(screenBPP == 16)
alphablit16(sprite);
if(screenBPP == 24)
alphablit24(sprite);
if(screenBPP == 32)
alphablit32(sprite);

This can of course be done with switch-statement.

I've thought of creating array of (in this case 3) function pointers, and then calling one of them, index based on desired function.
Is this even possible? And more important which of these methods is the fastest?

This wasn't propably very clear...

Tarmo

IP:

CheshireCat
Member
posted April 10, 2000 03:28 PM            
If this is C++ code, you could use the stl map container for this:

In the initialization:
typedef void (*ptAlphaBlit)(Sprite *);
// alphaBlit is a map that stores 'ptAlphaBlit's keyed to 'uint's
std::map<unsigned int, ptAlphaBlit> alphaBlit;

alphaBlit[16] = AlphaBlit16;
alphaBlit[24] = AlphaBlit24;
alphaBlit[32] = AlphaBlit32;

//Replacing the if block
alphaBlit[screenBPP](sprite);

IP:

Bryan T
Member
posted April 10, 2000 03:52 PM            
The std::map method is good for large sets of mappings, but for 3 it seems overkill. There's a lot of overhead in a map lookup, (depending on its implementation). Probably a lot more than three IF statements, or one SWITCH.

For the three function example, if all sprites are the same depth, I would just do a switch.

If each sprite differs, I would store a function pointer in the sprite's structure:

(for C)
struct {
... Sprite data
void (*Blit)(sprite *);
};

(for C++)
Use a pure virtual on the base class. Overridden by three subclasses (sprite16, sprite24, sprite32).

Then call the function on the sprite:
(for C)
sprite->Blit( sprite );

(for C++)
sprite->Blit();

--Bryan

IP:

Bryan T
Member
posted April 10, 2000 04:05 PM            
(Duh! Bryan, READ the post first...)

Sorry, I thought it was your sprites that had different depths. There's no reason to use any IF or SWITCH statements here at all. During program launch, check screen depth and set a global function ponter for the Blit() function.

During the draw, there is never a screen depth change, so there is only ever one Blit() function to call. When the user requests a depth change, just change the single Blit() to point to the right one.


// Globals
void (*Blit)(sprite *);

// Main Func
main() {
...
switch(screenBPP) {
case 16: Blit = alphablit16(); break;
...
}
}

draw() {
...
(*Blit)( sprite );
...
}

Something like that.. the compiler installation in my head failed (Microsoft products!) so the syntax may be wrong.. This would be the fastest method possible to allow for dynamic screenBPP switching.
--Bryan

IP:

CheshireCat
Member
posted April 10, 2000 04:14 PM            
I suppose the screen depth probably isn't going to change between sprites, is it? =]

Although it should be:
Draw(){
Blit(sprite);
}

No need for the indirection operator.

IP:

Cthulhu
Member
posted April 11, 2000 08:14 AM            
Ok, so sprite blitting was a bad example. I actually used single function pointer for blitting in my past 2d engine.

Let's say I have sprite blitting function using 3d hardware, drawing textured 2d polygons. Now I want to have huge amounts of different blit methods (normal, color-keyed, alpha-blended, additive, subtractive, mirror, flipped, rotated, whatever). Now I wouldn't want to use dozens of if:s every call.

I code in c++.

IP:

Bryan T
Member
posted April 11, 2000 10:57 AM            
Same techniques apply... If there are a "Huge number" and they are switched upon rather randomly, the "map" method is a good one. If there are less than 10 or so functions, a "switch" is going to be faster. Depends on your system and compiler.

And yes, both of these are faster than a series of "if" statements. Optimization of this level can only improve performance by about 20%.. you might spend your time looking at algorithmic improvements before approaching details at this level.

The fastest method would be to meta-optimize. Choose a method of texture drawing or a series of 3D calls which (if passed correct parameters) will give all the desired effects.

Such a function would level the playing field: the "hardest" and "easiest" drawing would take roughly the same amount of time, evening out your overall frame rate. Then any optimization applied to this single function affects the entire application evenly (and is worth the extra trouble).

Not sure if that applies to what you're trying to do though. It also strikes me as odd that you would want to blit textures in a 3D game..?

--Bryan

IP: