Improving graphics load time...

Started by
14 comments, last by The Frugal Gourmet 21 years, 6 months ago
Not to beat a dead horse, but I have to question your current methodology. How are you loading the graphics? How many megabytes of data are we talking about? How many seperate files? Even a dozen megabytes should load in a split second... I suspect that you might be doing something wrong here. If that is the case, then it makes more sense to fix this problem than to spend time coding up a work-around... it might be very easy to fix.
Advertisement
quote:Original post by Pyabo
Not to beat a dead horse, but I have to question your current methodology. How are you loading the graphics? How many megabytes of data are we talking about? How many seperate files? Even a dozen megabytes should load in a split second... I suspect that you might be doing something wrong here. If that is the case, then it makes more sense to fix this problem than to spend time coding up a work-around... it might be very easy to fix.


A dozen megabytes in a split second? Wow. I''m definitely not getting that. That sounds very impressive to me.

There are around 20 sprites, each with from 48 to 100 or so frames (depending on the number of frames needed to smoothly animate that item). This makes for about 60 MB of essential sprites loaded into memory up front.

There are some others which are loaded and unloaded as the game goes on now (ambience art, particularly), which is additional, but it''s never more than 10 MB at a time...

Maybe I''m doing something wrong. Here is the code that loads a .TGA file.


  bool PictureSurface::init(char *pFilename){	USHORT	w = 0;	USHORT	h = 0;	FILE*	pFile = fopen(pFilename, "rb");	assert(pFile != 0);    fseek(pFile, 2, SEEK_SET);        char c = fgetc(pFile);	fseek(pFile, 0x0c, SEEK_SET);	fread(&w, 2, 1, pFile);	fread(&h, 2, 1, pFile);	m_width = w;	m_height = h;    long ret = 0;    fseek(pFile, 0, SEEK_END);    long fileLen = ftell(pFile) - 0x12;        UCHAR *pRaw = new UCHAR[fileLen];    	// Skip over bytes for BPP and alpha bits (Mmmmm... Alphabits)	fseek(pFile, 0x12, SEEK_SET);    fread(pRaw, fileLen, 1, pFile);        fclose(pFile);        m_pData = new ULONG[m_width * m_height];        if (0x0a == c) // compressed tga    {        UCHAR* pRawIndex = pRaw;    	    ULONG* pPtr = m_pData;	    long	count = 0;	    long	value = 0;	    long	c = 0;	    long	reps = 0;	    // BEGIN PARSING tga data	    while ((count < (m_width * m_height)) && (!feof(pFile)))	    {		    value = 0;		    c = *(pRawIndex++);		    reps = (c & 0x7f) + 1;		    if ((c & 0x80) != 0)		    {		        value = (ULONG)(*((ULONG*)pRawIndex));    		    pRawIndex += 4;			    for (long i = 0; i < reps; i++)			    {				    *(pPtr++) = value;			    }		    }		    else		    {			    for (long i = 0; i < reps; i++)			    {				    (*pPtr) = (ULONG)(*((ULONG*)pRawIndex));				    pRawIndex += 4;				    pPtr++;			    }		    }		    count += reps;	    }    }    else    {        ULONG totalBytes = m_width * m_height * 4;        memcpy(m_pData, pRaw, totalBytes);     }            delete [] pRaw;    	DDSURFACEDESC2	ddsd;	HRESULT			ddrval;	memset(&ddsd, 0, sizeof(ddsd));	ddsd.dwSize = sizeof(ddsd);	ddsd.dwWidth = m_width;	ddsd.dwHeight = m_height;	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;	ddrval = g_pDD->CreateSurface(&ddsd, &m_pSurface, NULL);    restoreBitmap();        return true;}  
Co-creator of Star Bandits -- a graphical Science Fiction multiplayer online game, in the style of "Trade Wars'.
From your code it looks like you''re loading as fast as fread can go. Doing a single block read on the file. The only faster way would be to use the OS specific file access functions ( for win32 that would be CreateFile for example ), compact the multiple files into a single file, or use a compressor such as zlib or lzo, which have good decompression times and fair compression.

Good Luck!

-ddn
How about packing everything into one file, and mmap()ing it?
You get demand loading/unloading for free, and it's fast+simple.
Depending on your images, you may also want to RLE or LZ compress individual frames.

/* edit: typo */

[edited by - Jan Wassenberg on October 2, 2002 6:38:17 PM]
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
For one, use CreateFile/ReadFile as someone pointed out, if this is windows.

60Mb does sound like quite a bit of graphics though... How long does it take exactly? If I were to guess, I''m betting that 60Mb worth of files could be opened with a simple CreateFile/ReadFile routine in 1000-2000ms, assuming it wasn''t made up for 10,000 files. Maybe the real delay is somewhere else?

Just for experimentation sake, try opening and reading all of the files in a simple console app (or a Win32 app) that does nothing but read the files.... ?
You will get better throughput from the disk if all the data is in the same place on the disk, rather than in several files which may be fragmented. If you need separate files, you could use something like a zip file which packs them all together, allowing your disk to work at close to optimum speed.

Has anybody ever tried something weird and ugly, such as: using a single file pointer for all your loading, and after you load the data from the disk and are about to translate it, call fclose as usual but then call fopen on the next file you are about to read... that way, maybe the disk cache can be filling up with the next graphic while you are processing the current one.

I wouldn''t recommend this unless you really need the improvement, though... if there even is an improvement, of course.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

This topic is closed to new replies.

Advertisement