Перейти к содержанию

Рубрика классы от асов: Вертикальная синхронизация


helldrg

Рекомендуемые сообщения

Здравствуйте! Об этом много написано с применением DirectX и Opengl, но вот с WinAPI я один раз встречал на англоязычном стриме. Выкладываю код класса, возможности: установка фпс приложения и вывод некоторой информации. Имеется не большой баг, что фпс колеблется, но так наверно везде устроено. Может кому то пригодится, меня вот раньше напрягало, когда пустой цикл нагружал процессор на 12 -15%. Если есть идеи как можно улучшить класс с точки зрения производительности, логики и т.д. и т.п. или же есть какая то ошибка недочет пишите! Долой быдло код и необразованность!!!

Вот скриншот вывода информации:

Скрытый текст

download?id=T7LtmSCfvCUbh2DvHMgrhVhTBILH

 

Код:

Скрытый текст

#if !defined(VSYNCCLASS_H)
#include <Windows.h>
#include <stdio.h>

#pragma comment(lib, "winmm.lib")

class VSyncClass
{
public:
	VSyncClass();
	
	void Begin(int fps); // In front of while
	void End(bool printInfo);  // End while

	// Additional function
	float GetSecondsElapsed(LARGE_INTEGER start, LARGE_INTEGER end);
	LARGE_INTEGER GetCounter();
	LARGE_INTEGER GetFrequency();
private:
	LARGE_INTEGER m_perfCountFrequency;
	float m_targetSecondsPerFrame = 0.0f;
	LARGE_INTEGER m_lastCounter = {};
	INT64 m_lastCycleCount = 0;
	bool m_sleepIsGranular = false;
};


#define VSYNCCLASS_H
#endif

 

Скрытый текст

#include "vsyncclass.h"

VSyncClass::VSyncClass()
{
	m_perfCountFrequency = {};
	m_targetSecondsPerFrame = 0.0f;
	m_lastCounter = {};
	m_lastCycleCount = 0;
	m_sleepIsGranular = false;
}

void VSyncClass::Begin(int fps)
{
	QueryPerformanceFrequency(&m_perfCountFrequency);
	m_targetSecondsPerFrame = (1.0f / (float)fps);

	UINT DesiredSchedulerMS = 1;
	m_sleepIsGranular = (timeBeginPeriod(DesiredSchedulerMS) == TIMERR_NOERROR);

	m_lastCounter = GetCounter();
	m_lastCycleCount = __rdtsc();
}

void VSyncClass::End(bool printInfo)
{
	float secondsElapsedForFrame = GetSecondsElapsed(m_lastCounter, GetCounter());
	if (secondsElapsedForFrame < m_targetSecondsPerFrame)
	{
		if (m_sleepIsGranular)
		{
			DWORD sleepMS = (DWORD)(1000.0f * (m_targetSecondsPerFrame - secondsElapsedForFrame));
			if (sleepMS > 0)
			{
				Sleep(sleepMS);
			}
		}

		while (secondsElapsedForFrame < m_targetSecondsPerFrame)
		{
			secondsElapsedForFrame = GetSecondsElapsed(m_lastCounter, GetCounter());
		}
	}

	LARGE_INTEGER endCounter = GetCounter();
	INT64 counterElapsed = endCounter.QuadPart - m_lastCounter.QuadPart;

	INT64 endCycleCount = __rdtsc();
	INT64 cyclesElapsed = endCycleCount - m_lastCycleCount;



	if (printInfo == true)
	{
		double FPS = (double)m_perfCountFrequency.QuadPart / (double)counterElapsed;
		double MSPerFrame = 1000.0f * GetSecondsElapsed(m_lastCounter, endCounter);
		double MCPF = ((double)cyclesElapsed / (1000.0f * 1000.0f));
		char Buffer[256];
		_snprintf_s(Buffer, sizeof(Buffer), "%.02fms/f,  %.02ff/s,  %.02fmc/f\n", MSPerFrame, FPS, MCPF);
		OutputDebugStringA(Buffer);
	}

	m_lastCounter = endCounter;
	m_lastCycleCount = endCycleCount;
}

float VSyncClass::GetSecondsElapsed(LARGE_INTEGER start, LARGE_INTEGER end)
{
	float result = ((float)(end.QuadPart - start.QuadPart) / (float)m_perfCountFrequency.QuadPart);
	return result;
}

LARGE_INTEGER VSyncClass::GetCounter()
{
	LARGE_INTEGER result;
	QueryPerformanceCounter(&result);
	return result;
}

LARGE_INTEGER VSyncClass::GetFrequency()
{
	LARGE_INTEGER result;
	QueryPerformanceFrequency(&result);
	return result;
}

 

В проект добавляется так:

Скрытый текст

            VSyncClass VSync;
			VSync.Begin(30);// Обязательно перед циклом
			while (globalRunning)
			{
				if (PeekMessage(&message, 0, 0, 0, PM_REMOVE))
				{
					TranslateMessage(&message);
					DispatchMessage(&message);
				}
............................................................
				VSync.End(true);//обязательно в конце цикла
			}

 

 

Изменено пользователем helldrg
  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.