forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Swapping palettes for each texture

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Mon Dec 14, 2009 12:38 am    Post subject: Swapping palettes for each texture Reply with quote

I've come to the conclusion that 32-bit textures take up way too much RAM, so I wanted to try a different approach.

Let's say I had an 8-bit PCX file, which, being a PCX file, would be a completely 8-bit image. Now, with my old implementation, I would upsample the texture to a 32-bit image, then use that to render. However, I see now the amount of RAM that wastes.. Can somebody give me an example of swapping the palette whenever a texture is to be rendered?

Thanks :)
Back to top
View user's profile Send private message
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Mon Dec 14, 2009 12:49 am    Post subject: Reply with quote

pspsdk/samples/gu/clut/
_________________
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Back to top
View user's profile Send private message Visit poster's website
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Mon Dec 14, 2009 12:57 am    Post subject: Reply with quote

Raphael wrote:
pspsdk/samples/gu/clut/


Thanks, I'll take a look later today :D
Back to top
View user's profile Send private message
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Mon Dec 14, 2009 10:40 am    Post subject: Reply with quote

Alright, well I've come to a bit of a problem.

What's the format that sceGuClutLoad asks for?

Right now, my palette is stored as a pointer to a series of bytes that go as RGBRGBRGB.. etc. How would it be converted into the proper format?
Back to top
View user's profile Send private message
psPea



Joined: 01 Sep 2007
Posts: 64

PostPosted: Mon Dec 14, 2009 1:20 pm    Post subject: Reply with quote

sceGuClutMode sets the clut mode (line 125 of the sample)
psp doesn't support 24 bbp you'll have to add an alpha channel


>Right now, my palette is stored as a pointer to a series of bytes that go as RGBRGBRGB.. etc. How would it be converted into the proper format?
you could use the GU_RGBA(r,g,b,a) macro
_________________
Click ME!
Back to top
View user's profile Send private message Yahoo Messenger MSN Messenger
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Sun Dec 20, 2009 5:33 am    Post subject: Reply with quote

Okay; here's the issue.

The palette switches, sometimes, but it fails half the time, the correct palette will flash on and off every frame or so, it's really annoying. This is Quake, attempting to get Half-Life maps loading. The previous implementation I had would upsample the 8-bit textures to 32-bit textures and render them as such, but it took up far too much RAM, and now I decided to try this.

http://www.youtube.com/watch?v=32QDVXlJof4

I also put some good music on the video, so yay!
Back to top
View user's profile Send private message
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Sun Dec 20, 2009 6:26 am    Post subject: Reply with quote

Well... we see how the textures flicker, but we can't say what the reason is, since we don't know how you handle the palettes.

Do you have them in sys ram or vram?
Do you have all palettes in their own location and upload from there
or do you copy to your global palette each texture swap?
Do you set the parameters for sceGuClut* correctly?
...
_________________
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Back to top
View user's profile Send private message Visit poster's website
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Sun Dec 20, 2009 6:47 am    Post subject: Reply with quote

Raphael wrote:
Do you have them in sys ram or vram?


System RAM.

Raphael wrote:
Do you have all palettes in their own location and upload from there


Yes.

Raphael wrote:
or do you copy to your global palette each texture swap?


Every time I bind the texture, I swap by doing this:

Code:

void VID_SetPaletteHL(unsigned char* palette)
{
   ScePspRGBA8888 ALIGNED(16)   d_8to24tableHL[palette_size];
   
   // Convert the palette to PSP format.
   for (ScePspRGBA8888* color = &d_8to24tableHL[0]; color < &d_8to24tableHL[palette_size]; ++color)
   {
      const unsigned int r = *palette++;
      const unsigned int g = *palette++;
      const unsigned int b = *palette++;
      *color = GU_RGBA(r, g, b, 0xff);
   }

   // Upload the palette.
   sceGuClutMode(GU_PSM_8888, 0, palette_size - 1, 0);
   sceKernelDcacheWritebackRange(d_8to24tableHL, sizeof(d_8to24tableHL));
   sceGuClutLoad(palette_size / 8, d_8to24tableHL);
}


Raphael wrote:
Do you set the parameters for sceGuClut* correctly?
...


Yeah.

EDIT:
In case you're wondering, here's me binding them:

Code:

void GL_Bind (int texture_index)
{

   // Which texture is it?
   const gltexture_t& texture = gltextures[texture_index];
   
   if (texture.palette)
      VID_SetPaletteHL(texture.palette);
   else
      VID_SetPaletteTX();
   
   // Binding the currently bound texture?
   if (currenttexture == texture_index)
   {
      // Don't bother.
      return;
   }

   // Remember the current texture.
   currenttexture = texture_index;
   
   // Set the texture mode.
   if (texture.palette)
      sceGuTexMode(GU_PSM_T8, texture.mipmaps , 0, GU_TRUE);
   else
      sceGuTexMode(texture.format, texture.mipmaps , 0, GU_TRUE);

   if (texture.mipmaps > 0 && r_mipmaps.value > 0)
    {
      float slope = 0.4f;
      sceGuTexSlope(slope); // the near from 0 slope is the lower (=best detailed) mipmap it uses
        sceGuTexFilter(GU_LINEAR_MIPMAP_LINEAR, GU_LINEAR_MIPMAP_LINEAR);
      sceGuTexLevelMode(int(r_mipmaps_func.value), r_mipmaps_bias.value);
   }
   else
      sceGuTexFilter(texture.filter, texture.filter);
      
   // Set the texture image.
   const void* const texture_memory = texture.vram ? texture.vram : texture.ram;
   sceGuTexImage(0, texture.width, texture.height, texture.width, texture_memory);
}
Back to top
View user's profile Send private message
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Sun Dec 20, 2009 7:47 am    Post subject: Reply with quote

gotmilk065 wrote:

Code:

void VID_SetPaletteHL(unsigned char* palette)
{
   ScePspRGBA8888 ALIGNED(16)   d_8to24tableHL[palette_size];
   
   // Convert the palette to PSP format.
   for (ScePspRGBA8888* color = &d_8to24tableHL[0]; color < &d_8to24tableHL[palette_size]; ++color)
   {
      const unsigned int r = *palette++;
      const unsigned int g = *palette++;
      const unsigned int b = *palette++;
      *color = GU_RGBA(r, g, b, 0xff);
   }

   // Upload the palette.
   sceGuClutMode(GU_PSM_8888, 0, palette_size - 1, 0);
   sceKernelDcacheWritebackRange(d_8to24tableHL, sizeof(d_8to24tableHL));
   sceGuClutLoad(palette_size / 8, d_8to24tableHL);
}


Raphael wrote:
Do you set the parameters for sceGuClut* correctly?
...


Yeah.

There you go. Not really.
sceGuClutMode Parameter 2 is a mask parameter for the palette index read from the texture. As long as palette_size is exactly 256 this will work out perfectly well, for anything else it will fail. It doesn't really make sense to depend the index mask on the size, unless you have an T16 or T32 texture map. So just use 0xff there.

Apart from that, you should know that what you do there is gonna cause glitches obviously, as soon as you end up overwriting the stack where you place the palette before GU gets to use it (ie, the next texture is processed before GU got to render the previous one, hence ending up using the *wrong* palette data). This is because sceGu* functions are asynchronous, meaning that the pointer and it's data you give there *must* stay valid for the remainder of the whole frame (which it currently isn't, as its a local variable for that function, ie on stack).
Two solution options:
1. Use sceGuGetMemory to allocate the temporary palette in the current display list
2. allocate memory for the psp palette in your texture structure (256*4 bytes) and fill that with the right palette data on texture load time, then use that pointer (would also save you the need to convert the palette on each texture bind).


What does VID_SetPaletteTX() do exactly? Set a dummy palette? You don't have to, as GU won't use any palette information as soon as the texture format is non-paletted.
_________________
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Back to top
View user's profile Send private message Visit poster's website
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Sun Dec 20, 2009 8:27 am    Post subject: Reply with quote

Raphael wrote:

There you go. Not really.
sceGuClutMode Parameter 2 is a mask parameter for the palette index read from the texture. As long as palette_size is exactly 256 this will work out perfectly well, for anything else it will fail. It doesn't really make sense to depend the index mask on the size, unless you have an T16 or T32 texture map. So just use 0xff there.


Ooo Okay, thanks.

Raphael wrote:

Apart from that, you should know that what you do there is gonna cause glitches obviously, as soon as you end up overwriting the stack where you place the palette before GU gets to use it (ie, the next texture is processed before GU got to render the previous one, hence ending up using the *wrong* palette data). This is because sceGu* functions are asynchronous, meaning that the pointer and it's data you give there *must* stay valid for the remainder of the whole frame (which it currently isn't, as its a local variable for that function, ie on stack).
Two solution options:
1. Use sceGuGetMemory to allocate the temporary palette in the current display list
2. allocate memory for the psp palette in your texture structure (256*4 bytes) and fill that with the right palette data on texture load time, then use that pointer (would also save you the need to convert the palette on each texture bind).


Useful information, mate, thanks! I think I'll take option 2. I actually was going to do that originally, but decided on this to test, and when the method I'm using now didn't work, I figured there was a problem in general, lol, so I didn't bother switching.

Raphael wrote:

What does VID_SetPaletteTX() do exactly? Set a dummy palette? You don't have to, as GU won't use any palette information as soon as the texture format is non-paletted.


Nah, it's to revert to the Quake palette, to retain a bit of backwards compatibility with Quake and so the textures on the viewmodels would render correctly when they use the Quake palette.
Back to top
View user's profile Send private message
gotmilk065



Joined: 28 Nov 2009
Posts: 25

PostPosted: Sun Dec 20, 2009 9:05 am    Post subject: Reply with quote

Sweet, got it working!

Thanks again Raph, you're a lifesaver :D
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group