/* --------------------------------------------------------------------------- * - (C) Sony Computer Entertainment Europe. All Rights Reserved. * - * - Author: Andy Fitter * - * - Created: 8-Aug-1994 * - * - Description: * - ------------ * - Profiling code using the HSync root counter to time code and drawing. * - * - Changes / History: * - ------------------ * - Author Date Change * - ------ ---- ------ * - AJF 18/8/94 Made it work, start of timing work * - * - AJF 19/8/94 Continue profiling code, nearly done now... * - * - AJF 23/9/94 Added Video mode detection code (ProfileDispMode()) * - n.b. Only works with lib2.0 or newer * - * - MDG 5/12/94 Added extra count tied to DrawSyncCallback for * - timing drawing only. Must ProfileStartCount soon * - after DrawOTag for this count to be acurate. * - New routines : ProfileCallBack (local), ProfileRead * - and ProfileAddDrawOT. Old routines will still work. * - Use ProfileReadCount instead of ProfileStopCount. * - Use ProfileAddDrawOT to add drawing timing bar. * - * - V. Diesi 23/7/97 Bug Fix: GPU primitives are now double buffered. * - Previously this was not the case and the current OT * - was corrupted! ProfileAddOT() and ProfileAddDrawOT() * - now require the caller to pass the current double * - buffer index. * - * - V. Diesi 15/4/98 Declared gDrawCount variable as volatile. * - * - V. Diesi 15/4/98 The profiler nolonger resets the root counter. This * - caused VSync(1) calls to return strange values. Which * - also caused some timings obtained using VSync(1) to be * - incorrect! * - * - Added ProfileGetCurrentCount() which gets the current * - root count value. * - * - V. Diesi 21-4-98 Removed ProfileDispMode() which was complete bollocks. * - Bar graphs now work correctly in both PAL and NTSC modes. * - The bar graph scale markers are now in the correct positions! * - Cleaned up the file and code. The variable gDivisor is now only used * - to scale down the bar graphs when drawn. gDivisor is no longer * - used to scale down the root counter values. * - * - V. Diesi 16-4-98 Root ctr is now used with interrupts prohibited. By doing * - this OpenEvent() and EnableEvent() can be removed (an * - event was previously being used for no reason which caused * - problems with memory cards since the event was never being * - closed). The redundant event code has been removed! * --------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include /* --------------------------------------------------------------------------- * - CONSTANTS * --------------------------------------------------------------------------- */ #define TOP 25 #define LEFT 25 #define HEIGHT 2 #define GRIDSIZE 65 #define DRAW_TOP (TOP+5) #define NUMSTEPS 20 // No. of HBlanks (i.e. scan lines) per field. #define NUM_HBLANKS_PAL (625 >> 1) #define NUM_HBLANKS_NTSC (525 >> 1) #ifdef PAL_MODE #define NUM_HBLANKS NUM_HBLANKS_PAL #else #define NUM_HBLANKS NUM_HBLANKS_NTSC #endif #define GREEN 0,255,0 #define RED 255,0,0 #define BLUE 0,0,255 /* --------------------------------------------------------------------------- * - DATA TYPE AND STRUCTURE DECLARATIONS * --------------------------------------------------------------------------- */ typedef struct { char scaleFactor; char numMarks; } SCALE; /* --------------------------------------------------------------------------- * - GLOBAL DEFINITIONS * --------------------------------------------------------------------------- */ static u_short gDivisor; static u_short gNumMarks; static u_short gStepNum; static volatile u_short gProfileInitialCount; static volatile u_short gDrawCount; static u_short gCPUCounts[NUMSTEPS]; static POLY_F3 gCPUMarkerPrims[6][2]; static POLY_F3 gDrawMarkerPrims[6][2]; static POLY_G4 gCPUGraphPrims[NUMSTEPS][2][2]; static POLY_G4 gDrawGraphPrims[2][2]; static SCALE gBarGraphScales[] = { { 0, 2 }, { 1, 3 }, { 2, 5 } }; u_short col_r[] = { 200, 0, 0, 200, 0, 200, 200 }; u_short col_g[] = { 0, 200, 0, 200, 200, 0, 200 }; u_short col_b[] = { 0, 0,200, 0, 200, 200, 200 }; /* --------------------------------------------------------------------------- * - FUNCTION DEFINITIONS * --------------------------------------------------------------------------- */ static void ProfileCallBack(void) { gDrawCount = ((u_short) GetRCnt(RCntCNT1) - gProfileInitialCount) & 0xffff; } /* ------------------------------------------------------------------------ */ void ProfileInit(int scale) { short i, j; short grid; gNumMarks = gBarGraphScales[scale].numMarks; gDivisor = gBarGraphScales[scale].scaleFactor; grid = NUM_HBLANKS >> gDivisor; EnterCriticalSection(); SetRCnt(RCntCNT1, 65535, RCntMdNOINTR); // Init root ctr with interrupts prohibited. DrawSyncCallback(ProfileCallBack); ExitCriticalSection(); // Init bar graph scale markers. for (i = 1; i >= 0; i--) { for (j = 0; j < gNumMarks; j++) { SetPolyF3(&gCPUMarkerPrims[j][i]); setRGB0(&gCPUMarkerPrims[j][i],50,50,150); setXY3(&gCPUMarkerPrims[j][i], LEFT+j*grid-4,TOP-3, LEFT+j*grid+4,TOP-3, LEFT+j*grid,TOP+3); SetPolyF3(&gDrawMarkerPrims[j][i]); setRGB0(&gDrawMarkerPrims[j][i],50,50,150); setXY3(&gDrawMarkerPrims[j][i], LEFT+j*grid-4,DRAW_TOP+6, LEFT+j*grid+4,DRAW_TOP+6, LEFT+j*grid,DRAW_TOP); } } // Init CPU time bar graph. for (i = 1; i >= 0; i--) { for (j = 0; j < NUMSTEPS ; j++) { SetPolyG4(&gCPUGraphPrims[j][0][i]); SetPolyG4(&gCPUGraphPrims[j][1][i]); setRGB0(&gCPUGraphPrims[j][0][i],col_r[j]/2, col_g[j]/2, col_b[j]/2); setRGB1(&gCPUGraphPrims[j][0][i],col_r[j]/2, col_g[j]/2, col_b[j]/2); setRGB2(&gCPUGraphPrims[j][0][i],col_r[j], col_g[j], col_b[j]); setRGB3(&gCPUGraphPrims[j][0][i],col_r[j], col_g[j], col_b[j]); setXY4(&gCPUGraphPrims[j][0][i],LEFT,TOP, 100,TOP, LEFT,TOP+HEIGHT-1, 100,TOP+HEIGHT); setRGB0(&gCPUGraphPrims[j][1][i],col_r[j], col_g[j], col_b[j]); setRGB1(&gCPUGraphPrims[j][1][i],col_r[j], col_g[j], col_b[j]); setRGB2(&gCPUGraphPrims[j][1][i],col_r[j]/2, col_g[j]/2, col_b[j]/2); setRGB3(&gCPUGraphPrims[j][1][i],col_r[j]/2, col_g[j]/2, col_b[j]/2); setXY4(&gCPUGraphPrims[j][1][i],LEFT,TOP+HEIGHT, 100,TOP+HEIGHT-1, LEFT,TOP+HEIGHT+HEIGHT, 100,TOP+HEIGHT+HEIGHT); } } // Init draw time bar graph. for (i = 1; i >= 0; i--) { SetPolyG4(&gDrawGraphPrims[0][i]); setRGB0(&gDrawGraphPrims[0][i],0,100,0); setRGB1(&gDrawGraphPrims[0][i],100,0,0); setRGB2(&gDrawGraphPrims[0][i],100,255,100); setRGB3(&gDrawGraphPrims[0][i],255,100,100); setXY4(&gDrawGraphPrims[0][i] , LEFT,DRAW_TOP, 100,DRAW_TOP, LEFT,DRAW_TOP+HEIGHT-1, 100,DRAW_TOP+HEIGHT); SetPolyG4(&gDrawGraphPrims[1][i]); setRGB0(&gDrawGraphPrims[1][i],100,255,100); setRGB1(&gDrawGraphPrims[1][i],255,100,100); setRGB2(&gDrawGraphPrims[1][i],0,100,0); setRGB3(&gDrawGraphPrims[1][i],100,0,0); setXY4(&gDrawGraphPrims[1][i], LEFT,DRAW_TOP+HEIGHT-1, 100,DRAW_TOP+HEIGHT, LEFT,DRAW_TOP+HEIGHT+HEIGHT, 100,DRAW_TOP+HEIGHT+HEIGHT); } gStepNum = 0; } /* ------------------------------------------------------------------------ */ void ProfileStartCount(void) { // Don't reset the root counter. Instead all root counter values // will be relative to gProfileInitialCount! gProfileInitialCount = (u_short) GetRCnt(RCntCNT1); StartRCnt(RCntCNT1); gStepNum = 0; } /* ------------------------------------------------------------------------ */ short ProfileStopCount(void) { StopRCnt(RCntCNT1); // NOTE: & 0xffff ensures root counter wrap does not cause any problem! // This same method is used by the VSync() function. gCPUCounts[gStepNum++] = ((u_short) GetRCnt(RCntCNT1) - gProfileInitialCount) & 0xffff; return gCPUCounts[gStepNum-1]; } /* ------------------------------------------------------------------------ */ short ProfileReadCount(void) { gCPUCounts[gStepNum++] = ((u_short) GetRCnt(RCntCNT1) - gProfileInitialCount) & 0xffff; return gCPUCounts[gStepNum-1]; } /* ------------------------------------------------------------------------ */ short ProfileGetCurrentCount(void) { return ((u_short) GetRCnt(RCntCNT1) - gProfileInitialCount) & 0xffff; } /* ------------------------------------------------------------------------ */ void ProfileAddOT(unsigned long * ot, short lcdb) { long count; for (count = 0; count < gNumMarks; count++) AddPrim(ot,&gCPUMarkerPrims[count][lcdb]); gCPUGraphPrims[0][0][lcdb].x1 = (gCPUCounts[0] >> gDivisor) + LEFT; gCPUGraphPrims[0][0][lcdb].x3 = (gCPUCounts[0] >> gDivisor) + LEFT; gCPUGraphPrims[0][1][lcdb].x1 = (gCPUCounts[0] >> gDivisor) + LEFT; gCPUGraphPrims[0][1][lcdb].x3 = (gCPUCounts[0] >> gDivisor) + LEFT; AddPrim(ot,&gCPUGraphPrims[0][0][lcdb]); AddPrim(ot,&gCPUGraphPrims[0][1][lcdb]); for (count = 1; count < gStepNum ; count++) { gCPUGraphPrims[count][0][lcdb].x0 = gCPUGraphPrims[count][0][lcdb].x2 = (gCPUCounts[count-1] >> gDivisor) + LEFT; gCPUGraphPrims[count][0][lcdb].x1 = gCPUGraphPrims[count][0][lcdb].x3 = (gCPUCounts[count] >> gDivisor) + LEFT; gCPUGraphPrims[count][1][lcdb].x0 = gCPUGraphPrims[count][1][lcdb].x2 = (gCPUCounts[count-1] >> gDivisor) + LEFT; gCPUGraphPrims[count][1][lcdb].x1 = gCPUGraphPrims[count][1][lcdb].x3 = (gCPUCounts[count] >> gDivisor) + LEFT; AddPrim(ot,&gCPUGraphPrims[count][0][lcdb]); AddPrim(ot,&gCPUGraphPrims[count][1][lcdb]); } } /* ------------------------------------------------------------------------ */ void ProfileAddDrawOT(unsigned long * ot, short lcdb) { long count; gDrawGraphPrims[0][lcdb].x1 = (gDrawCount >> gDivisor) + LEFT; gDrawGraphPrims[0][lcdb].x3 = (gDrawCount >> gDivisor) + LEFT; gDrawGraphPrims[1][lcdb].x1 = (gDrawCount >> gDivisor) + LEFT; gDrawGraphPrims[1][lcdb].x3 = (gDrawCount >> gDivisor) + LEFT; for (count = 0; count < gNumMarks; count++) AddPrim(ot,&gDrawMarkerPrims[count][lcdb]); AddPrim(ot,&gDrawGraphPrims[0][lcdb]); AddPrim(ot,&gDrawGraphPrims[1][lcdb]); } /* ------------------------------------------------------------------------ */