forked from dolphin-emu/dolphin
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			317 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			317 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifdef _WIN32
 | 
						|
#include "W32Util/Misc.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#include "Common.h"
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
int frameCount;
 | 
						|
int lut3to8[8];
 | 
						|
int lut4to8[16];
 | 
						|
int lut5to8[32];
 | 
						|
int lut6to8[64];
 | 
						|
float lutu8tosfloat[256];
 | 
						|
float lutu8toufloat[256];
 | 
						|
float luts8tosfloat[256];
 | 
						|
 | 
						|
void InitLUTs()
 | 
						|
{
 | 
						|
	for (int i = 0; i < 8; i++)
 | 
						|
		lut3to8[i] = (i * 255) / 7;
 | 
						|
	for (int i = 0; i < 16; i++)
 | 
						|
		lut4to8[i] = (i * 255) / 15;
 | 
						|
	for (int i = 0; i < 32; i++)
 | 
						|
		lut5to8[i] = (i * 255) / 31;	
 | 
						|
	for (int i = 0; i < 64; i++)
 | 
						|
		lut6to8[i] = (i * 255) / 63;
 | 
						|
	for (int i = 0; i < 256; i++)
 | 
						|
	{
 | 
						|
		lutu8tosfloat[i] = (float)(i-128) / 127.0f;
 | 
						|
		lutu8toufloat[i] = (float)(i) / 255.0f;
 | 
						|
		luts8tosfloat[i] = ((float)(signed char)(char)i) / 127.0f;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Message handler for about box.
 | 
						|
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 | 
						|
{
 | 
						|
	switch (message)
 | 
						|
	{
 | 
						|
	case WM_INITDIALOG:
 | 
						|
		W32Util::CenterWindow(hDlg);
 | 
						|
		return TRUE;
 | 
						|
 | 
						|
	case WM_COMMAND:
 | 
						|
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
 | 
						|
		{
 | 
						|
			EndDialog(hDlg, LOWORD(wParam));
 | 
						|
			return TRUE;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
////////////////////
 | 
						|
// Small profiler //
 | 
						|
////////////////////
 | 
						|
#include <list>
 | 
						|
#include <string>
 | 
						|
#include <map>
 | 
						|
using namespace std;
 | 
						|
 | 
						|
int g_bWriteProfile=0;
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
 | 
						|
#if defined (_MSC_VER) && _MSC_VER >= 1400
 | 
						|
#include <intrin.h>
 | 
						|
#pragma intrinsic(__rdtsc)
 | 
						|
#endif
 | 
						|
 | 
						|
static u64 luPerfFreq=0;
 | 
						|
inline u64 GET_PROFILE_TIME()
 | 
						|
{
 | 
						|
#if defined (_MSC_VER) && _MSC_VER >= 1400
 | 
						|
    return __rdtsc();
 | 
						|
#else
 | 
						|
    LARGE_INTEGER lu;
 | 
						|
    QueryPerformanceCounter(&lu);
 | 
						|
    return lu.QuadPart;
 | 
						|
#endif
 | 
						|
}
 | 
						|
#else
 | 
						|
static u64 luPerfFreq = 1000000;
 | 
						|
#define GET_PROFILE_TIME() //GetCpuTick()
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
struct DVPROFSTRUCT;
 | 
						|
 | 
						|
struct DVPROFSTRUCT
 | 
						|
{
 | 
						|
    struct DATA
 | 
						|
    {
 | 
						|
        DATA(u64 time, u32 user = 0) : dwTime(time), dwUserData(user) {}
 | 
						|
        DATA() : dwTime(0), dwUserData(0) {}
 | 
						|
        
 | 
						|
        u64 dwTime;
 | 
						|
        u32 dwUserData;
 | 
						|
    };
 | 
						|
 | 
						|
    ~DVPROFSTRUCT() {
 | 
						|
        list<DVPROFSTRUCT*>::iterator it = listpChild.begin();
 | 
						|
        while(it != listpChild.end() ) {
 | 
						|
            delete *it; *it = NULL;
 | 
						|
            ++it;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    list<DATA> listTimes;       // before DVProfEnd is called, contains the global time it started
 | 
						|
                                // after DVProfEnd is called, contains the time it lasted
 | 
						|
                                // the list contains all the tracked times 
 | 
						|
    char pname[256];
 | 
						|
 | 
						|
    list<DVPROFSTRUCT*> listpChild;     // other profilers called during this profiler period
 | 
						|
};
 | 
						|
 | 
						|
struct DVPROFTRACK
 | 
						|
{
 | 
						|
    u32 dwUserData;
 | 
						|
    DVPROFSTRUCT::DATA* pdwTime;
 | 
						|
    DVPROFSTRUCT* pprof;
 | 
						|
};
 | 
						|
 | 
						|
list<DVPROFTRACK> g_listCurTracking;    // the current profiling functions, the back element is the
 | 
						|
                                        // one that will first get popped off the list when DVProfEnd is called
 | 
						|
                                        // the pointer is an element in DVPROFSTRUCT::listTimes
 | 
						|
list<DVPROFSTRUCT> g_listProfilers;         // the current profilers, note that these are the parents
 | 
						|
                                            // any profiler started during the time of another is held in
 | 
						|
                                            // DVPROFSTRUCT::listpChild
 | 
						|
list<DVPROFSTRUCT*> g_listAllProfilers;     // ignores the hierarchy, pointer to elements in g_listProfilers
 | 
						|
 | 
						|
void DVProfRegister(char* pname)
 | 
						|
{
 | 
						|
    if( !g_bWriteProfile )
 | 
						|
        return;
 | 
						|
 | 
						|
#ifdef _WIN32
 | 
						|
    if( luPerfFreq <= 1 ) {
 | 
						|
#if defined (_MSC_VER) && _MSC_VER >= 1400
 | 
						|
        luPerfFreq = 1000000;
 | 
						|
#else
 | 
						|
        LARGE_INTEGER temp;
 | 
						|
        QueryPerformanceFrequency(&temp);
 | 
						|
        luPerfFreq = temp.QuadPart;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    list<DVPROFSTRUCT*>::iterator it = g_listAllProfilers.begin();
 | 
						|
    
 | 
						|
//  while(it != g_listAllProfilers.end() ) {
 | 
						|
//
 | 
						|
//      if( _tcscmp(pname, (*it)->pname) == 0 ) {
 | 
						|
//          (*it)->listTimes.push_back(timeGetTime());
 | 
						|
//          DVPROFTRACK dvtrack;
 | 
						|
//          dvtrack.pdwTime = &(*it)->listTimes.back();
 | 
						|
//          dvtrack.pprof = *it;
 | 
						|
//          g_listCurTracking.push_back(dvtrack);
 | 
						|
//          return;
 | 
						|
//      }
 | 
						|
//
 | 
						|
//      ++it;
 | 
						|
//  }
 | 
						|
 | 
						|
    // else add in a new profiler to the appropriate parent profiler
 | 
						|
    DVPROFSTRUCT* pprof = NULL;
 | 
						|
    
 | 
						|
    if( g_listCurTracking.size() > 0 ) {
 | 
						|
        assert( g_listCurTracking.back().pprof != NULL );
 | 
						|
        g_listCurTracking.back().pprof->listpChild.push_back(new DVPROFSTRUCT());
 | 
						|
        pprof = g_listCurTracking.back().pprof->listpChild.back();
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        g_listProfilers.push_back(DVPROFSTRUCT());
 | 
						|
        pprof = &g_listProfilers.back();
 | 
						|
    }
 | 
						|
 | 
						|
    strncpy(pprof->pname, pname, 256);
 | 
						|
 | 
						|
    // setup the profiler for tracking
 | 
						|
    pprof->listTimes.push_back(DVPROFSTRUCT::DATA(GET_PROFILE_TIME()));
 | 
						|
 | 
						|
    DVPROFTRACK dvtrack;
 | 
						|
    dvtrack.pdwTime = &pprof->listTimes.back();
 | 
						|
    dvtrack.pprof = pprof;
 | 
						|
    dvtrack.dwUserData = 0;
 | 
						|
 | 
						|
    g_listCurTracking.push_back(dvtrack);
 | 
						|
 | 
						|
    // add to all profiler list
 | 
						|
    g_listAllProfilers.push_back(pprof);
 | 
						|
}
 | 
						|
 | 
						|
void DVProfEnd(u32 dwUserData)
 | 
						|
{
 | 
						|
    if( !g_bWriteProfile )
 | 
						|
        return;
 | 
						|
    if( g_listCurTracking.size() == 0 )
 | 
						|
        return;
 | 
						|
 | 
						|
    DVPROFTRACK dvtrack = g_listCurTracking.back();
 | 
						|
 | 
						|
    assert( dvtrack.pdwTime != NULL && dvtrack.pprof != NULL );
 | 
						|
 | 
						|
    dvtrack.pdwTime->dwTime = GET_PROFILE_TIME()- dvtrack.pdwTime->dwTime;
 | 
						|
    dvtrack.pdwTime->dwUserData= dwUserData;
 | 
						|
 | 
						|
    g_listCurTracking.pop_back();
 | 
						|
}
 | 
						|
 | 
						|
struct DVTIMEINFO
 | 
						|
{
 | 
						|
    DVTIMEINFO() : uInclusive(0), uExclusive(0) {}
 | 
						|
    u64 uInclusive, uExclusive;
 | 
						|
};
 | 
						|
 | 
						|
map<string, DVTIMEINFO> mapAggregateTimes;
 | 
						|
 | 
						|
u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident)
 | 
						|
{
 | 
						|
    fprintf(f, "%*s%s - ", ident, "", p->pname);
 | 
						|
 | 
						|
    list<DVPROFSTRUCT::DATA>::iterator ittime = p->listTimes.begin();
 | 
						|
 | 
						|
    u64 utime = 0;
 | 
						|
 | 
						|
    while(ittime != p->listTimes.end() ) {
 | 
						|
        utime += ittime->dwTime;
 | 
						|
 | 
						|
        if( ittime->dwUserData )
 | 
						|
            fprintf(f, "time: %d, user: 0x%8.8x", (u32)ittime->dwTime, ittime->dwUserData);
 | 
						|
        else
 | 
						|
            fprintf(f, "time: %d", (u32)ittime->dwTime);
 | 
						|
        ++ittime;
 | 
						|
    }
 | 
						|
 | 
						|
    // yes this is necessary, maps have problems with constructors on their type
 | 
						|
    map<string, DVTIMEINFO>::iterator ittimes = mapAggregateTimes.find(p->pname);
 | 
						|
    if( ittimes == mapAggregateTimes.end() ) {
 | 
						|
        ittimes = mapAggregateTimes.insert(map<string, DVTIMEINFO>::value_type(p->pname, DVTIMEINFO())).first;
 | 
						|
        ittimes->second.uExclusive = 0;
 | 
						|
        ittimes->second.uInclusive = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ittimes->second.uInclusive += utime;
 | 
						|
 | 
						|
    fprintf(f, "\n");
 | 
						|
 | 
						|
    list<DVPROFSTRUCT*>::iterator itprof = p->listpChild.begin();
 | 
						|
 | 
						|
    u64 uex = utime;
 | 
						|
    while(itprof != p->listpChild.end() ) {
 | 
						|
 | 
						|
        uex -= DVProfWriteStruct(f, *itprof, ident+4);
 | 
						|
        ++itprof;
 | 
						|
    }
 | 
						|
 | 
						|
    if( uex > utime ) {
 | 
						|
        uex = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    ittimes->second.uExclusive += uex;
 | 
						|
    return utime;
 | 
						|
}
 | 
						|
 | 
						|
void DVProfWrite(char* pfilename, u32 frames)
 | 
						|
{
 | 
						|
    assert( pfilename != NULL );
 | 
						|
    FILE* f = fopen(pfilename, "w");
 | 
						|
 | 
						|
    // pop back any unused
 | 
						|
    mapAggregateTimes.clear();
 | 
						|
    list<DVPROFSTRUCT>::iterator it = g_listProfilers.begin();
 | 
						|
 | 
						|
    while(it != g_listProfilers.end() ) {
 | 
						|
        DVProfWriteStruct(f, &(*it), 0);
 | 
						|
        ++it;
 | 
						|
    }
 | 
						|
 | 
						|
    {
 | 
						|
        map<string, DVTIMEINFO>::iterator it;
 | 
						|
        fprintf(f, "\n\n-------------------------------------------------------------------\n\n");
 | 
						|
 | 
						|
        u64 uTotal[2] = {0};
 | 
						|
        double fiTotalTime[2];
 | 
						|
 | 
						|
        for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) {
 | 
						|
            uTotal[0] += it->second.uExclusive;
 | 
						|
            uTotal[1] += it->second.uInclusive;
 | 
						|
        }
 | 
						|
 | 
						|
        fprintf(f, "total times (%d): ex: %Lu ", frames, 1000000*uTotal[0]/(luPerfFreq*(u64)frames));
 | 
						|
        fprintf(f, "inc: %Lu\n", 1000000 * uTotal[1]/(luPerfFreq*(u64)frames));
 | 
						|
 | 
						|
        fiTotalTime[0] = 1.0 / (double)uTotal[0];
 | 
						|
        fiTotalTime[1] = 1.0 / (double)uTotal[1];
 | 
						|
 | 
						|
        // output the combined times
 | 
						|
        for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) {
 | 
						|
            fprintf(f, "%s - ex: %f inc: %f\n", it->first.c_str(), (float)((double)it->second.uExclusive * fiTotalTime[0]),
 | 
						|
                (float)((double)it->second.uInclusive * fiTotalTime[1]));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    fclose(f);
 | 
						|
}
 | 
						|
 | 
						|
void DVProfClear()
 | 
						|
{
 | 
						|
    g_listCurTracking.clear();
 | 
						|
    g_listProfilers.clear();
 | 
						|
    g_listAllProfilers.clear();
 | 
						|
}
 |