delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/20/04:05:02

From: Shawn Hargreaves <Shawn AT talula DOT demon DOT co DOT uk>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Style AND speed in C++? How? Please, I need some radical ideas on this one!
Date: Sat, 19 Apr 1997 16:38:51 +0100
Organization: None
Distribution: world
Message-ID: <AgZD$BALcOWzEwmr@talula.demon.co.uk>
References: <5j8ue0$8gg AT nr1 DOT toronto DOT istar DOT net>
NNTP-Posting-Host: talula.demon.co.uk
MIME-Version: 1.0
Lines: 88
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Jeff Weeks writes:
>Video_Template *video;
>video = new S3_driver;
>video.setmode();
[snip]
>I've tested this and the virtual functions seem to be exactly 2 times
>slower!  While style is a big concern, so is speed... so virtual
>functions are a no go I think.

Well, when I encoutered this problem in Allegro I opted for using
virtual functions: I can't see any other way to handle different
hardware architectures! Although I had to roll mine by hand rather than
using that nice 'virtual' keyword, as I was working in plain 'ole C :-)

Like you, I was initially quite concerned about the speed implications
of this, but profiling showed it to have a negligible impact on
performance. Versions of Allegro up to 2.1 used direct function calls,
and I only added the virtual function indirection in v2.1 to support the
new mode-X resolutions. On my 486-dx33, the change caused about a 5%
slowdown in the putpixel() function, which didn't concern me unduly as
such a tiny function is a useless thing to profile in any case. With
more complex routines like hline() and rectfill(), it was less than
quarter of a percent slower, and I couldn't measure any speed difference
with blit() and the sprite drawing routines. So I wouldn't worry about
it. When you say your virtual functions are 2 times slower, what are you
doing in these functions? Sure, the actual function call will take
longer, but proportional to the amount of time spent executing the code
inside the function, is that really such a significant thing?

Another trick I found useful is to seperate the main drawing routines
from the hardware bank switching code. The drawing code is called by
user programs, so it has to use the normal C calling convention, and you
will often be able to reuse the same functions on many different types
of hardware (in Allegro I have a regular 256 color putpixel function, a
mode-X putpixel, and I'm currently adding 15, 16, and 32 bit putpixels.
Apart from that, the same code works on any chipset). The bank switch
code, though, differs on every card, and is typically only called by
other of your own routines (eg. by the putpixel() function). It is a
rather different case, as it can frequently be called in tight,
optimised inner loops. I found it useful to implement my own calling
convention for the bank switch function. I store the function pointers
directly in my BITMAP structure, rather than relegating them to the
vtable along with all the other virtual functions, which wastes 8 bytes
of memory per bitmap but cuts out a level of indirection from the
function call, and I call them from asm with a specialised register
calling convention (line number in eax, bitmap pointer in edx, and the
bank switcher isn't allowed to clobber any registers except eax). It can
be a bit of a pain to work with these restrictions, but given the types
of places a bank switch is typically used, it gave some spectacular
speed improvements over using a regular C function...

>I should also mention that in time, Video_Template will have a static
>function called "autodetect" which will return a pointer to one of the
>drivers detected.  Is it then possible to do something like this:
>
>Video_Template *video
>;
>video = new Video_Template::AutoDetect();

Sure, you can do that. You'd just need to make the AutoDetect() function
a static member. I'd try something like:

In each derived class, have a static function along the lines of

    BOOL Detect();

Then your AutoDetect goes something like:

static Video_Template * Video_Template::AutoDetect()
{
    if (VideoS3::Detect())
        return new VideoS3;
    else if (VideoCirrus::Detect())
        return new VideoCirrus;
    else
        etc;
    
    return NULL;
}

Then your initialise code would just become:

    Video_Template *video = Video_Template::AutoDetect();


--
Shawn Hargreaves - shawn AT talula DOT demon DOT co DOT uk - http://www.talula.demon.co.uk/
Beauty is a French phonetic corruption of a short cloth neck ornament.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019