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 

Hardware bugs in phat psp?

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



Joined: 09 May 2005
Posts: 84

PostPosted: Thu Aug 21, 2008 11:45 am    Post subject: Hardware bugs in phat psp? Reply with quote

I tried a search to see if there was anything on hardware bugs sony left behind for phat psp's, but no such luck.

Reason I ask, is because I'm rendering a skybox which works perfectly fine on my slim psp, but on the phat psp it looks like the uv coordinates are screwing up in strange ways when I start clipping the skybox polys against my world geometry (when it isn't getting clipped, it looks fine). Same eboot, same rendering code, doing nothing specific for the slim or phat psp's.

Slim:


Phat:


Rendering Code (sorry its a lot, would be great if I could get it cut down):
Code:

vec3_t   skyclip[6] = {
   {1,1,0},
   {1,-1,0},
   {0,-1,1},
   {0,1,1},
   {1,0,1},
   {-1,0,1}
};
int   c_sky;

// 1 = s, 2 = t, 3 = 2048
int   st_to_vec[6][3] =
{
   {3,-1,2},
   {-3,1,2},

   {1,3,2},
   {-1,-3,2},

   {-2,-1,3},      // 0 degrees yaw, look straight up
   {2,-1,-3}      // look straight down

//   {-1,2,3},
//   {1,2,-3}
};

// s = [0]/[2], t = [1]/[2]
int   vec_to_st[6][3] =
{
   {-2,3,1},
   {2,3,-1},

   {1,3,2},
   {-1,3,-2},

   {-2,-1,3},
   {-2,1,-3}

//   {-1,2,3},
//   {1,2,-3}
};

float   skymins[2][6], skymaxs[2][6];

void DrawSkyPolygon (int nump, vec3_t vecs)
{
   int      i,j;
   vec3_t   v, av;
   float   s, t, dv;
   int      axis;
   float   *vp;

   c_sky++;

   // decide which face it maps to
   VectorCopy (vec3_origin, v);
   for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
   {
      VectorAdd (vp, v, v);
   }
   av[0] = fabs(v[0]);
   av[1] = fabs(v[1]);
   av[2] = fabs(v[2]);
   if (av[0] > av[1] && av[0] > av[2])
   {
      if (v[0] < 0)
         axis = 1;
      else
         axis = 0;
   }
   else if (av[1] > av[2] && av[1] > av[0])
   {
      if (v[1] < 0)
         axis = 3;
      else
         axis = 2;
   }
   else
   {
      if (v[2] < 0)
         axis = 5;
      else
         axis = 4;
   }

   // project new texture coords
   for (i=0 ; i<nump ; i++, vecs+=3)
   {
      j = vec_to_st[axis][2];
      if (j > 0)
         dv = vecs[j - 1];
      else
         dv = -vecs[-j - 1];

      j = vec_to_st[axis][0];
      if (j < 0)
         s = -vecs[-j -1] / dv;
      else
         s = vecs[j-1] / dv;
      j = vec_to_st[axis][1];
      if (j < 0)
         t = -vecs[-j -1] / dv;
      else
         t = vecs[j-1] / dv;

      if (s < skymins[0][axis])
         skymins[0][axis] = s;
      if (t < skymins[1][axis])
         skymins[1][axis] = t;
      if (s > skymaxs[0][axis])
         skymaxs[0][axis] = s;
      if (t > skymaxs[1][axis])
         skymaxs[1][axis] = t;
   }
}

#define   MAX_CLIP_VERTS   64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
   float   *norm;
   float   *v;
   qboolean   front, back;
   float   d, e;
   float   dists[MAX_CLIP_VERTS];
   int      sides[MAX_CLIP_VERTS];
   vec3_t   newv[2][MAX_CLIP_VERTS];
   int      newc[2];
   int      i, j;

   if (nump > MAX_CLIP_VERTS-2)
      Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
   if (stage == 6)
   {   // fully clipped, so draw it
      DrawSkyPolygon (nump, vecs);
      return;
   }

   front = back = qfalse;
   norm = skyclip[stage];
   for (i=0, v = vecs ; i<nump ; i++, v+=3)
   {
      d = DotProduct (v, norm);
      if (d > ON_EPSILON)
      {
         front = qtrue;
         sides[i] = SIDE_FRONT;
      }
      else if (d < ON_EPSILON)
      {
         back = qtrue;
         sides[i] = SIDE_BACK;
      }
      else
         sides[i] = SIDE_ON;
      dists[i] = d;
   }

   if (!front || !back)
   {   // not clipped
      ClipSkyPolygon (nump, vecs, stage+1);
      return;
   }

   // clip it
   sides[i] = sides[0];
   dists[i] = dists[0];
   VectorCopy (vecs, (vecs+(i*3)) );
   newc[0] = newc[1] = 0;

   for (i=0, v = vecs ; i<nump ; i++, v+=3)
   {
      switch (sides[i])
      {
      case SIDE_FRONT:
         VectorCopy (v, newv[0][newc[0]]);
         newc[0]++;
         break;
      case SIDE_BACK:
         VectorCopy (v, newv[1][newc[1]]);
         newc[1]++;
         break;
      case SIDE_ON:
         VectorCopy (v, newv[0][newc[0]]);
         newc[0]++;
         VectorCopy (v, newv[1][newc[1]]);
         newc[1]++;
         break;
      }

      if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
         continue;

      d = dists[i] / (dists[i] - dists[i+1]);
      for (j=0 ; j<3 ; j++)
      {
         e = v[j] + d*(v[j+3] - v[j]);
         newv[0][newc[0]][j] = e;
         newv[1][newc[1]][j] = e;
      }
      newc[0]++;
      newc[1]++;
   }

   // continue
   ClipSkyPolygon (newc[0], newv[0][0], stage+1);
   ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
{
   int      i;

   for (i=0 ; i<6 ; i++)
   {
      skymins[0][i] = skymins[1][i] = 9999;
      skymaxs[0][i] = skymaxs[1][i] = -9999;
   }
}

float s_axis;
float t_axis;
vec3_t v_axis;

void MakeSkyVec (float s, float t, int axis)
{
   vec3_t      b;
   int         j, k;

   b[0] = s*r_skyclip.value;
   b[1] = t*r_skyclip.value;
   b[2] = r_skyclip.value;

   for (j=0 ; j<3 ; j++)
   {
      k = st_to_vec[axis][j];
      if (k < 0)
         v_axis[j] = -b[-k - 1];
      else
         v_axis[j] = b[k - 1];
      v_axis[j] += r_origin[j];
   }

   // avoid bilerp seam
   s = (s+1)*0.5;
   t = (t+1)*0.5;

   if (s < 1.0/512)
      s = 1.0/512;
   else if (s > 511.0/512)
      s = 511.0/512;
   if (t < 1.0/512)
      t = 1.0/512;
   else if (t > 511.0/512)
      t = 511.0/512;

   t = 1.0 - t;

   s_axis = s;
   t_axis = t;
}

/*
==============
R_DrawSkyBox
==============
*/
void R_DrawSkyBox (void)
{
    int      i;
    float   r,g,b,a;

   for (i=0 ; i<6 ; i++)
   {
      // Allocate memory for this polygon.
      const int      unclipped_vertex_count   = 4;
      glvert_t* const   unclipped_vertices      =
         static_cast<glvert_t*>(sceGuGetMemory(sizeof(glvert_t) * unclipped_vertex_count));

      if (skymins[0][i] >= skymaxs[0][i]
      || skymins[1][i] >= skymaxs[1][i])
         continue;

        GL_Bind (skyimage[skytexorder[i]]);

      MakeSkyVec (skymins[0][i], skymins[1][i], i);

        unclipped_vertices[0].st[0]       = s_axis;
        unclipped_vertices[0].st[1]       = t_axis;
        unclipped_vertices[0].xyz[0]   = v_axis[0];
        unclipped_vertices[0].xyz[1]   = v_axis[1];
        unclipped_vertices[0].xyz[2]   = v_axis[2];

      MakeSkyVec (skymins[0][i], skymaxs[1][i], i);

        unclipped_vertices[1].st[0]       = s_axis;
        unclipped_vertices[1].st[1]       = t_axis;
        unclipped_vertices[1].xyz[0]   = v_axis[0];
        unclipped_vertices[1].xyz[1]   = v_axis[1];
        unclipped_vertices[1].xyz[2]   = v_axis[2];

      MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);

        unclipped_vertices[2].st[0]       = s_axis;
        unclipped_vertices[2].st[1]       = t_axis;
        unclipped_vertices[2].xyz[0]   = v_axis[0];
        unclipped_vertices[2].xyz[1]   = v_axis[1];
        unclipped_vertices[2].xyz[2]   = v_axis[2];

      MakeSkyVec (skymaxs[0][i], skymins[1][i], i);

        unclipped_vertices[3].st[0]       = s_axis;
        unclipped_vertices[3].st[1]       = t_axis;
        unclipped_vertices[3].xyz[0]   = v_axis[0];
        unclipped_vertices[3].xyz[1]   = v_axis[1];
        unclipped_vertices[3].xyz[2]   = v_axis[2];

        if (clipping::is_clipping_required(
            unclipped_vertices,
            unclipped_vertex_count))
        {
            // Clip the polygon.
            const glvert_t*   clipped_vertices;
            std::size_t      clipped_vertex_count;
            clipping::clip(
                unclipped_vertices,
                unclipped_vertex_count,
                &clipped_vertices,
                &clipped_vertex_count);

            // Did we have any vertices left?
            if (clipped_vertex_count)
            {
                // Copy the vertices to the display list.
                const std::size_t buffer_size = clipped_vertex_count * sizeof(glvert_t);
                glvert_t* const display_list_vertices = static_cast<glvert_t*>(sceGuGetMemory(buffer_size));
                memcpy(display_list_vertices, clipped_vertices, buffer_size);

                if(cl.worldmodel)
                    VID_SetPaletteSKY ();

                Fog_DisableGFog();

                if (r_refdef.fog_end > 0 && r_skyfog.value)
                {
                    a = r_refdef.fog_end * 0.00025f;
                    r = r_refdef.fog_red * 0.01f + (a * 0.25f);
                    g = r_refdef.fog_green * 0.01f + (a * 0.25f);
                    b = r_refdef.fog_blue * 0.01f + (a * 0.25f);

                    if (a > 1)
                        a = 1;
                    if (r > 1)
                        r = 1;
                    if (g > 1)
                        g = 1;
                    if (b > 1)
                        b = 1;

                    sceGuEnable(GU_BLEND);
                    sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, GU_COLOR(r,g,b,a), GU_COLOR(r,g,b,a));
                }

                sceGuDepthRange(32767, 65535);

                // Draw the clipped vertices.
                sceGuDrawArray(
                    GU_TRIANGLE_FAN,
                    GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
                    clipped_vertex_count, 0, display_list_vertices);

                sceGuDepthRange(0, 65535);

                if (r_refdef.fog_end > 0 && r_skyfog.value)
                {
                    sceGuDisable(GU_BLEND);
                    sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
                }

                VID_SetPaletteTX ();
                Fog_EnableGFog();

            }
        }
        else
        {

            if(cl.worldmodel)
                VID_SetPaletteSKY ();

            Fog_DisableGFog();

            if (r_refdef.fog_end > 0 && r_skyfog.value)
            {
                a = r_refdef.fog_end * 0.00025f;
                r = r_refdef.fog_red * 0.01f + (a * 0.25f);
                g = r_refdef.fog_green * 0.01f + (a * 0.25f);
                b = r_refdef.fog_blue * 0.01f + (a * 0.25f);

                if (a > 1)
                    a = 1;
                if (r > 1)
                    r = 1;
                if (g > 1)
                    g = 1;
                if (b > 1)
                    b = 1;

                sceGuEnable(GU_BLEND);
                sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, GU_COLOR(r,g,b,a), GU_COLOR(r,g,b,a));
            }

            sceGuDepthRange(32767, 65535);

            // Draw the poly directly.
            sceGuDrawArray(
                GU_TRIANGLE_FAN,
                GU_TEXTURE_32BITF | GU_VERTEX_32BITF,
                unclipped_vertex_count, 0, unclipped_vertices);

            sceGuDepthRange(0, 65535);

            if (r_refdef.fog_end > 0 && r_skyfog.value)
            {
                sceGuDisable(GU_BLEND);
                sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
            }

            VID_SetPaletteTX ();
            Fog_EnableGFog();
        }
   }
}

//===============================================================

/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
   msurface_t   *fa;
    int      i;
    vec3_t   verts[MAX_CLIP_VERTS];
    glpoly_t   *p;

    if (skybox_name[0]) // if the skybox has a name, draw the skybox
   {
        c_sky = 0;
 //       GL_Bind(solidskytexture);

        // calculate vertex values for sky box

        for (fa=s ; fa ; fa=fa->texturechain)
        {
            for (p=fa->polys ; p ; p=p->next)
            {
                for (i=0 ; i<p->numverts ; i++)
                {
                    VectorSubtract (p->verts[i].xyz, r_origin, verts[i]);
                }
                ClipSkyPolygon (p->numverts, verts[0], 0);
            }

        }
   }
    else // otherwise, draw the normal quake sky
   {
        // used when gl_texsort is on
        GL_Bind(solidskytexture);

        if (kurok)
            speedscale = realtime*2;
        else
            speedscale = realtime*8;

        speedscale -= (int)speedscale & ~127 ;

        for (fa=s ; fa ; fa=fa->texturechain)
            EmitSkyPolys (fa);

        sceGuEnable(GU_BLEND);
//        sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);

        GL_Bind (alphaskytexture);

        if (kurok)
            speedscale = realtime*4;
        else
            speedscale = realtime*16;

        speedscale -= (int)speedscale & ~127 ;

        for (fa=s ; fa ; fa=fa->texturechain)
            EmitSkyPolys (fa);

        sceGuDisable(GU_BLEND);
//        sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
   }
}
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Thu Aug 21, 2008 1:41 pm    Post subject: Reply with quote

I'd look more into how you're doing the textures... the main difference between the Phat and Slim as far a video goes is the amount of vram. Maybe you're loading more than 2 MB into vram, which will work in the Slim, but not the Phat.
Back to top
View user's profile Send private message AIM Address
MDave



Joined: 09 May 2005
Posts: 84

PostPosted: Thu Aug 21, 2008 1:57 pm    Post subject: Reply with quote

I havn't unlocked the extra 2mb of vram for the slim (because I'm having problems using it after unlocking it).

Can't be vram because I fallback on using system ram if there isn't any vram left to allocate. Thanks to some help on irc, it seems to be related to how the phat psp dosn't like uvmap coordinates below 0, which the slim dosn't suffer from. Which is what happens when the skypolys are being shifted around (and the coordinates) because of clipping against the world geometry. Not sure what to do.
Back to top
View user's profile Send private message
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Thu Aug 21, 2008 2:15 pm    Post subject: Reply with quote

You could try manually wrapping the texture coordinates when they are < 0 by adding 1.0 to it until they are >= 0.
_________________
<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
Raphael



Joined: 17 Jan 2006
Posts: 646
Location: Germany

PostPosted: Thu Aug 21, 2008 3:31 pm    Post subject: Reply with quote

Solved via IRC. Screw Sony for not creating a DMA interface aware of the CPU cache for the sake of saving a few latency cycles.
Tradeoff: Hours and days of debugging pseudo-random bugs, again and again.
Anyway, thank you SCE.


For all follow-up readers - the once again solution:
Whenever you're going to draw a vertex buffer that you dynamically create (or have touched for any means), be sure to add a sceKernelDcacheWritebackRange( vertex_buffer, vertex_buffer_size ); before the following sceGu(m)Draw* call.
_________________
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl


Last edited by Raphael on Fri Aug 22, 2008 7:14 am; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Thu Aug 21, 2008 7:17 pm    Post subject: Reply with quote

are you speaking about the GPU internal cache for texture or about Allegrex cache ? so far as I know, you always need to writeback the Allegrex cache especially if a DMA operation is envolved.
Back to top
View user's profile Send private message
KickinAezz



Joined: 03 Jun 2007
Posts: 328

PostPosted: Fri Aug 22, 2008 12:53 am    Post subject: Reply with quote

Raphael wrote:
Solved via IRC. Screw Sony for not creating a DMA interface aware of the CPU cache for the sake of saving a few latency cycles.
Tradeoff: Hours and days of debugging pseudo-random bugs, again and again.

Or was it all just a hardware bug to begin with, seeing this 'fixed' on SLIM?
Anyway, thank you SCE.


For all follow-up readers - the once again solution:
Whenever you're going to draw a vertex buffer that you dynamically create (or have touched for any means), be sure to add a sceKernelDcacheWritebackRange( vertex_buffer, vertex_buffer_size ); before the following sceGu(m)Draw* call.



Will sceKernelDcacheWriteBackAll() be Sufficient if framerate is not put to consideration?
_________________
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
Back to top
View user's profile Send private message
MDave



Joined: 09 May 2005
Posts: 84

PostPosted: Fri Aug 22, 2008 2:38 am    Post subject: Reply with quote

It seems it hasn't totally fixed my problems. The S and T coordintes are the prime suspect here, the phat dosn't like me flipping the T axis (so the skybox images are displayed correctly) while the slim has no problem about it.

I get better results if I flip the T axis in these, and don't write back to the cache (still not perfect though):
Code:

// Orignal
unclipped_vertices[0].st[1]       = t_axis;

// New
unclipped_vertices[0].st[1]       = (t_axis = 1.0f - t_axis);


instead of flipping it in the other original function like this:
Code:
t = 1.0f - t;


Any ideas?

Here's screenshots, using the above fix:

Without cache writeback:


With cache writeback:
Back to top
View user's profile Send private message
MDave



Joined: 09 May 2005
Posts: 84

PostPosted: Fri Aug 22, 2008 8:41 am    Post subject: Reply with quote

Temporary solution for now is to flip the image vertically in an image editor instead of doing it in code.

I guess this is something that won't be easily solved, thanks sony :(
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