728x90

원문 : http://www.rastertek.com/dx11tut15.html


Tutorial 15: FPS, CPU Usage, and Timers


이번 강좌는 fps, cpu 사용량, 매우 정확한 시간의 기능을 캡슐화하는 새 클래스 3개를 다루어 볼 것입니다. 이번 강좌의 코드는 폰트 엔진 강좌에 기초합니다.


첫번째 새 클래스는 FpsClass입니다. FpsClass는 어플리케이션이 돌아가는 초당 프레임을 기록하는 것을 처리할 것입니다. 매초에 프레임이 몇번 렌더링되는지 아는 것은 우리의 어플리케이션의 성능을 측정하는데 좋은 기준이 됩니다. 이는 받아들일 수 있는 그래픽 렌더링 속도를 결정하는데 사용되는 업계 표준 측정 기준중 하나입니다. 또 새로운 것을 시험해볼때 프레임 스피드에 얼마나 영향을 미칠지 보기위해서도 유용합니다. 새로 추가한 것이 프레임 스피드를 반이나 깍아먹으면 큰 문제가 있다는 것을 이 간단한 카운터를 사용함으로 즉각 알 수 있습니다. 현재 컴퓨터에 대한 표준(보통 기본적인) fps 스피드는 60 fps인 것을 명심하시기 바랍니다. 60 fps밑으로는 퍼포먼스가 좋지 못하다고 여기며 30 밑으로는 사람 눈으로도 알아차릴 수 있습니다. 코딩 시 일반적으로 fps를 최대로 하며 적절히 시행된 새로운 특성이 속도에 심각한 영향을 미치면 문제를 해명해야 하며 최소한 집중할 필요는 있습니다.


두번째 새 클래스는 CpuClass입니다. 이 클래스는 cpu 사용량 기록을 처리할 것이며 그래서 현재 cpu 사용률을 화면에 나타낼 수 있습니다. cpu 사용량을 아는 것은 fps가 사용되는 방법과 비슷하게 새 코드 변화를 디버깅하는데 유용합니다. 현재 시행된 코드나 알고리즘을 확인하는데 간단하고 즉각적인 측정 기준을 제공합니다.


마지막 새 클래스는 TimerClass입니다. 정확성이 아주 좋은 타이머이며 타이밍 이벤트나 우리의 어플리케이션과 다양한 구성요소들을 공통된 시간 프레임으로 동기화하는데 사용할 수 있습니다.


Framework


이번 강좌의 새 클래스 3개와 함께 프레임워크는 다음과 같습니다.



이 새 클래스 3개를 설명하는 것으로 강좌를 시작할 것입니다.



Fpsclass.h


FpsClass는 관련 타이머를 간단하게 재는 것입니다. 1초동안 프레임이 몇번 발생했는지를 세며 지속적으로 갱신합니다.


////////////////////////////////////////////////////////////////////////////////
// Filename: fpsclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _FPSCLASS_H_
#define _FPSCLASS_H_


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


//////////////
// INCLUDES //
//////////////
#include <windows.h>
#include <mmsystem.h>


////////////////////////////////////////////////////////////////////////////////
// Class name: FpsClass
////////////////////////////////////////////////////////////////////////////////
class FpsClass
{
public:
	FpsClass();
	FpsClass(const FpsClass&);
	~FpsClass();

	void Initialize();
	void Frame();
	int GetFps();

private:
	int m_fps, m_count;
	unsigned long m_startTime;
};

#endif


Fpsclass.cpp


///////////////////////////////////////////////////////////////////////////////
// Filename: fpsclass.cpp
///////////////////////////////////////////////////////////////////////////////
#include "fpsclass.h"


FpsClass::FpsClass()
{
}


FpsClass::FpsClass(const FpsClass& other)
{
}


FpsClass::~FpsClass()
{
}


Initialize 함수는 모든 카운터를 0으로 설정하고 타이머를 시작합니다.


void FpsClass::Initialize()
{
	m_fps = 0;
	m_count = 0;
	m_startTime = timeGetTime();
	return;
}


Frame 함수는 반드시 매 프레임마다 호출되어야 하며 호출 시 프레임 카운트를 1 증가시킵니다. 1초가 흘렀다면 m_fps 변수에 프레임 카운트를 저장할 것입니다. 그리고는 카운트를 리셋하고 타이머를 재시작합니다.


void FpsClass::Frame()
{
	m_count++;

	if(timeGetTime() >= (m_startTime + 1000))
	{
		m_fps = m_count;
		m_count = 0;
		
		m_startTime = timeGetTime();
	}
}


GetFps은 지난 마지막 초에 대한 초당 프레임 속도를 반환합니다. 이 함수는 지속적으로 요청되어 화면에 fps가 표시됩니다.


int FpsClass::GetFps()
{
	return m_fps;
}


Cpuclass.h


CpuClass은 매 초에 발생중인 총 cpu 사용의 사용률을 결정하는데 사용됩니다.


///////////////////////////////////////////////////////////////////////////////
// Filename: cpuclass.h
///////////////////////////////////////////////////////////////////////////////
#ifndef _CPUCLASS_H_
#define _CPUCLASS_H_


cpu 사용량을 요청하기 위해 pdh 라이브러리를 사용합니다.


/////////////
// LINKING //
/////////////
#pragma comment(lib, "pdh.lib")


//////////////
// INCLUDES //
//////////////
#include <pdh.h>


///////////////////////////////////////////////////////////////////////////////
// Class name: CpuClass
///////////////////////////////////////////////////////////////////////////////
class CpuClass
{
public:
	CpuClass();
	CpuClass(const CpuClass&);
	~CpuClass();

	void Initialize();
	void Shutdown();
	void Frame();
	int GetCpuPercentage();

private:
	bool m_canReadCpu;
	HQUERY m_queryHandle;
	HCOUNTER m_counterHandle;
	unsigned long m_lastSampleTime;
	long m_cpuUsage;
};

#endif


Cpuclass.cpp


///////////////////////////////////////////////////////////////////////////////
// Filename: cpuclass.cpp
///////////////////////////////////////////////////////////////////////////////
#include "cpuclass.h"


CpuClass::CpuClass()
{
}


CpuClass::CpuClass(const CpuClass& other)
{
}


CpuClass::~CpuClass()
{
}


Initialize 함수는 cpu 사용량 요청 핸들을 설정할 것입니다. 그 쿼리는 각각의 cpu 사용량 대신 시스템의 모든 cpu 사용량을 결합하여 알려줄 것입니다. 만약 쿼리 핸들을 얻을 수 없거나 무슨 이유로서인지 cpu 사용량을 받지 못하면 m_canReadCpu 플래그를 false로 설정하고 cpu 사용량을 0퍼센트로 유지할 것입니다. 일부 cpu와 운영체제 특권 레벨은(ring0 ?) 이 과정을 실패할 수 있습니다. 또 1초에 한번 cpu 사용량을 얻도록 타이머를 시작합니다.


void CpuClass::Initialize()
{
	PDH_STATUS status;


	// Initialize the flag indicating whether this object can read the system cpu usage or not.
	m_canReadCpu = true;

	// Create a query object to poll cpu usage.
	status = PdhOpenQuery(NULL, 0, &m_queryHandle);
	if(status != ERROR_SUCCESS)
	{
		m_canReadCpu = false;
	}

	// Set query object to poll all cpus in the system.
	status = PdhAddCounter(m_queryHandle, TEXT("\\Processor(_Total)\\% processor time"), 0, &m_counterHandle);
	if(status != ERROR_SUCCESS)
	{
		m_canReadCpu = false;
	}

	m_lastSampleTime = GetTickCount(); 

	m_cpuUsage = 0;

	return;
}


Shutdown 함수는 cpu 사용량을 요청하기 위해 사용했던 핸들을 해제합니다.


void CpuClass::Shutdown()
{
	if(m_canReadCpu)
	{
		PdhCloseQuery(m_queryHandle);
	}

	return;
}


FpsClass와 같이 Frame 함수를 매 프레임마다 호출해야 합니다. 요청 횟수를 줄이기 위해 m_lastSampleTime 변수를 사용하여 1초에 한번 얻도록 합니다. 그래서 매초마다 cpu에 사용량을 묻고 m_cpuUsage 변수에 저장합니다. 이 이상은 불필요합니다.


void CpuClass::Frame()
{
	PDH_FMT_COUNTERVALUE value; 

	if(m_canReadCpu)
	{
		if((m_lastSampleTime + 1000) < GetTickCount())
		{
			m_lastSampleTime = GetTickCount(); 

			PdhCollectQueryData(m_queryHandle);
        
			PdhGetFormattedCounterValue(m_counterHandle, PDH_FMT_LONG, NULL, &value);

			m_cpuUsage = value.longValue;
		}
	}

	return;
}


GetCpuPercentage 함수는 현재 cpu 사용량을 호출하는 함수에게 반환합니다. 다시 한번 어떤 이유든지 cpu를 읽을 수 없었을 경우 usage를 0으로 설정합니다.


int CpuClass::GetCpuPercentage()
{
	int usage;

	if(m_canReadCpu)
	{
		usage = (int)m_cpuUsage;
	}
	else
	{
		usage = 0;
	}

	return usage;
}


Timerclass.h


TimerClass은 프레임들의 사이 정확한 시간을 측정하는 정밀도가 높은 타이머입니다. 원래 사용법은 이동에 대해 표준 시간 프레임을 필요로하는 오브젝트들의 동기화를 위함입니다. 이번 강좌에서는 그렇게 사용하지는 않을거지만 코드는 있으니 어떻게 여러분의 프로젝트에 적용할 수 있을지는 볼 수 있을 겁니다. 대부분의 TimerClass의 공통 사용법은 프레임 시간을 사용하여 현재 프레임에 넘겨진 초의 '비율'을 알아내고 그 비율에 따라 오브젝트를 움직입니다.


////////////////////////////////////////////////////////////////////////////////
// Filename: timerclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _TIMERCLASS_H_
#define _TIMERCLASS_H_


//////////////
// INCLUDES //
//////////////
#include <windows.h>


////////////////////////////////////////////////////////////////////////////////
// Class name: TimerClass
////////////////////////////////////////////////////////////////////////////////
class TimerClass
{
public:
	TimerClass();
	TimerClass(const TimerClass&);
	~TimerClass();

	bool Initialize();
	void Frame();

	float GetTime();

private:
	INT64 m_frequency;
	float m_ticksPerMs;
	INT64 m_startTime;
	float m_frameTime;
};

#endif


Timerclass.cpp


///////////////////////////////////////////////////////////////////////////////
// Filename: timerclass.cpp
///////////////////////////////////////////////////////////////////////////////
#include "timerclass.h"


TimerClass::TimerClass()
{
}


TimerClass::TimerClass(const TimerClass& other)
{
}


TimerClass::~TimerClass()
{
}


Initialize 함수는 먼저 시스템에게 고빈도 타이머를 지원하는지 알기 위해 요청을 합니다. 빈도를 반환하면 그 값을 사용하여 밀리초마다 째깍거림이 얼마나 발생할 지를 알아냅니다. 그러면 프레임 시간을 계산하기 위해 각 프레임 마다 이 값을 사용할 수 있습니다. Initialize 함수의 마지막에서 타이밍을 시작하기 위해 프레임의 시작 시간을 요청합니다.


bool TimerClass::Initialize()
{
	// Check to see if this system supports high performance timers.
	QueryPerformanceFrequency((LARGE_INTEGER*)&m_frequency);
	if(m_frequency == 0)
	{
		return false;
	}

	// Find out how many times the frequency counter ticks every millisecond.
	m_ticksPerMs = (float)(m_frequency / 1000);

	QueryPerformanceCounter((LARGE_INTEGER*)&m_startTime);

	return true;
}


Frame 함수는 메인 프로그램 루프마다 호출됩니다. 루프 사이 시간 차이를 계산할 수 있고 이 프레임을 실행하는 시간도 알 수 있습니다. 이 프레임에 대해 시간을 요청하고 계산하고 m_frameTime에 저장하여 동기화를 위해 호출하는 모든 오브젝트에 의해 사용될 수 있습니다. 그리하여 현재 시간을 다음 프레임의 시작으로 저장합니다.


void TimerClass::Frame()
{
	INT64 currentTime;
	float timeDifference;


	QueryPerformanceCounter((LARGE_INTEGER*)& currentTime);

	timeDifference = (float)(currentTime - m_startTime);

	m_frameTime = timeDifference / m_ticksPerMs;

	m_startTime = currentTime;

	return;
}


GetTime는 가장 최근에 계산된 프레임 시간을 반환합니다.


float TimerClass::GetTime()
{
	return m_frameTime;
}


Systemclass.h


이제 새 클래스 3개를 보았으니 프레임에 어떻게 맞출지를 설명할 수 있습니다. 이 클래스들은 SystemClass밑에 위치될 것입니다.


////////////////////////////////////////////////////////////////////////////////
// Filename: systemclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _SYSTEMCLASS_H_
#define _SYSTEMCLASS_H_


///////////////////////////////
// PRE-PROCESSING DIRECTIVES //
///////////////////////////////
#define WIN32_LEAN_AND_MEAN


//////////////
// INCLUDES //
//////////////
#include <windows.h>


///////////////////////
// MY CLASS INCLUDES //
///////////////////////
#include "inputclass.h"
#include "graphicsclass.h"


새 클래스 3개를 여기서 인클루드합니다.


#include "fpsclass.h"
#include "cpuclass.h"
#include "timerclass.h"


////////////////////////////////////////////////////////////////////////////////
// Class name: SystemClass
////////////////////////////////////////////////////////////////////////////////
class SystemClass
{
public:
	SystemClass();
	SystemClass(const SystemClass&);
	~SystemClass();

	bool Initialize();
	void Shutdown();
	void Run();

	LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);

private:
	bool Frame();
	void InitializeWindows(int&, int&);
	void ShutdownWindows();

private:
	LPCWSTR m_applicationName;
	HINSTANCE m_hinstance;
	HWND m_hwnd;

	InputClass* m_Input;
	GraphicsClass* m_Graphics;


각 새 클래스에 대해 객체를 만듭니다.


	FpsClass* m_Fps;
	CpuClass* m_Cpu;
	TimerClass* m_Timer;
};


/////////////////////////
// FUNCTION PROTOTYPES //
/////////////////////////
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


/////////////
// GLOBALS //
/////////////
static SystemClass* ApplicationHandle = 0;


#endif


Systemclass.cpp


폰트 강좌 이후 이 클래스에 변화된 부분만 다룰 것입니다.


////////////////////////////////////////////////////////////////////////////////
// Filename: systemclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "systemclass.h"


SystemClass::SystemClass()
{
	m_Input = 0;
	m_Graphics = 0;


생성자에서 새 객체 3개를 null로 초기화합니다.


	m_Fps = 0;
	m_Cpu = 0;
	m_Timer = 0;
}


bool SystemClass::Initialize()
{
	int screenWidth, screenHeight;
	bool result;


	// Initialize the width and height of the screen to zero before sending the variables into the function.
	screenWidth = 0;
	screenHeight = 0;

	// Initialize the windows api.
	InitializeWindows(screenWidth, screenHeight);

	// Create the input object.  This object will be used to handle reading the keyboard input from the user.
	m_Input = new InputClass;
	if(!m_Input)
	{
		return false;
	}

	// Initialize the input object.
	result = m_Input->Initialize(m_hinstance, m_hwnd, screenWidth, screenHeight);
	if(!result)
	{
		MessageBox(m_hwnd, L"Could not initialize the input object.", L"Error", MB_OK);
		return false;
	}

	// Create the graphics object.  This object will handle rendering all the graphics for this application.
	m_Graphics = new GraphicsClass;
	if(!m_Graphics)
	{
		return false;
	}

	// Initialize the graphics object.
	result = m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd);
	if(!result)
	{
		return false;
	}


FpsClass를 생성하고 초기화합니다.


	// Create the fps object.
	m_Fps = new FpsClass;
	if(!m_Fps)
	{
		return false;
	}

	// Initialize the fps object.
	m_Fps->Initialize();


CpuClass를 생성하고 초기화합니다.


	// Create the cpu object.
	m_Cpu = new CpuClass;
	if(!m_Cpu)
	{
		return false;
	}

	// Initialize the cpu object.
	m_Cpu->Initialize();


TimerClass를 생성하고 초기화합니다.


	// Create the timer object.
	m_Timer = new TimerClass;
	if(!m_Timer)
	{
		return false;
	}

	// Initialize the timer object.
	result = m_Timer->Initialize();
	if(!result)
	{
		MessageBox(m_hwnd, L"Could not initialize the Timer object.", L"Error", MB_OK);
		return false;
	}

	return true;
}


void SystemClass::Shutdown()
{


Shutdown 함수내 여기서 새 클래스 객체들을 해제합니다.


	// Release the timer object.
	if(m_Timer)
	{
		delete m_Timer;
		m_Timer = 0;
	}

	// Release the cpu object.
	if(m_Cpu)
	{
		m_Cpu->Shutdown();
		delete m_Cpu;
		m_Cpu = 0;
	}

	// Release the fps object.
	if(m_Fps)
	{
		delete m_Fps;
		m_Fps = 0;
	}

	// Release the graphics object.
	if(m_Graphics)
	{
		m_Graphics->Shutdown();
		delete m_Graphics;
		m_Graphics = 0;
	}

	// Release the input object.
	if(m_Input)
	{
		m_Input->Shutdown();
		delete m_Input;
		m_Input = 0;
	}

	// Shutdown the window.
	ShutdownWindows();
	
	return;
}


마지막 변화는 Frame 함수입니다. 각 새 클래스들은 어플리케이션이 거치는 각 프레임에 대해 클래스마다 있는 Frame 함수를 호출해야 합니다. 각 Frame이 호출되고 나면 각각의 업데이트된 데이터를 요청할 수 있고 사용하도록 GraphicsClass에 보낼 수 있습니다.


bool SystemClass::Frame()
{
	bool result;


	// Update the system stats.
	m_Timer->Frame();
	m_Fps->Frame();
	m_Cpu->Frame();

	// Do the input frame processing.
	result = m_Input->Frame();
	if(!result)
	{
		return false;
	}

	// Do the frame processing for the graphics object.
	result = m_Graphics->Frame(m_Fps->GetFps(), m_Cpu->GetCpuPercentage(), m_Timer->GetTime());
	if(!result)
	{
		return false;
	}

	// Finally render the graphics to the screen.
	result = m_Graphics->Render();
	if(!result)
	{
		return false;
	}

	return true;
}


Graphicsclass.h


////////////////////////////////////////////////////////////////////////////////
// Filename: graphicsclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _GRAPHICSCLASS_H_
#define _GRAPHICSCLASS_H_


/////////////
// GLOBALS //
/////////////
const bool FULL_SCREEN = true;


이번 강좌에는 vsync를 껐으며 그래서 어플리케이션이 최대빠르기로 실행될 것입니다.


const bool VSYNC_ENABLED = false;
const float SCREEN_DEPTH = 1000.0f;
const float SCREEN_NEAR = 0.1f;


///////////////////////
// MY CLASS INCLUDES //
///////////////////////
#include "d3dclass.h"
#include "cameraclass.h"
#include "textclass.h"


////////////////////////////////////////////////////////////////////////////////
// Class name: GraphicsClass
////////////////////////////////////////////////////////////////////////////////
class GraphicsClass
{
public:
	GraphicsClass();
	GraphicsClass(const GraphicsClass&);
	~GraphicsClass();

	bool Initialize(int, int, HWND);
	void Shutdown();
	bool Frame(int, int, float);
	bool Render();

private:
	D3DClass* m_D3D;
	CameraClass* m_Camera;
	TextClass* m_Text;
};

#endif


Graphicsclass.cpp


폰트 강좌이후 달라진 함수만 살펴볼 것입니다.


////////////////////////////////////////////////////////////////////////////////
// Filename: graphicsclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "graphicsclass.h"


Frame 함수는 이제 fps, cpu, 타이머 카운트들을 취합니다. fps와 cpu 카운트는 TextClass에 설정되어 화면에 렌더링 됩니다.


bool GraphicsClass::Frame(int fps, int cpu, float frameTime)
{
	bool result;


	// Set the frames per second.
	result = m_Text->SetFps(fps, m_D3D->GetDeviceContext());
	if(!result)
	{
		return false;
	}

	// Set the cpu usage.
	result = m_Text->SetCpu(cpu, m_D3D->GetDeviceContext());
	if(!result)
	{
		return false;
	}

	// Set the position of the camera.
	m_Camera->SetPosition(0.0f, 0.0f, -10.0f);

	return true;
}


Textclass.h


////////////////////////////////////////////////////////////////////////////////
// Filename: textclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _TEXTCLASS_H_
#define _TEXTCLASS_H_

///////////////////////
// MY CLASS INCLUDES //
///////////////////////
#include "fontclass.h"
#include "fontshaderclass.h"


////////////////////////////////////////////////////////////////////////////////
// Class name: TextClass
////////////////////////////////////////////////////////////////////////////////
class TextClass
{
private:
	struct SentenceType
	{
		ID3D11Buffer *vertexBuffer, *indexBuffer;
		int vertexCount, indexCount, maxLength;
		float red, green, blue;
	};

	struct VertexType
	{
		D3DXVECTOR3 position;
		D3DXVECTOR2 texture;
	};

public:
	TextClass();
	TextClass(const TextClass&);
	~TextClass();

	bool Initialize(ID3D11Device*, ID3D11DeviceContext*, HWND, int, int, D3DXMATRIX);
	void Shutdown();
	bool Render(ID3D11DeviceContext*, D3DXMATRIX, D3DXMATRIX);


fps 카운트와 cpu 사용량을 설정하는 것에 대한 새로운 함수 2개가 추가되었습니다.


	bool SetFps(int, ID3D11DeviceContext*);
	bool SetCpu(int, ID3D11DeviceContext*);

private:
	bool InitializeSentence(SentenceType**, int, ID3D11Device*);
	bool UpdateSentence(SentenceType*, char*, int, int, float, float, float, ID3D11DeviceContext*);
	void ReleaseSentence(SentenceType**);
	bool RenderSentence(ID3D11DeviceContext*, SentenceType*, D3DXMATRIX, D3DXMATRIX);

private:
	FontClass* m_Font;
	FontShaderClass* m_FontShader;
	int m_screenWidth, m_screenHeight;
	D3DXMATRIX m_baseViewMatrix;
	SentenceType* m_sentence1;
	SentenceType* m_sentence2;
};

#endif


Textclass.cpp


폰트 강좌 이후 달라진 함수만 다룰 것입니다.


///////////////////////////////////////////////////////////////////////////////
// Filename: textclass.cpp
///////////////////////////////////////////////////////////////////////////////
#include "textclass.h"


SetFps 함수는 fps 정수 값을 취하여 문자열로 변환합니다. fps 카운트가 문자열이 되면 또 다른 fps 스피드가는 것을 나타내는 접두사를 가진 관련 문자열을 얻습니다. 그 후에 렌더링을 위해 문장 구조체에 저장합니다. SetFps 함수는 60 fps 이상이면 fps 문자열을 초록색으로 60 밑으로는 노란색, 30밑으로는 빨간색으로 설정합니다.


bool TextClass::SetFps(int fps, ID3D11DeviceContext* deviceContext)
{
	char tempString[16];
	char fpsString[16];
	float red, green, blue;
	bool result;


	// Truncate the fps to below 10,000.
	if(fps > 9999)
	{
		fps = 9999;
	}

	// Convert the fps integer to string format.
	_itoa_s(fps, tempString, 10);

	// Setup the fps string.
	strcpy_s(fpsString, "Fps: ");
	strcat_s(fpsString, tempString);

	// If fps is 60 or above set the fps color to green.
	if(fps >= 60)
	{
		red = 0.0f;
		green = 1.0f;
		blue = 0.0f;
	}

	// If fps is below 60 set the fps color to yellow.
	if(fps < 60)
	{
		red = 1.0f;
		green = 1.0f;
		blue = 0.0f;
	}

	// If fps is below 30 set the fps color to red.
	if(fps < 30)
	{
		red = 1.0f;
		green = 0.0f;
		blue = 0.0f;
	}

	// Update the sentence vertex buffer with the new string information.
	result = UpdateSentence(m_sentence1, fpsString, 20, 20, red, green, blue, deviceContext);
	if(!result)
	{
		return false;
	}

	return true;
}


SetCpu 함수는 SetFps 함수와 비슷합니다. cpu값을 위하여 문장 구조체에 저장될 문자열로 변환하고 렌더링됩니다.


bool TextClass::SetCpu(int cpu, ID3D11DeviceContext* deviceContext)
{
	char tempString[16];
	char cpuString[16];
	bool result;


	// Convert the cpu integer to string format.
	_itoa_s(cpu, tempString, 10);

	// Setup the cpu string.
	strcpy_s(cpuString, "Cpu: ");
	strcat_s(cpuString, tempString);
	strcat_s(cpuString, "%");

	// Update the sentence vertex buffer with the new string information.
	result = UpdateSentence(m_sentence2, cpuString, 20, 40, 0.0f, 1.0f, 0.0f, deviceContext);
	if(!result)
	{
		return false;
	}

	return true;
}


요약



우리의 씬을 렌더링하는 동안 FPS와 CPU 사용량을 볼 수 있습니다. 우리는 이제 정확한 타이머를 가지게 되어 어플리케이션이 실행되는 속도와 상관없이 오브젝트들의 이동과 회전이 일정하게 하기 위해 타이머를 사용할 수 있습니다.



연습하기


1. 코드를 컴파일하고 fps와 cpu 사용량이 보이는지 확인해 보세요. esc키로 종료하세요.


2. graphicsclass.h 파일의 vsync를 켜서 여러분의 비디오 카드/모니터가 어플리케이션을 잠그는 재생률이 몇인지를 확인해 보세요.

728x90

+ Recent posts