공부중

[DirectX12]Hello Wolrd Sample - D3D12HelloWindow - 9 본문

Programing/DirectX

[DirectX12]Hello Wolrd Sample - D3D12HelloWindow - 9

곤란 2018. 5. 16. 19:21
반응형
void D3D12HelloWindow::OnRender()
{
	// 장면을 렌더링 하는데 필요한 모든 명령을 기록
	PopulateCommandList();

	// 명령 리스트 실행.
	ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
	m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);

	// 프레임 전환
	ThrowIfFailed(m_swapChain->Present(1, 0));

	WaitForPreviousFrame();
}

 

PopulateCommandList에서 주석에 적힌대로 렌더링시 필요한 모든 명령을 기록했었다.

그리고 명령리스트 배열을 만들어서 m_commandQueue->ExcuteCommandLists 에 명령들을 넣고 실행해주고 있다.

 

명령을 실행한 뒤에 m_swapChain->Present를 통해서 프레임을 전환하고

 

마지막으로 WaitForPreviousFrame 함수를 호출해 주고 있다.

 

내부를 보자.

 

void D3D12HelloWindow::WaitForPreviousFrame()
{
	/*
		진행하기 전에 프레임을 완료 할 때까지 기다리는것이 가장 바람직 하지는 않다.
		이것은 단순하게 구현된 코드이며 D3D12HelloFrameBuffering 샘플은 효율적인 리소스 사용과
		GPU활용을 극대화 하기 위해 Fence(울타리)를 사용 하는 방법을 보여준다.
	*/

	// Fence(울타리) 값 증가를 신호.
	const UINT64 fence = m_fenceValue;
	ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), fence));
	m_fenceValue++;

	// 이전 프레임이 끝날 때 까지 기다린다.
	if (m_fence->GetCompletedValue() < fence)
	{
		ThrowIfFailed(m_fence->SetEventOnCompletion(fence, m_fenceEvent));
		WaitForSingleObject(m_fenceEvent, INFINITE);
	}

	m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
}

 

특별히 진행되는것은 없다. 이 튜토리얼에서는 그리는것 하나 없는 모습이므로 그런것 같다.

여기서 Fence(울타리)라는 것이 있는데. 

한 시스템에서 두개의 처리장치(CPU와 GPU)가 병렬로 실행 되다 보니 여러가지 동기화 문제가 발생하게 되었다.

간단히 예를 들어서 CPU가 위치 이동 계산을 하고 나서 그리는 연산을 GPU에 던져 주었는데

GPU가 그리는 연산을 완료하기 전에 CPU는 계속해서 다음 이동 연산을 하는 경우... 의도하지 않는 곳에 그려지는 문제가 발생!!!!

 

이러한 문제의 해결책으로는 GPU가 명령 대기열의 명령들중 특정 지점까지의 모든 명령을 다 처리할 때까지 CPU를 기다리게 하는것이다.

대기열의 모든(특정 지점까지의) 명령을 처리 하는것을 가리켜서 명령대기열을 비운다 또는 방출(Flush)라고 하는데...

이때 필요한 것이 Fence(울타리)라고 부르는 객체이다.

 

Fence라는것이 있구나 하고 알아두고 다음에 이 부분에 어떤 코드가 들어가는지를 자세히 살펴보는것으로 마무리를 지어야겠다.

 

다음에는 D3D12HelloTriangle프로젝트를 살펴보자.

 

반응형