How to swizzle textures?
How to swizzle textures?
I'm trying to display an image that is covering the entire screen using the gpu. As it is now I get some serious slowdowns doing this as the image is too big to be put in the vram. I've heard that it's alot faster to swizzle the textures but I can't find anything about how to do that.
How can I swizzle textures?
How can I swizzle textures?
You need to pre-process your image into blocks, that each contains 16 bytes by 8 lines. Example:
This is a 32 bytes by 8 lines texture block (so it would be a 8x8 32-bit block, or a 16x8 16-bit block). Each index is represented by a vertical index (first value) of 0-7. The second index is the horizontal index, ranging from 0-U. When reorganizing this for swizzling, we will order the data so that when the GE needs to read something in the first 16x8 block, if can just fetch that entire block, instead of offsetting into the texture for each line it has to read. The resulting swizzled portion looks like this:
As you might have noticed, the first linear 16x8 block has ended up at the top of the texture.
Here's a function that should do this:
It's not optimized in any way (it can be done a lot faster, but not very readable), but it should do the trick and let you understand how to swizzle. Make sure you adjust the width with the size of the pixel.
EDIT: corrected the function to use chars, not ints (from my first test that needed the info, not the actual values)
Code: Select all
000102030405060708090A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V
101112131415161718191A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V
202122232425262728292A2B2C2D2E2F2G2H2I2J2K2L2M2N2O2P2Q2R2S2T2U2V
303132333435363738393A3B3C3D3E3F3G3H3I3J3K3L3M3N3O3P3Q3R3S3T3U3V
404142434445464748494A4B4C4D4E4F4G4H4I4J4K4L4M4N4O4P4Q4R4S4T4U4V
505152535455565758595A5B5C5D5E5F5G5H5I5J5K5L5M5N5O5P5Q5R5S5T5U5V
606162636465666768696A6B6C6D6E6F6G6H6I6J6K6L6M6N6O6P6Q6R6S6T6U6V
707172737475767778797A7B7C7D7E7F7G7H7I7J7K7L7M7N7O7P7Q7R7S7T7U7V
Code: Select all
000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F
404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F
606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F
0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V
2G2H2I2J2K2L2M2N2O2P2Q2R2S2T2U2V3G3H3I3J3K3L3M3N3O3P3Q3R3S3T3U3V
4G4H4I4J4K4L4M4N4O4P4Q4R4S4T4U4V5G5H5I5J5K5L5M5N5O5P5Q5R5S5T5U5V
6G6H6I6J6K6L6M6N6O6P6Q6R6S6T6U6V7G7H7I7J7K7L7M7N7O7P7Q7R7S7T7U7V
Here's a function that should do this:
Code: Select all
void swizzle(unsigned char* out, unsigned char* in, unsigned int width, unsigned int height)
{
unsigned int i,j;
unsigned int rowblocks = (width / 16);
for (j = 0; j < height; ++j)
{
for (i = 0; i < width; ++i)
{
unsigned int blockx = i / 16;
unsigned int blocky = j / 8;
unsigned int x = (i - blockx*16);
unsigned int y = (j - blocky*8);
unsigned int block_index = blockx + ((blocky) * rowblocks);
unsigned int block_address = block_index * 16 * 8;
out[block_address + x + y * 16] = in[i+j*width];
}
}
}
EDIT: corrected the function to use chars, not ints (from my first test that needed the info, not the actual values)
GE Dominator
Yes, you are swizzling bytes, not texels. So when you are swizzling a 32-bit texture, you'll have to multiply your texel-width by 4 to get the byte-width for swizzling.jsgf wrote:Just to be clear, you are swizzling the raw bytes rather than texels (ie, the swizzle function is independent of the texel format)?
Oh, and does it mean the minimum swizzlable texture size is (16/texelsize) x 8?
Well, since you have to align the buffer-width to 16 bytes anyway (the bufferwidth), your 8x8,4x4,2x2,1x1 (bytesize) will still atleasy occupy 16xN bytes, and when they are this small, swizzling the block will not do anything, since the texture-page is smaller than the swizzled block itself.
GE Dominator
Just as a side-note: I've added a page to the wiki that reflects what I've written here, together with the code and an additonal version more targetted against applications that want to swizzle their textures at runtime.
GE Dominator
Hey guys, thx for the swizzle info..
just to clarify...
whats the story with DXT 1,3,5 textures? Can they swizzle too?
a DXT block is 8/16 bytes, so logically, it could work... but it would do very strange things for the texture addressing unit :P (since DXT textures are already swizzled, in a sense)
just to clarify...
whats the story with DXT 1,3,5 textures? Can they swizzle too?
a DXT block is 8/16 bytes, so logically, it could work... but it would do very strange things for the texture addressing unit :P (since DXT textures are already swizzled, in a sense)
Although they are decompressed into 32-bit in the texture cache and as such are slower than for example 4-bit paletted anyway... though the quality increase over 4-bit for the same space cost could be worth it
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
Have you measured this, or are you making an educated guess?
I would have guessed that a DXT tile could be decompressed on the fly, rather than being explicitly decompressed into the cache.
Though I guess bilinear filtering will need the 4 neighbours of the sample, which could need up to 4 adjacent tiles. In this case, swizzling would help simply because the 4 neighbouring tiles are likely to be closer in memory, burstable, etc.
I would have guessed that a DXT tile could be decompressed on the fly, rather than being explicitly decompressed into the cache.
Though I guess bilinear filtering will need the 4 neighbours of the sample, which could need up to 4 adjacent tiles. In this case, swizzling would help simply because the 4 neighbouring tiles are likely to be closer in memory, burstable, etc.
swizzle DXT textures
We've been testing our app with both palletized and DXT textures. Swizzling the palettized textures is certainly a large speed improvement (thanks for the excellent swizzling code, chp).
We also tried running it with DXT textures both with and without the swizzling set... we seem to get a large speed improvement with the DXT textures when we tell the PSP they're swizzled, but of course the textures no longer look right since they haven't actually been swizzled. Anybody have any ideas or experience about how one would swizzle a DXT formatted image? Would we just rearrange all the 4x4 texel blocks in the image to reflect 8x8 blocks within the original image? i.e. a 16x16 DXT image currently has blocks arranged like this (where bx,y represents the 64-bit 4x4 DXT texel block at x,y in the image):
b1,1 b2,1 b3,1 b4,1
b1,2 b2,2 b3,2 b4,2
b1,3 b2,3 b3,3 b4,3
b1,4 b2,4 b3,4 b4,4
and rearrange to:
b1,1 b2,1 b1,2 b2,2
b3,1 b4,1 b3,2 b4,2
b1,3 b2,3 b1,4 b2,4
b3,3 b4,3 b3,4 b4,4
Or maybe we just swizzle all the bytes in the DXT file in the same way we're currently swizzling bytes in the palletized data?
Sorry if this doesn't make sense, I'm having a hard time wrapping my head around this problem...
We also tried running it with DXT textures both with and without the swizzling set... we seem to get a large speed improvement with the DXT textures when we tell the PSP they're swizzled, but of course the textures no longer look right since they haven't actually been swizzled. Anybody have any ideas or experience about how one would swizzle a DXT formatted image? Would we just rearrange all the 4x4 texel blocks in the image to reflect 8x8 blocks within the original image? i.e. a 16x16 DXT image currently has blocks arranged like this (where bx,y represents the 64-bit 4x4 DXT texel block at x,y in the image):
b1,1 b2,1 b3,1 b4,1
b1,2 b2,2 b3,2 b4,2
b1,3 b2,3 b3,3 b4,3
b1,4 b2,4 b3,4 b4,4
and rearrange to:
b1,1 b2,1 b1,2 b2,2
b3,1 b4,1 b3,2 b4,2
b1,3 b2,3 b1,4 b2,4
b3,3 b4,3 b3,4 b4,4
Or maybe we just swizzle all the bytes in the DXT file in the same way we're currently swizzling bytes in the palletized data?
Sorry if this doesn't make sense, I'm having a hard time wrapping my head around this problem...
As I commented in the DXT thread, I think DXT textures can't be swizzled. When I enable swizzling, I see lots of 4x4 blocks that appear repeated, which should never happen. However, the data inside each block is still correct.
If you got your DXT textures working, I'd appreciate some help over in that thread, as I haven't been able to find any info and I hate to reinvent the wheel.
If you got your DXT textures working, I'd appreciate some help over in that thread, as I haven't been able to find any info and I hate to reinvent the wheel.
Paco