Precompute Display List Size

Post Reply
figgles
Posts: 5
Joined: Thu Jun 30, 2011 8:40 pm

Precompute Display List Size

Post by figgles » Fri Jul 01, 2011 8:31 pm

Short story: I'd like to precompute the size of the display list so it is always the appropriate size given a static set of vertices and their format. The display list contains only vertex data, no state changes. I can't find any documentation on the proper way to compute a display list's size, so I'm asking here.

I've read that GX_EndDispList() will return the actual size of the display list, which is then passed on to GX_CallDispList(). So far, so good, but it can return 0, indicating that the display list was too small. Since I know how many vertices and all of the attributes and their sizes, I'd like to precompute the size of a display list so that it will never return 0, but not overallocate by blindly just allocating large chunks memory or "guess" the size and redo the display list until it is the right size, etc.

Just by reading libogc/gx.c, I think the following functions have the following byte sizes when placed in a display list:

GX_Begin(): 3 bytes
GX_End(): 0 (no-op)
GX_Position3f32(): 12 bytes (3x 32-bit floats)
GX_Position2f32(): 8 bytes (2x 32-bit floats)
... follows same general pattern based on datatype ...

I see "the display buffer should be at least 32 bytes larger than the maximum expected amount." Ok, so size += 32. Then, is the appropriate formula:

displayListSize = vertexSize * vertexCount + 32 + 3

...where vertexSize is the size of all of the per-vertex attributes (position, color, texcoords, etc)?

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: Precompute Display List Size

Post by tueidj » Tue Jul 05, 2011 5:31 am

Rather than calculate it manually, run it once with a large preallocated list and check the size returned by GX_EndDispList. Then reduce the preallocated size to match.

figgles
Posts: 5
Joined: Thu Jun 30, 2011 8:40 pm

Re: Precompute Display List Size

Post by figgles » Fri Jul 08, 2011 12:35 am

Eh, I'd rather not playing guessing games. The GameCube has 24MB of RAM, and I don't want to fragment the heap unnecessarily. In fact, I'd like to have a fixed region of memory, say a few MB, and use that solely as a geometry cache in a streaming engine architecture. This means I will make 1 call to malloc() and then none after it. Because I would be managing the memory myself, I would need to know the size of a display list ahead of time to see whether I need to evict geometry from the cache or simply pick a region.

I've found that the above equation nearly works, but modifying it so it rounds up to the nearest 32 bytes seems to do it, i.e:

Code: Select all

guessSize = aboveEquation();

guessSize = (guessSize & 0x1F) + 32;

Still, this "just works" -- it isn't based on any documentation or hardware probing, just an absolutely random guess based on the hardware's love for 32-byte aligned/multiple buffers. I wish there was more information about simple stuff like this -- the API is cryptic enough as is.

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: Precompute Display List Size

Post by tueidj » Mon Jul 11, 2011 7:37 am

I don't think you understood what I meant. If your display lists are static, run your program once to find the required size then hardcode that size into the source and recompile. This takes the guesswork out of manually counting the byte size of the static lists.

ccfreak2k
Posts: 14
Joined: Sat Mar 06, 2010 1:11 pm

Re: Precompute Display List Size

Post by ccfreak2k » Sun Aug 14, 2011 8:02 am

figgles wrote:I've found that the above equation nearly works, but modifying it so it rounds up to the nearest 32 bytes seems to do it, i.e:

Code: Select all

guessSize = aboveEquation();

guessSize = (guessSize & 0x1F) + 32;

Still, this "just works" -- it isn't based on any documentation or hardware probing, just an absolutely random guess based on the hardware's love for 32-byte aligned/multiple buffers. I wish there was more information about simple stuff like this -- the API is cryptic enough as is.
Yes, the final display list buffer needs to be rounded up to the nearest 32-byte boundary. Pretty much any access by the GP to main memory needs this alignment, so you'll see it often. Also make sure your buffer gets flushed out to RAM.

mtheall
Posts: 210
Joined: Thu Feb 03, 2011 10:47 pm

Re: Precompute Display List Size

Post by mtheall » Sun Aug 14, 2011 7:22 pm

figgles wrote:I've found that the above equation nearly works, but modifying it so it rounds up to the nearest 32 bytes seems to do it, i.e:

Code: Select all

guessSize = aboveEquation();

guessSize = (guessSize & 0x1F) + 32;
This is totally wrong. guessSize will always be between 32-63 with this code. I think you're looking for this to round up to the next 32-bytes-alignment:

Code: Select all

guessSize = aboveEquation();
guessSize = (guessSize + 0x1F) & (~0x1F);
However, this is only to give you the smallest size that is a multiple of 32 and fits the original guessSize. If you need to actually align the memory to 32 bytes, then it'd be something like this:

Code: Select all

guessSize = aboveEquation();

char* myFreeablePointer = malloc(guessSize + 32);
char* myAlignedPointer = (myFreeablePointer + 0x1F) & (~0x1F);
Now you will have two pointers: myFreeablePointer is what you will pass to free() to clean up the allocated memory. myAlignedPointer is the start address which is aligned to 32 bytes. The allocated memory is large enough that myAlignedPointer+guessSize does not go past the end of what was allocated.

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: Precompute Display List Size

Post by tueidj » Fri Aug 19, 2011 6:03 pm

The easier way to get aligned memory is to use memalign instead of malloc.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests