Welcome! Log In Create A New Profile

Advanced

Display list proper form

Posted by dancinninja 
Display list proper form
November 30, 2010 07:04AM
I have never been able to get display lists to work. That changes today.

Here is how I build my display list (in my Player class, which represents the avatar on screen):

void Player::buildDisplayList(){
	
	static const u32 TEMP_SIZE = 16384;

	if(displayList)
		free(displayList);
	displayList = NULL;

	u8* tmpDisplayList = (u8*)(memalign(32, TEMP_SIZE));

	if(!tmpDisplayList){
		// PANIC!
		exit(1);
	}

	DCInvalidateRange((void*)tmpDisplayList, TEMP_SIZE);
	
	memset(tmpDisplayList, 0, TEMP_SIZE);

	GX_BeginDispList(tmpDisplayList, TEMP_SIZE);

	GX_ClearVtxDesc();
	GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);

	// Color info
	u8 r = 0x00;
	u8 g = 0x00;
	u8 b = 0xFF;

	GX_Begin(GX_QUADS, GX_VTXFMT_CLR, 24);		

		// Right now we're just rendering a box.

		GX_Position3f32(-1.0f,1.0f,1.0f);  
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,1.0f);	  
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,-1.0f); 
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,1.0f,-1.0f);  
		GX_Color4u8(r, g, b, 0xff);

		// ...

	GX_End();

	// Copy the temporary DL into our permanent display list

	actualDLsize = (GX_EndDispList()+31)&~31;

	displayList = (u8*)(memalign(32, actualDLsize));

	DCInvalidateRange((void*)displayList, actualDLsize);

	memcpy(displayList, tmpDisplayList, actualDLsize);

	DCFlushRange((void*)displayList, actualDLsize);

	// Delete the temporary display list
	if(tmpDisplayList)
		free(tmpDisplayList);
	tmpDisplayList = NULL;

}

...And here is how I call my display list:

void RenderEverything(){

	Mtx mv, rot;

	guMtxIdentity(mv);
	guMtxTransApply(mv, mv, player->pos.x, player->pos.y, player->pos.z);

	guMtxIdentity(rot);
	guMtxRotDeg(rot, 'x', player->az);
	guMtxRotDeg(rot, 'y', player->ay);
	guMtxRotDeg(rot, 'z', player->az);

	guMtxConcat(mv, rot, mv);

	GX_LoadPosMtxImm(mv, GX_PNMTX0);

	GX_CallDispList(player->displayList, player->actualDLsize);

}

This gives me a big 'ol black screen. If I replace the GX_CallDispList with the actual code that was put into the display list (the cube), then it renders just fine. I'm not sure what I am doing wrong. Thanks in advance!
Re: Display list proper form
November 30, 2010 07:50PM
It's a bit weird that you create the display list in a temporary array and then malloc more memory to duplicate it, but I'll assume you have your reasons.
What is GX_VTXFMT_CLR? I guess it's a custom define for one of the standard values?
Do the *VtxDesc functions work when put in display lists? I thought they just set some flags to signal that the hardware values should be updated when GX_Begin()/GX_Flush() is called... so they wouldn't be storing any data in the display list.
Re: Display list proper form
November 30, 2010 08:07PM
The big temporary array is due to the fact that I don't know how big my display list is going to be. So I make a big one, populate it, and copy over the results. The "GX_VTXFMT_CLR", I apologize for not explaining.


#define GX_VTXFMT_CLR    GX_VTXFMT1

// In the initialization code:
GX_SetVtxAttrFmt(GX_VTXFMT_CLR, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT_CLR, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);

I moved the GX_SetVtxDesc functions out of the display list, and I just call them right before I call the display list. I still get nothing. I checked the size of the display list, it's 416, so there's clearly SOMETHING in there. Does a display list mean that it's no longer direct? Meaning I can't use "GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);" or something? I have no idea.



Edited 2 time(s). Last edit at 11/30/2010 08:22PM by dancinninja.
Re: Display list proper form
November 30, 2010 11:00PM
You are passing 24 as parameter to GX_Begin, are you actually drawing 24 vertices before calling GX_End ? Because it's not the case in the code you posted, you only draw 4 (a 2D quad). I guess you just didn't copypasted all the code in your post but it does not harm to ask.



Edited 2 time(s). Last edit at 11/30/2010 11:05PM by ekeeke.
Re: Display list proper form
November 30, 2010 11:13PM
You are correct. I didn't want to clutter up the page with all that stuff. There are actually 24 vertices in the original code.
Re: Display list proper form
November 30, 2010 11:52PM
Have you tried using a single buffer (allocated with the max size) to store the display list and use it as pointer for the GX_CallDispList function, with the size returned by GX_EndDispList ? Maybe it's needing more than the returned size when executing the Display list...

Also, try removing the "memset" that is executed before the display list, I don't think GX function writes goes through the CPU cache so your "memset" might as well be done in cache and later erase what you have written during the display list setup. It's just an idea, might be irrelevant as I'm not 100% sure to understand how the cache works :/

On a general note, i'm not sure the way you are managing data cache while playing with the 2 buffers is correct:

DCFlushRange should be used when external controller is going to access RAM which was previously modified by CPU
DCInvalidateRange should be used when CPU is going to access an address that was previously modified by external controller.

In this case, it seems to me you should invalidate the FIRST buffer after having written the display list since the memset function could have cached that memory range again and when you copy it to the 2nd buffer, zeroes are copied from cache instead of reading the modified values in RAM.

Another possibility is that Display List functions are simply not correctly implemented in libogc, I remember this has already been discussed before but I don't know the general position on that subject.



Edited 1 time(s). Last edit at 12/01/2010 12:11AM by ekeeke.
Re: Display list proper form
December 01, 2010 06:15AM
Quote
ekeeke

Another possibility is that Display List functions are simply not correctly implemented in libogc, I remember this has already been discussed before but I don't know the general position on that subject.

I think this is the original thread - [forum.wiibrew.org]

I did try and use lists for static models a while back, I could never get them working either. I noticed Michael did have a workaround but it seems that wiki page has been deleted.
Re: Display list proper form
December 01, 2010 12:10PM
This problem was bugging me so I actually wrote some code and did some tests - that memset line is definitely your problem. If I put a similar line in my code I get a black screen, without it everything works as expected. So I can confirm that Display Lists definitely are working in libogc.

Edit: Here's the code I was playing around with, neheGX lesson4: [pastebin.com]



Edited 1 time(s). Last edit at 12/01/2010 01:02PM by tueidj.
Re: Display list proper form
December 01, 2010 06:36PM
ekeeke, tueidj, you two are absolutely right. Thank you so much! Everything works perfectly now!
Re: Display list proper form
December 02, 2010 09:12AM
By the way, as I see you're trying to get the maximum performance for your application, yoou should definitely start using Indexed data. It will reduce the size of your display lists and improve general system performance
Re: Display list proper form
December 02, 2010 08:20PM
technik, absolutely. I have a question about that, though. Would the indexing of data really affect the display list? I thought that the display list took care of packing everything that you put into it.

Also, and this may be a stupid question, can you use the index on a dynamic array? Since I'm reading everything in via xml files, I won't know everything ahead of time.
Re: Display list proper form
December 05, 2010 02:28AM
Say for example you were using indexed data for your colors; you would load an array with all possible colors onto the GX hardware (with GX_SetArray) and then when creating the display list you only need to specify 1 value (the index of the color you want) rather than the 4 specific color values. Less data = smaller display list size.

Your display lists will also be more reusable, since you can change the values in the arrays without having to recreate the lists (just remember to use GX_InvVtxCache when modifying the arrays).
Re: Display list proper form
December 05, 2010 03:19AM
I thought that display lists were more static than that. Being able to change the array (color!) would be awesome. I thought I had to pick one or the other, but I can have both? Sign me up. Thanks!
Re: Display list proper form
December 06, 2010 01:05AM
Basically, you have to create a display list that contains the indices instead of the data itself. Somewhere else, you create the array of data. And when you want to draw, you set the correct array and call the display list. This allows you to use the same display list for many objects in your game that use the same model but are in a different frame of their animations, for example.
Re: Display list proper form
December 23, 2010 02:10AM
I've hit another snag, and I'm wondering if it has to do with the display lists. Here is the complete function:


void Model::buildDisplayList(){

	if(displayList)
		free(displayList);
	displayList = NULL;

	u8* tmpDisplayList = (u8*)(memalign(32, TEMP_DISPLIST_SIZE));

	if(!tmpDisplayList) exit(1); // PANIC!

	DCInvalidateRange((void*)tmpDisplayList, TEMP_DISPLIST_SIZE);

	GX_BeginDispList(tmpDisplayList, TEMP_DISPLIST_SIZE);

	/////////////////////////////////////////////////////////////
	////// Temporary model information:
	/////////////////////////////////////////////////////////////
	static const u8 r = 0x00;
	static const u8 g = 0x00;
	static const u8 b = 0xff;

	GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
	GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
	//
	GX_ClearVtxDesc();
	GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
	GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
	GX_Begin(GX_QUADS, GX_VTXFMT_CLR, 24);          

		GX_Position3f32(-1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);

		GX_Position3f32(-1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);

		GX_Position3f32(-1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);

		GX_Position3f32(-1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);

		GX_Position3f32(-1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(-1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);

		GX_Position3f32(1.0f,1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,-1.0f);
		GX_Color4u8(r, g, b, 0xff);
		GX_Position3f32(1.0f,-1.0f,1.0f);
		GX_Color4u8(r, g, b, 0xff);

	GX_End();

	/////////////////////////////////////////////////////////////
	/////////// end temporary model info
	/////////////////////////////////////////////////////////////			
	/*
	Actual model loading goes here
	*/

			

	// Copy the temporary DL into our permanent display list

	actualDLsize = GX_EndDispList();

	displayList = (u8*)(memalign(32, actualDLsize));

	DCInvalidateRange((void*)displayList, actualDLsize);

	memcpy(displayList, tmpDisplayList, actualDLsize);
	DCFlushRange((void*)displayList, actualDLsize);

	// Clean up
	if(tmpDisplayList)
		free(tmpDisplayList);
	tmpDisplayList = NULL;
}

If I replace the call to GX_CallDispList with the "Temporary model information" section, it will the display blue box (with flickering problems but at least it doesn't crash). That is, if I don't call a display list and send everything directly to GX, it will work. This leads me to believe that the problem is in the display list. Thoughts?
Sorry, only registered users may post in this forum.

Click here to login