[Solved] Textures to VRAM

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

[Solved] Textures to VRAM

Post by skistovel »

Hello!

I 've have started porting NeHe's Tutorials for the PSPGU and was wondering of how can I assign a texture to the VRAM? I made a search but no similar posts appeared (if there is one already, i am sorry, but didn't find it..)

If you are interested about the tutorials (and with it the code I use..) you can find the here:

http://www.psp-programming.com/code/ind ... rt-lesson1
http://www.psp-programming.com/code/ind ... rt-lesson2
http://www.psp-programming.com/code/ind ... rt-lesson3
http://www.psp-programming.com/code/ind ... rt-lesson4
http://www.psp-programming.com/code/ind ... rt-lesson5
.. - will try to port them all -

I just found out that ps2dev had a wiki too..

Thank you for your time!
Last edited by skistovel on Sun Jul 23, 2006 1:49 pm, edited 1 time in total.
User avatar
ReKleSS
Posts: 73
Joined: Sat Jun 18, 2005 12:57 pm
Location: Melbourne, Australia

Post by ReKleSS »

What exactly do you mean by "assign"? If you want to place a texture from system ram into vram, use sceGuCopyImage. If you want to set a texture to use from either vram or system ram, use sceGuTexImage.
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

Post by skistovel »

Yes, I saw the "sceGuCopyImage" function, but looking at the provided example I was a bit confused. How do you call bind the texture afterward?
Would you still use the variable name? Or do you provide a different variable for the vram placed texture?

the example i say is that:

Code: Select all

sceGuCopyImage(GU_PSM_8888,0,0,480,272,512,pixels,0,0,512,(void*)(((unsigned int)framebuffer)+0x4000000))
I dont understand the last parameter (void*)(((unsigned int)framebuffer)+0x4000000))
User avatar
ReKleSS
Posts: 73
Joined: Sat Jun 18, 2005 12:57 pm
Location: Melbourne, Australia

Post by ReKleSS »

That last argument, the address of the framebuffer and then some, is where you're dropping the image into. Pass that address to sceGuCopyImage, and don't forget to sceGuTexSync() before you try to draw using it.
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

Post by skistovel »

I am still not sure what exacly this function does, I suppose that somehow it moves the data to the video memory, but I didn't see any difference in speed!

In my head I imagined that it would create a new allocation in video memory and would copy the data there and so you would be able to free the data from the main memory afterwards. It seems I am wrong..

Thanks for the help anyway! Appreciate the quick reply!
User avatar
ReKleSS
Posts: 73
Joined: Sat Jun 18, 2005 12:57 pm
Location: Melbourne, Australia

Post by ReKleSS »

There's no memory management provided for the graphics memory. It's up to you how to handle that. I think somebody wrote a basic dynamic memory allocation thingo for vram, you might want to search for it. sceGuCopyImage just does the transfer faster than if you were to do it on cpu, and also means you can use the cpu time for more important stuff.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

The sceGuCopyImage function is nothing more than it's name tells - a simple hardware blitter, copying from source (7th param) to dest (last param).
As said already, the gu does not handle vram allocations and it also does not provide a texture manager as openGL does. It's all up to you to load textures into vram and keep them there. It's quite a demanding to code a texture manager, since the VRAM is pretty limited (2MB, and only 1.2MB for textures in 16bit mode with doublebuffering+zbuffer, 600kb in 32bit mode). I have just some time ago started to working on one myself and it's nearly finished, though I'm still thinking about better ways to handle the cases.
Most likely, you're already best setup if you just transfer every texture you need to VRAM without much worries for keeping as much textures as possible as long as possible in VRAM, since the transfer speed accounts for the lack of memory.

I have written the vram mmu mentioned by ReKleSS. You can get the current version here: http://www.fx-world.org/download/valloc101.zip
It provides you with alloc, free and realloc functions on VRAM. You need to allocate your framebuffers and zbuffer with this to correctly work with offscreen textures, since else it doesn't know which parts are already used.
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

Post by skistovel »

Thanks a lot Raphael, I will try once more, to see if it actually worths the hassle to move the textures to video memory (if the speed is not increased dramatically I see no point..). Although its always useful to keep your most used texture maps (of your main character example) somewhere fast!

Just to make sure, in my image loader function, instead of malloc, i replace it with valloc and that should be enough? Do I still need to use sceGuTexSync()?

Also, in case you have any experience; I mentioned on my first post that I recently started porting nehe's tutorials. Reaching lesson 9 ( a simple particle system ), when the particle number increased more than 20, artifacts started appearing on the textures. The bigger the number of stars the bigger the space the artifacts took on the quads..
Is that because the texture was on the main memory and had to read it so many times per frame?

The code is here, if u want to take a look: http://www.skistovel.2plans.com/psp/Lesson8.rar
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

skistovel wrote:Thanks a lot Raphael, I will try once more, to see if it actually worths the hassle to move the textures to video memory (if the speed is not increased dramatically I see no point..). Although its always useful to keep your most used texture maps (of your main character example) somewhere fast!
As long as you have some few textures which are heavily used, it does make much sense to keep them in VRAM all the time (speed difference, depending on texture size, is starting from double speed upwards). For other cases it's ok to just transfer the texture to VRAM each time you need it. As I said, the transfer speed (~150mb/s) makes up for the lack of VRAM.
Just to make sure, in my image loader function, instead of malloc, i replace it with valloc and that should be enough? Do I still need to use sceGuTexSync()?
You could do that, yes, but I wouldn't recommend that way. As long as it's your only texture used and you don't swizzle it, this might be ok, but if you have more textures or want to swizzle them, better load your textures to system ram, and then either do a swizzled upload or in the latter case from above swizzle them in sysram and upload every frame.
SceGuTexSync() is needed when you upload a texture to VRAM and part of that memory is still in texture cash (which you won't know until you get some wrong texture artifacts). So just call it after each sceGuCopyImage and you're fine.
Also, in case you have any experience; I mentioned on my first post that I recently started porting nehe's tutorials. Reaching lesson 9 ( a simple particle system ), when the particle number increased more than 20, artifacts started appearing on the textures. The bigger the number of stars the bigger the space the artifacts took on the quads..
Is that because the texture was on the main memory and had to read it so many times per frame?
The code is here, if u want to take a look: http://www.skistovel.2plans.com/psp/Lesson8.rar
No, the number of times you use a texture is meaningless, since the gu just directly reads from the specified memory address. If that address is in sysram, it will slow down those reads quite frankly, but other than that have no influence.
Your problem was that your commandlist was too short to hold much more than 20 of your stars. Increase it to somewhat much more than 1024bytes, especially if you want to extend your drawing code with models and other stuff. Actually, some 100 or 200kb statically allocated memory won't hurt your program, but get you on the safe side ;)

And as a sidenote:
I noticed you did something like that:

Code: Select all

fpsDisplay = (char*) malloc( 20*sizeof(char));
	fpsDisplay = "FPS: calculating";
which afaik is generally not good, since the = "..." assignment, does not copy the content to your memory pointer, but assigns the memory location of the static string to your pointer, thus overwriting your dynamic allocated pointer address which is lost then.
I wonder however, why the free( fpsDisplay ); statement at the end then doesn't crash the application, since it should try to free memory which wasn't allocated by malloc, but maybe the compiler is smart enough to make up for your static assignment from above.
Well, I'd just outcomment that second line from above, since you generate your fps string every time anyway, so it makes no difference.
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

Post by skistovel »

Code: Select all

fpsDisplay = (char*) malloc( 20*sizeof(char));
fpsDisplay = "FPS: calculating";
That line actually, it was from crashes I had on my earlier attempts. I used to have fpsDisplay as a normal char array of 20, which i added the # of frames using the sprintf call at the fps() function.

I was drawing a few triangles and was fine, then i decided to add a cube. And then I though lets have them rotate with different values, different axis. Suddenly psplink crashed, again and again - running it from the VSH displayed a "drugged up" double screen with washed out colors. I found after many recompiles that the sprintf line was the root of all evil. So I tried everything .. At a point it worked and forgot to check it again!
your commandlist was too short
Well, THAT - I didn't expect! PSP had crashed on me saw many times the past 3 days, that since it was running it didn't occur to me at all that it might be the display list size.. Anyway,

Thanks again the valuable info & you patience -to read my code-, you have been a great help!
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

skistovel wrote: That line actually, it was from crashes I had on my earlier attempts. I used to have fpsDisplay as a normal char array of 20, which i added the # of frames using the sprintf call at the fps() function.

I was drawing a few triangles and was fine, then i decided to add a cube. And then I though lets have them rotate with different values, different axis. Suddenly psplink crashed, again and again - running it from the VSH displayed a "drugged up" double screen with washed out colors. I found after many recompiles that the sprintf line was the root of all evil. So I tried everything .. At a point it worked and forgot to check it again!
sprintf can be evil sometimes :) especially if you don't exactly look at your buffer sizes and what you can end up writing there (that's why I prefer snprintf now). The results sometimes are even fancier than plain crashes (had a lot of out of memory problems once with that)
Thanks again the valuable info & you patience -to read my code-, you have been a great help!
No problem, glad to help :)
User avatar
skistovel
Posts: 14
Joined: Mon Jul 17, 2006 11:46 pm

Post by skistovel »

You are already my personal hero!

The now updated tutorial 8 thanks to you!

ps: I didnt know what to say, so I just wrote Raphael from ps2dev.org..
Post Reply