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 

Confusion about GU Texture swizzling
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
blasty



Joined: 22 Aug 2005
Posts: 9

PostPosted: Mon Aug 22, 2005 12:22 am    Post subject: Confusion about GU Texture swizzling Reply with quote

Hi,

I need to get some things straight I guess. Today I have been busy porting my 2D GFX functions to use the GU instead of writing directly to VRAM (and use a doublebuffer technique). as example I took the "blit" demo from the PSPSDK samples directory. This one renders a flat 480x272 texture to the screen. I got this all nicely working, only there was one downside, the animation of my stuff wasn't 100% smooth. Someone suggested I might needed to flush the caches using sceKernelDcacheWritebackAll(); But this didn't change a thing..

Then I read on this forum about texture swizzling. I enabled swizzling in sceGuTexMode(); and took the example function from [here] (thanks chp). Now comes my actual problem, I don't know how to use this function properly. it requires a input and output pointer which are chars. My texture is in raw 16bit format..

My code looks (shortened) like this:
Code:

  static unsigned short __attribute__((aligned(16))) pixels[512*272]; // display buffer
  static unsigned int __attribute__((aligned(16))) list[262144];

  // Setup GU
  sceGuStart(GU_DIRECT,list);
  sceGuDrawBuffer(GU_PSM_5551,(void*)0,512);
  sceGuDispBuffer(480,272,(void*)0x88000,512);

  sceGuDepthBuffer((void*)0x110000,512);
  sceGuOffset(2048 - (480/2),2048 - (272/2));
  sceGuViewport(2048,2048,480,272);

  sceGuDepthRange(0xc350,0x2710);
  sceGuScissor(0,0,480,272);
  sceGuEnable(GU_SCISSOR_TEST);
  sceGuFrontFace(GU_CW);
  sceGuEnable(GU_TEXTURE_2D);

  sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
  sceGuFinish();
  sceGuSync(0,0);

  sceDisplayWaitVblankStart();
  sceGuDisplay(1);

  struct Vertex* vertices;
  unsigned short *texture;

  texture = malloc(sizeof(pixels));
 
  // swizzle texture
  swizzle(texture, &pixels, 480*2, 272); // pixel width = 2 bytes, so x2
 
  sceGuStart(GU_DIRECT,list);
 
  // setup the source buffer as a 512x512 texture, but only copy 480x272
  sceGuTexMode(GU_PSM_5551,0,0,GU_TRUE);
  sceGuTexImage(0,512,512,512,texture);
  sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGB);
  sceGuTexFilter(GU_NEAREST,GU_NEAREST);
  sceGuTexScale(1.0f/512.0f,1.0f/512.0f); // scale UVs to 0..1
  sceGuTexOffset(0.0f,0.0f);
  sceGuAmbientColor(0xffffffff);
 
  for (j = 0; j < 480; j = j+SLICE_SIZE) {
    vertices = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex));

    vertices[0].u = j; vertices[0].v = 0;
    vertices[0].color = 0;
    vertices[0].x = j; vertices[0].y = 0; vertices[0].z = 0;
    vertices[1].u = j+SLICE_SIZE; vertices[1].v = 272;
    vertices[1].color = 0;
    vertices[1].x = j+SLICE_SIZE; vertices[1].y = 272; vertices[1].z = 0;
    sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_COLOR_5551|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vertices);
  }

  sceGuFinish();
  sceGuSync(0,0);


This doesn't give the wanted result. I see parts of my image data back, but it's not ordered properly. Does anyone have a clue what I'm missing/doing wrong here?

Any help would be highly appreciated!
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Mon Aug 22, 2005 2:13 am    Post subject: Reply with quote

Quite simple: You're swizzling it as a 480x272 16-bit, while it's clearly a 512x272 16-bit. That will shift all the blocks because of the dead data read.

If you wanted to swizzle just part of a texture, you'd have to take into account the buffer-width aswell. The swizzle functions I wrote do not at the moment.
_________________
GE Dominator
Back to top
View user's profile Send private message
blasty



Joined: 22 Aug 2005
Posts: 9

PostPosted: Mon Aug 22, 2005 2:37 am    Post subject: Reply with quote

Damn. that was quite obvious actually. just fixed that bug in the source.

But still my texture still doesn't come out correct.. It's divided in 4 vertical lines and seems to skip a row of pixels (so is black in end result) each time. veeery strange.
Back to top
View user's profile Send private message
blasty



Joined: 22 Aug 2005
Posts: 9

PostPosted: Tue Aug 23, 2005 7:40 pm    Post subject: Reply with quote

NOBODY has an idea what I am doing wrong here? Furthermore, I have looked through the PSPWARE SVN directory to see if any of the projects used texture swizzling.. but NONE of them does. Why?? Am I the only person experiencing heavy frame tearing when copying a 480x272 texture a few times every second? I have fiddled around with this for 12+ hours now, and I'm getting kind of fed up with it. Without swizzling my code looks exactly the same except for the memory getting malloc()'d and the swizzle parameter not being set in sceGuTexMode(); (oh, and the reference to "pixels" insteaf of "texture", kinda obvious). A working example or explanation why my stuff is so slow would be highly appreciated.
Back to top
View user's profile Send private message
Panajev2001a



Joined: 20 Aug 2005
Posts: 100

PostPosted: Sat Aug 27, 2005 7:48 pm    Post subject: Reply with quote

Try this function: it is the original function chp optimized for the Wiki submission and I did a small few changes to it (no divides, but shifts instead, etc...).

Code:
void swizzle_fast(u8* out, const u8* in, unsigned int width, unsigned int height)
{
   unsigned int blockx, blocky;
   unsigned int i,j;
 
   unsigned int width_blocks = (width >> 4);
   unsigned int height_blocks = (height >> 3);
 
   unsigned int src_pitch = (width-16) >> 2;
   unsigned int src_row = width << 3;
 
   const u8* ysrc = in;
   u32* dst = out;
 
   for (blocky = 0; blocky < height_blocks; ++blocky)
   {
      const u8* xsrc = ysrc;
      for (blockx = 0; blockx < width_blocks; ++blockx)
      {
         const u32* src = (u32*)xsrc;
         for (j = 0; j < 8; ++j)
         {
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            src += src_pitch;
         }
         xsrc += 16;
     }
     ysrc += src_row;
   }
}


The best thing would be to swizzle outside of your PSP program, presenting the texture as already swizzled when you load them up.
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sat Aug 27, 2005 10:38 pm    Post subject: Reply with quote

Panajev2001a wrote:
Try this function: it is the original function chp optimized for the Wiki submission and I did a small few changes to it (no divides, but shifts instead, etc...).


Most compilers replace division by power-of-two integer numbers by shifts. Check the compiler or objdump output to be sure.
Back to top
View user's profile Send private message
Panajev2001a



Joined: 20 Aug 2005
Posts: 100

PostPosted: Sun Aug 28, 2005 12:06 am    Post subject: Reply with quote

holger wrote:
Panajev2001a wrote:
Try this function: it is the original function chp optimized for the Wiki submission and I did a small few changes to it (no divides, but shifts instead, etc...).


Most compilers replace division by power-of-two integer numbers by shifts. Check the compiler or objdump output to be sure.


I tend not to trust the compiler ;).
Back to top
View user's profile Send private message
ector



Joined: 12 May 2005
Posts: 195

PostPosted: Sun Aug 28, 2005 1:46 am    Post subject: Reply with quote

holger wrote:
Panajev2001a wrote:
Try this function: it is the original function chp optimized for the Wiki submission and I did a small few changes to it (no divides, but shifts instead, etc...).


Most compilers replace division by power-of-two integer numbers by shifts. Check the compiler or objdump output to be sure.


That's true for left-shifts, but rightshifts aren't as simple. You must use unsigned variables for the compiler to be able to fully replace a division with a rightshift, otherwise it has to add fixup code to account for the fact that -1 >> 1 == -1 and not 0 as would be expected.
_________________
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
Back to top
View user's profile Send private message
blasty



Joined: 22 Aug 2005
Posts: 9

PostPosted: Wed Aug 31, 2005 8:11 pm    Post subject: Reply with quote

boohoo, I'm still camping around with this problem. I tried Panajev's function also, but basically it does the same as chp's one. To clarify a little, I have redrawn the result of what I get when I swizzle my textures. It looks like [this], but it's supposed to look like [this]. (yes, a white rectangle ;))

My code looks still the same except for the bug/mistake I fixed regarding to the swizzle(); call. (the one chp mentioned earlier in this thread)
Back to top
View user's profile Send private message
ector



Joined: 12 May 2005
Posts: 195

PostPosted: Thu Sep 01, 2005 3:22 am    Post subject: Reply with quote

The width of your image has to be a multiple of 32 bytes. You can't just try to swizzle a 23x20 pixel image and expect it to come out right..
_________________
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
Back to top
View user's profile Send private message
blasty



Joined: 22 Aug 2005
Posts: 9

PostPosted: Thu Sep 01, 2005 6:41 am    Post subject: Reply with quote

Heh, I guess I was a little vague. This is just a quick cut and paste of the result. the texture itself is 512x512.
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Mon Oct 03, 2005 11:35 am    Post subject: Reply with quote

Did you ever manage to fix your problem?

I'm having trouble swizzling anything. I'm trying to do a 128*128 texture, but its not working. I went back to trying to swizzle the texture that came with the cube demo instead to try and find out what I'm doing wrong, but thats still not happening. Anything obviously wrong with the following?

Code:

extern unsigned char logo_start[];
const unsigned short swizzleData[64*64] = {0};

...

swizzle(swizzleData,logo_start, 64, 64);

...

sceGuTexMode(GU_PSM_4444,0,0,TRUE);
sceGuTexImage(0,64,64,64,swizzleData);


_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Mon Oct 03, 2005 5:32 pm    Post subject: Reply with quote

you must not declare arrays that you are intending to change as "const", you want to use "static" instead.
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Mon Oct 03, 2005 7:00 pm    Post subject: Reply with quote

I can spot one problem in your code, and that is that you are passing texel-width to swizzle(), when the code in itself assumes byte-width, so the width for a 64x64 16-bit texture is in fact 128 (64 texels times 2 bytes).

I'll take a look at making a "complete" approach on the wiki soon, which will make understanding the code more clear, like passing a pixelformat to make width independent, and support swizzling just part of a texture.
_________________
GE Dominator
Back to top
View user's profile Send private message
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Mon Oct 03, 2005 7:21 pm    Post subject: Reply with quote

Hi chp,

if you change the calling convention of the swizzle/tile function, so that the texture stride is passed as argument and not calculated internally you avoid bugs like this and would even allow more flexible use...

btw. Using the VFPU you can make the inner loop a single load/store-128bit-vector pair.
Back to top
View user's profile Send private message
chp



Joined: 23 Jun 2004
Posts: 313

PostPosted: Tue Oct 04, 2005 12:02 am    Post subject: Reply with quote

But since people mistake the width as texel-width, it does show that it's unclear now aswell, doesn't it? One good approach would perhaps be to make the prototype identical to sceGuCopyImage() (from my perspective, I guess you want something else :)), since people know atleast somewhat how to use it and what the parameters mean.

Optimizing using VFPU is of secondary interest right now actually. The question is if it's any gain, depending on how we can pipeline memory-accesses from the VFPU, or if any gain can be had since you'll probably be cache-tied when reading the source-data anyway. One approach would be to switch approach and read data in a linear fashion and write in blocks. This could improve performance more than using 128-bit read/writes since we might not have to refill the cache as often.
_________________
GE Dominator
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Tue Oct 04, 2005 4:07 am    Post subject: Reply with quote

Thanks for clearing up the width parameter for me. And I can't believe I made such a stupid mistake leaving that 'const' there... The perils of Copy & Paste.
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Tue Oct 04, 2005 4:11 am    Post subject: Reply with quote

chp wrote:

Optimizing using VFPU is of secondary interest right now actually. The question is if it's any gain, depending on how we can pipeline memory-accesses from the VFPU, or if any gain can be had since you'll probably be cache-tied when reading the source-data anyway. One approach would be to switch approach and read data in a linear fashion and write in blocks. This could improve performance more than using 128-bit read/writes since we might not have to refill the cache as often.



By setting the cache policy bit in the sw.q instruction you can bypass the cache entirely, you can also avoid cache pollution by using the uncached high memory address space. In our pspgl experiments uncached word writes to the GE command buffer were more performant than cached ones, I assume there is a write combiner unit in the uncached write path.
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Tue Oct 04, 2005 4:22 am    Post subject: Reply with quote

Code:

extern unsigned char logo_start[];
static unsigned short swizzleData[64*64] = {0};
...
swizzle(swizzleData,logo_start, 64*2, 64);
//swizzle_fast(swizzleData,logo_start, 64*2, 64);
...
sceGuTexMode(GU_PSM_4444,0,0,TRUE);
sceGuTexImage(0,64,64,64,swizzleData);


Odd that this still shows a corrupt image...
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
ector



Joined: 12 May 2005
Posts: 195

PostPosted: Tue Oct 04, 2005 4:34 am    Post subject: Reply with quote

ashleydb, do you flush the texture cache?
_________________
http://www.dtek.chalmers.se/~tronic/PSPTexTool.zip Free texture converter for PSP with source. More to come.
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Tue Oct 04, 2005 4:41 am    Post subject: Reply with quote

No, I wasn't. I just tried adding it here:

sceGuTexFlush();
sceGuTexImage(0,64,64,64,swizzleData);

But that made it look worse...
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Tue Oct 04, 2005 4:44 am    Post subject: Reply with quote

You also need to flush DCache before calling the TexImage function.
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Tue Oct 04, 2005 5:09 am    Post subject: Reply with quote

From this in another post:

Quote:
sceKernelDcacheWritebackAll() before calling the glTex*() functions, glFinish() after the vertex render functions before you are moving to the next texture on the same texture object.


I made this:

Code:

void GameMain(void)
{
   sceGuStart(GU_DIRECT,list);

   //Clear screen and depth buffers.
   sceGuClearColor(0xff000000);
   sceGuClearDepth(0);
   sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);

   //Read in the user input
   GetInput();


   //Setup model matrix for the cube. Projection and View already done once since camera is static.
   sceGumMatrixMode(GU_MODEL);
   sceGumLoadIdentity();
   {
      ScePspFVector3 pos = { g_fTranslateX, g_fTranslateY, g_fTranslateZ };
      ScePspFVector3 rot = {
         g_fRotateX * (M_PI/180.0f),
         g_fRotateY * (M_PI/180.0f),
         g_fRotateZ * (M_PI/180.0f) };
      sceGumRotateXYZ(&rot);
      sceGumTranslate(&pos);
   }

   // setup texture
   sceGuTexMode(GU_PSM_4444,0,0,TRUE);


   //-------------ADDED THESE LINES----------------
   sceKernelDcacheWritebackAll();
   sceGuTexFlush();


   //Set current texturemap.
   sceGuTexImage(0,64,64,64,swizzleData);

   //Set how textures are applied.
   sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGB);

   //Set how the texture is filtered.
   sceGuTexFilter(GU_LINEAR,GU_LINEAR);

   sceGuTexScale(1.0f,1.0f);

   //?Where to start the texture when drawing?
   sceGuTexOffset(0.0f,0.0f);

   //?Set the ambient light colour?
   sceGuAmbientColor(0xffffffff);

   //Draw array of vertices forming the cube.
   sceGumDrawArray(GU_TRIANGLES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D,12*3,0,vertices);


   //Finish current display list and go back to the parent context.
   sceGuFinish();

   //Wait until display list has finished executing. Pass (0,0)
   sceGuSync(0,0);

   //Wait for the screen to finish drawing, (the next Vertical Refresh will be starting)
   sceDisplayWaitVblankStart();

   //Swap display and draw buffer so we see what we just drew.
   sceGuSwapBuffers();
}


The black bits are gone, but the texture still isn't right. I also tried moving those lines above sceGuTexMode(GU_PSM_4444,0,0,TRUE); but that didn't help either.
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Tue Oct 04, 2005 5:36 pm    Post subject: Reply with quote

call sceGuTexFlush() after sceGuTexImage() and before sceGumDrawArray(), otherwise it does not makes much sense. In Addition to sceGuTexFlush() it may even make more sense to call also sceGuTexSync(), in order to force the GE to wait until the texture transfer is finished before starting to render.

So the entire sequence looks like:

Code:

/* paint your texture, and swizzle if you want to */
sceKernelDcacheWritebackAll();  /* get all data into memory */
/* upload your texture to VRAM if you want to, e.g. using CopyImage() */
TexImage();  /* set up DMA pointers of GE for texture access */
TexFlush();  /* start DMA transfer */
/* ... do other things ...*/
TexSync();   /* let the GE wait for end of DMA transfer */
DrawArray(); /* trigger vertex array rendering */

Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Wed Oct 05, 2005 2:19 am    Post subject: Reply with quote

Thanks again for your help. That all makes good sense. After implementing the calls in the order you suggest, I really don't know why its still not working, but I don't want to keep bothering you guys with it. I guess I'll keep plugging away and see if I get anywhere eventually.
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Wed Oct 05, 2005 3:31 am    Post subject: Reply with quote

Has anyone got any example code of doing this stuff so that it works? Maybe looking at a working implementation would point out an obvious error in my code.

Thanks!
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Fri Oct 07, 2005 2:34 pm    Post subject: Reply with quote

ashleydb wrote:
Has anyone got any example code of doing this stuff so that it works? Maybe looking at a working implementation would point out an obvious error in my code.

Thanks!


Anyone? Please? ;)
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Fri Oct 07, 2005 5:37 pm    Post subject: Reply with quote

what about the cube sample in gu/samples/ ?
Back to top
View user's profile Send private message
ashleydb



Joined: 03 Oct 2005
Posts: 26
Location: USA

PostPosted: Sat Oct 08, 2005 3:03 am    Post subject: Reply with quote

It doesn't swizzle anything. That is the demo I'm trying to edit. Unless it is swizzled and I'm trying to swizzle it again...
_________________
www.PSP-Files.com - PSP News, Hacks etc.

www.HiAsh.com - My work and stuff
Back to top
View user's profile Send private message Visit poster's website
holger



Joined: 18 Aug 2005
Posts: 204

PostPosted: Sat Oct 08, 2005 4:01 am    Post subject: Reply with quote

haven't you been talking about cache inconsistency problems?
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
Goto page 1, 2  Next
Page 1 of 2

 
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