#ifdef _WIN32 #include "W32Util/Misc.h" #endif #include "Common.h" #include 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 #include #include using namespace std; int g_bWriteProfile=0; #ifdef _WIN32 #if defined (_MSC_VER) && _MSC_VER >= 1400 #include #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::iterator it = listpChild.begin(); while(it != listpChild.end() ) { delete *it; *it = NULL; ++it; } } list 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 listpChild; // other profilers called during this profiler period }; struct DVPROFTRACK { u32 dwUserData; DVPROFSTRUCT::DATA* pdwTime; DVPROFSTRUCT* pprof; }; list 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 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 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::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 mapAggregateTimes; u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident) { fprintf(f, "%*s%s - ", ident, "", p->pname); list::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::iterator ittimes = mapAggregateTimes.find(p->pname); if( ittimes == mapAggregateTimes.end() ) { ittimes = mapAggregateTimes.insert(map::value_type(p->pname, DVTIMEINFO())).first; ittimes->second.uExclusive = 0; ittimes->second.uInclusive = 0; } ittimes->second.uInclusive += utime; fprintf(f, "\n"); list::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::iterator it = g_listProfilers.begin(); while(it != g_listProfilers.end() ) { DVProfWriteStruct(f, &(*it), 0); ++it; } { map::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(); }