Пример #1
0
// 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();
}
Пример #2
0
// 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();
}