// Note EXPORT_C GSReplay(char* lpszCmdLine, int renderer) { GLLoader::in_replayer = true; GSRendererType m_renderer; // Allow to easyly switch between SW/HW renderer -> this effectively removes the ability to select the renderer by function args m_renderer = static_cast<GSRendererType>(theApp.GetConfigI("Renderer")); // alternatively: // m_renderer = static_cast<GSRendererType>(renderer); if (m_renderer != GSRendererType::OGL_HW && m_renderer != GSRendererType::OGL_SW) { fprintf(stderr, "wrong renderer selected %d\n", static_cast<int>(m_renderer)); return; } struct Packet {uint8 type, param; uint32 size, addr; vector<uint8> buff;}; list<Packet*> packets; vector<uint8> buff; vector<float> stats; stats.clear(); uint8 regs[0x2000]; GSinit(); GSsetBaseMem(regs); s_vsync = theApp.GetConfigB("vsync"); void* hWnd = NULL; int err = _GSopen((void**)&hWnd, "", m_renderer); if (err != 0) { fprintf(stderr, "Error failed to GSopen\n"); return; } if (s_gs->m_wnd == NULL) return; { // Read .gs content std::string f(lpszCmdLine); #ifdef LZMA_SUPPORTED GSDumpFile* file = (f.size() >= 4) && (f.compare(f.size()-3, 3, ".xz") == 0) ? (GSDumpFile*) new GSDumpLzma(lpszCmdLine) : (GSDumpFile*) new GSDumpRaw(lpszCmdLine); #else GSDumpFile* file = new GSDumpRaw(lpszCmdLine); #endif uint32 crc; file->Read(&crc, 4); GSsetGameCRC(crc, 0); GSFreezeData fd; file->Read(&fd.size, 4); fd.data = new uint8[fd.size]; file->Read(fd.data, fd.size); GSfreeze(FREEZE_LOAD, &fd); delete [] fd.data; file->Read(regs, 0x2000); GSvsync(1); while(!file->IsEof()) { uint8 type; file->Read(&type, 1); Packet* p = new Packet(); p->type = type; switch(type) { case 0: file->Read(&p->param, 1); file->Read(&p->size, 4); switch(p->param) { case 0: p->buff.resize(0x4000); p->addr = 0x4000 - p->size; file->Read(&p->buff[p->addr], p->size); break; case 1: case 2: case 3: p->buff.resize(p->size); file->Read(&p->buff[0], p->size); break; } break; case 1: file->Read(&p->param, 1); break; case 2: file->Read(&p->size, 4); break; case 3: p->buff.resize(0x2000); file->Read(&p->buff[0], 0x2000); break; } packets.push_back(p); } delete file; } sleep(1); //while(IsWindowVisible(hWnd)) //FIXME map? int finished = theApp.GetConfigI("linux_replay"); if (theApp.GetConfigI("dump")) { fprintf(stderr, "Dump is enabled. Replay will be disabled\n"); finished = 1; } unsigned long frame_number = 0; unsigned long total_frame_nb = 0; while(finished > 0) { frame_number = 0; unsigned long start = timeGetTime(); for(auto i = packets.begin(); i != packets.end(); i++) { Packet* p = *i; switch(p->type) { case 0: switch(p->param) { case 0: GSgifTransfer1(&p->buff[0], p->addr); break; case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; } break; case 1: GSvsync(p->param); frame_number++; break; case 2: if(buff.size() < p->size) buff.resize(p->size); GSreadFIFO2(&buff[0], p->size / 16); break; case 3: memcpy(regs, &p->buff[0], 0x2000); break; } } // Ensure the rendering is complete to measure correctly the time. glFinish(); if (finished > 90) { sleep(1); } else { unsigned long end = timeGetTime(); frame_number = std::max(1ul, frame_number); // avoid a potential division by 0 fprintf(stderr, "The %ld frames of the scene was render on %ldms\n", frame_number, end - start); fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number); stats.push_back((float)(end - start)); finished--; total_frame_nb += frame_number; } } if (theApp.GetConfigI("linux_replay") > 1) { // Print some nice stats // Skip first frame (shader compilation populate the result) // it divides by 10 the standard deviation... float n = (float)theApp.GetConfigI("linux_replay") - 1.0f; float mean = 0; float sd = 0; for (auto i = stats.begin()+1; i != stats.end(); i++) { mean += *i; } mean = mean/n; for (auto i = stats.begin()+1; i != stats.end(); i++) { sd += pow((*i)-mean, 2); } sd = sqrt(sd/n); fprintf(stderr, "\n\nMean: %fms\n", mean); fprintf(stderr, "Standard deviation: %fms\n", sd); fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean); fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number); } #ifdef ENABLE_OGL_DEBUG_MEM_BW total_frame_nb *= 1024; fprintf(stderr, "memory bandwith. T: %f KB/f. V: %f KB/f. U: %f KB/f\n", (float)g_real_texture_upload_byte/(float)total_frame_nb, (float)g_vertex_upload_byte/(float)total_frame_nb, (float)g_uniform_upload_byte/(float)total_frame_nb ); #endif for(auto i = packets.begin(); i != packets.end(); i++) { delete *i; } packets.clear(); sleep(1); GSclose(); GSshutdown(); }
// Note EXPORT_C GSReplay(char* lpszCmdLine, int renderer) { GLLoader::in_replayer = true; GSRendererType m_renderer; // Allow to easyly switch between SW/HW renderer -> this effectively removes the ability to select the renderer by function args m_renderer = static_cast<GSRendererType>(theApp.GetConfigI("Renderer")); // alternatively: // m_renderer = static_cast<GSRendererType>(renderer); if (m_renderer != GSRendererType::OGL_HW && m_renderer != GSRendererType::OGL_SW) { fprintf(stderr, "wrong renderer selected %d\n", static_cast<int>(m_renderer)); return; } struct Packet {uint8 type, param; uint32 size, addr; vector<uint8> buff;}; list<Packet*> packets; vector<uint8> buff; uint8 regs[0x2000]; GSinit(); GSsetBaseMem(regs); s_vsync = theApp.GetConfigB("vsync"); void* hWnd = NULL; int err = _GSopen((void**)&hWnd, "", m_renderer); if (err != 0) { fprintf(stderr, "Error failed to GSopen\n"); return; } if (s_gs->m_wnd == NULL) return; { // Read .gs content std::string f(lpszCmdLine); #ifdef LZMA_SUPPORTED GSDumpFile* file = (f.size() >= 4) && (f.compare(f.size()-3, 3, ".xz") == 0) ? (GSDumpFile*) new GSDumpLzma(lpszCmdLine) : (GSDumpFile*) new GSDumpRaw(lpszCmdLine); #else GSDumpFile* file = new GSDumpRaw(lpszCmdLine); #endif uint32 crc; file->Read(&crc, 4); GSsetGameCRC(crc, 0); GSFreezeData fd; file->Read(&fd.size, 4); fd.data = new uint8[fd.size]; file->Read(fd.data, fd.size); GSfreeze(FREEZE_LOAD, &fd); delete [] fd.data; file->Read(regs, 0x2000); GSvsync(1); while(!file->IsEof()) { uint8 type; file->Read(&type, 1); Packet* p = new Packet(); p->type = type; switch(type) { case 0: file->Read(&p->param, 1); file->Read(&p->size, 4); switch(p->param) { case 0: p->buff.resize(0x4000); p->addr = 0x4000 - p->size; file->Read(&p->buff[p->addr], p->size); break; case 1: case 2: case 3: p->buff.resize(p->size); file->Read(&p->buff[0], p->size); break; } break; case 1: file->Read(&p->param, 1); break; case 2: file->Read(&p->size, 4); break; case 3: p->buff.resize(0x2000); file->Read(&p->buff[0], 0x2000); break; } packets.push_back(p); } delete file; } sleep(1); //while(IsWindowVisible(hWnd)) //FIXME map? int finished = theApp.GetConfigI("linux_replay"); if (theApp.GetConfigI("dump")) { fprintf(stderr, "Dump is enabled. Replay will be disabled\n"); finished = 1; } unsigned long frame_number = 0; while(finished > 0) { for(auto i = packets.begin(); i != packets.end(); i++) { Packet* p = *i; switch(p->type) { case 0: switch(p->param) { case 0: GSgifTransfer1(&p->buff[0], p->addr); break; case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; } break; case 1: GSvsync(p->param); frame_number++; break; case 2: if(buff.size() < p->size) buff.resize(p->size); GSreadFIFO2(&buff[0], p->size / 16); break; case 3: memcpy(regs, &p->buff[0], 0x2000); break; } } if (finished >= 200) { ; // Nop for Nvidia Profiler } else if (finished > 90) { sleep(1); } else { finished--; } } #ifdef ENABLE_OGL_DEBUG_MEM_BW unsigned long total_frame_nb = std::max(1ul, frame_number) << 10; fprintf(stderr, "memory bandwith. T: %f KB/f. V: %f KB/f. U: %f KB/f\n", (float)g_real_texture_upload_byte/(float)total_frame_nb, (float)g_vertex_upload_byte/(float)total_frame_nb, (float)g_uniform_upload_byte/(float)total_frame_nb ); #endif for(auto i = packets.begin(); i != packets.end(); i++) { delete *i; } packets.clear(); sleep(1); GSclose(); GSshutdown(); }
EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { GSRendererType renderer = GSRendererType::Undefined; { char* start = lpszCmdLine; char* end = NULL; long n = strtol(lpszCmdLine, &end, 10); if(end > start) {renderer = static_cast<GSRendererType>(n); lpszCmdLine = end;} } while(*lpszCmdLine == ' ') lpszCmdLine++; ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS); if(FILE* fp = fopen(lpszCmdLine, "rb")) { Console console("GSdx", true); GSinit(); uint8 regs[0x2000]; GSsetBaseMem(regs); s_vsync = theApp.GetConfigB("vsync"); HWND hWnd = NULL; _GSopen((void**)&hWnd, "", renderer); uint32 crc; fread(&crc, 4, 1, fp); GSsetGameCRC(crc, 0); GSFreezeData fd; fread(&fd.size, 4, 1, fp); fd.data = new uint8[fd.size]; fread(fd.data, fd.size, 1, fp); GSfreeze(FREEZE_LOAD, &fd); delete [] fd.data; fread(regs, 0x2000, 1, fp); long start = ftell(fp); GSvsync(1); struct Packet {uint8 type, param; uint32 size, addr; vector<uint8> buff;}; list<Packet*> packets; vector<uint8> buff; int type; while((type = fgetc(fp)) != EOF) { Packet* p = new Packet(); p->type = (uint8)type; switch(type) { case 0: p->param = (uint8)fgetc(fp); fread(&p->size, 4, 1, fp); switch(p->param) { case 0: p->buff.resize(0x4000); p->addr = 0x4000 - p->size; fread(&p->buff[p->addr], p->size, 1, fp); break; case 1: case 2: case 3: p->buff.resize(p->size); fread(&p->buff[0], p->size, 1, fp); break; } break; case 1: p->param = (uint8)fgetc(fp); break; case 2: fread(&p->size, 4, 1, fp); break; case 3: p->buff.resize(0x2000); fread(&p->buff[0], 0x2000, 1, fp); break; } packets.push_back(p); } Sleep(100); while(IsWindowVisible(hWnd)) { for(list<Packet*>::iterator i = packets.begin(); i != packets.end(); i++) { Packet* p = *i; switch(p->type) { case 0: switch(p->param) { case 0: GSgifTransfer1(&p->buff[0], p->addr); break; case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; } break; case 1: GSvsync(p->param); break; case 2: if(buff.size() < p->size) buff.resize(p->size); GSreadFIFO2(&buff[0], p->size / 16); break; case 3: memcpy(regs, &p->buff[0], 0x2000); break; } } } for(list<Packet*>::iterator i = packets.begin(); i != packets.end(); i++) { delete *i; } packets.clear(); Sleep(100); /* vector<uint8> buff; bool exit = false; int round = 0; while(!exit) { uint32 index; uint32 size; uint32 addr; int pos; switch(fgetc(fp)) { case EOF: fseek(fp, start, 0); exit = !IsWindowVisible(hWnd); //exit = ++round == 60; break; case 0: index = fgetc(fp); fread(&size, 4, 1, fp); switch(index) { case 0: if(buff.size() < 0x4000) buff.resize(0x4000); addr = 0x4000 - size; fread(&buff[addr], size, 1, fp); GSgifTransfer1(&buff[0], addr); break; case 1: if(buff.size() < size) buff.resize(size); fread(&buff[0], size, 1, fp); GSgifTransfer2(&buff[0], size / 16); break; case 2: if(buff.size() < size) buff.resize(size); fread(&buff[0], size, 1, fp); GSgifTransfer3(&buff[0], size / 16); break; case 3: if(buff.size() < size) buff.resize(size); fread(&buff[0], size, 1, fp); GSgifTransfer(&buff[0], size / 16); break; } break; case 1: GSvsync(fgetc(fp)); exit = !IsWindowVisible(hWnd); break; case 2: fread(&size, 4, 1, fp); if(buff.size() < size) buff.resize(size); GSreadFIFO2(&buff[0], size / 16); break; case 3: fread(regs, 0x2000, 1, fp); break; } } */ GSclose(); GSshutdown(); fclose(fp); } }
// Note EXPORT_C GSReplay(char* lpszCmdLine, int renderer) { GLLoader::in_replayer = true; // lpszCmdLine: // First parameter is the renderer. // Second parameter is the gs file to load and run. //EXPORT_C GSReplay(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) #if 0 int renderer = -1; { char* start = lpszCmdLine; char* end = NULL; long n = strtol(lpszCmdLine, &end, 10); if(end > start) {renderer = n; lpszCmdLine = end;} } while(*lpszCmdLine == ' ') lpszCmdLine++; ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS); #endif // Allow to easyly switch between SW/HW renderer renderer = theApp.GetConfig("renderer", 12); if (renderer != 12 && renderer != 13) { fprintf(stderr, "wrong renderer selected %d\n", renderer); return; } vector<float> stats; stats.clear(); if(FILE* fp = fopen(lpszCmdLine, "rb")) { //Console console("GSdx", true); GSinit(); uint8 regs[0x2000]; GSsetBaseMem(regs); s_vsync = !!theApp.GetConfig("vsync", 0); void* hWnd = NULL; int err = _GSopen((void**)&hWnd, "", renderer); if (err != 0) { fprintf(stderr, "Error failed to GSopen\n"); return; } if (s_gs->m_wnd == NULL) return; uint32 crc; fread(&crc, 4, 1, fp); GSsetGameCRC(crc, 0); GSFreezeData fd; fread(&fd.size, 4, 1, fp); fd.data = new uint8[fd.size]; fread(fd.data, fd.size, 1, fp); GSfreeze(FREEZE_LOAD, &fd); delete [] fd.data; fread(regs, 0x2000, 1, fp); GSvsync(1); struct Packet {uint8 type, param; uint32 size, addr; vector<uint8> buff;}; list<Packet*> packets; vector<uint8> buff; int type; while((type = fgetc(fp)) != EOF) { Packet* p = new Packet(); p->type = (uint8)type; switch(type) { case 0: p->param = (uint8)fgetc(fp); fread(&p->size, 4, 1, fp); switch(p->param) { case 0: p->buff.resize(0x4000); p->addr = 0x4000 - p->size; fread(&p->buff[p->addr], p->size, 1, fp); break; case 1: case 2: case 3: p->buff.resize(p->size); fread(&p->buff[0], p->size, 1, fp); break; } break; case 1: p->param = (uint8)fgetc(fp); break; case 2: fread(&p->size, 4, 1, fp); break; case 3: p->buff.resize(0x2000); fread(&p->buff[0], 0x2000, 1, fp); break; } packets.push_back(p); } sleep(1); //while(IsWindowVisible(hWnd)) //FIXME map? int finished = theApp.GetConfig("linux_replay", 1); unsigned long frame_number = 0; while(finished > 0) { frame_number = 0; unsigned long start = timeGetTime(); for(auto i = packets.begin(); i != packets.end(); i++) { Packet* p = *i; switch(p->type) { case 0: switch(p->param) { case 0: GSgifTransfer1(&p->buff[0], p->addr); break; case 1: GSgifTransfer2(&p->buff[0], p->size / 16); break; case 2: GSgifTransfer3(&p->buff[0], p->size / 16); break; case 3: GSgifTransfer(&p->buff[0], p->size / 16); break; } break; case 1: GSvsync(p->param); frame_number++; break; case 2: if(buff.size() < p->size) buff.resize(p->size); GSreadFIFO2(&buff[0], p->size / 16); break; case 3: memcpy(regs, &p->buff[0], 0x2000); break; } } unsigned long end = timeGetTime(); fprintf(stderr, "The %ld frames of the scene was render on %ldms\n", frame_number, end - start); fprintf(stderr, "A means of %fms by frame\n", (float)(end - start)/(float)frame_number); stats.push_back((float)(end - start)); sleep(1); finished--; } if (theApp.GetConfig("linux_replay", 1) > 1) { // Print some nice stats // Skip first frame (shader compilation populate the result) // it divides by 10 the standard deviation... float n = (float)theApp.GetConfig("linux_replay", 1) - 1.0f; float mean = 0; float sd = 0; for (auto i = stats.begin()+1; i != stats.end(); i++) { mean += *i; } mean = mean/n; for (auto i = stats.begin()+1; i != stats.end(); i++) { sd += pow((*i)-mean, 2); } sd = sqrt(sd/n); fprintf(stderr, "\n\nMean: %fms\n", mean); fprintf(stderr, "Standard deviation: %fms\n", sd); fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean); fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number); } #ifdef ENABLE_OGL_DEBUG_MEM_BW fprintf(stderr, "memory bandwith. T: %f. V: %f\n", (float)g_texture_upload_byte/(float)frame_number/1024, (float)g_vertex_upload_byte/(float)frame_number/1024); #endif for(auto i = packets.begin(); i != packets.end(); i++) { delete *i; } packets.clear(); sleep(1); GSclose(); GSshutdown(); fclose(fp); } else { fprintf(stderr, "failed to open %s\n", lpszCmdLine); } }