공부중

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

Programing/DirectX

[DirectX12]Hello Wolrd Sample - D3D12HelloWindow - 7

곤란 2018. 5. 7. 21:21
반응형
void D3D12HelloWindow::OnInit()
{
	LoadPipeline();
	LoadAssets();
}

길고긴 LoadPipeLine함수가 끝나고 다음은 LoadAssets함수의 내부를 살펴보자.

// sample asset들 불러오기
void D3D12HelloWindow::LoadAssets()
{
	// 명령 리스트 생성
	ThrowIfFailed(m_device->CreateCommandList(0
						  ,D3D12_COMMAND_LIST_TYPE_DIRECT
						  ,m_commandAllocator.Get()
						  ,nullptr
						  ,IID_PPV_ARGS(&m_commandList)));

	/*
		명령리스트는 기록 상태에서 생성되지만 아무것도 없다.
		아직 기록하지는 않고 메인 루프는 닫히기를 기대하므로 지금 닫아라.
	*/
	ThrowIfFailed(m_commandList->Close());

	// 동기화 object 생성. (Fence, 울타리)
	{
		ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
		m_fenceValue = 1;

		// 프레임 동기화에 사용할 이벤트 핸들을 만듭니다.
		m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
		if (m_fenceEvent == nullptr)
		{
			ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
		}
	}
}

그렇게 길지는 않은 코드다.

 

딱히 설명할것은 없고 명령리스트(CommandList) 생성하는 라인이 있지만 딱히 여기 이 샘플에서는 삼각형 조차 찍지 않기 때문에

명령을 기록하는것은 하나도 없다.

 

그리고 하단에 Fence(울타리)라는것을 생성하는데 이 Fence를 이용해서 동기화를 진행한다.

DirectX를 이용할때는 두개의 처리장치(CPU와 GPU)가 병렬로 실행 되다보니 여러가지 동기화 문제가 발생한다.

쉬운 예로는 CPU가 이동 계산을 하고 GPU에게 그리는 연산을 던져주었으나 GPU가 그리는 연산을 끝내기 전에 CPU가 계속해서 이동 계산을 하게되면

실제로 그려져 있는 모습과 실질적인 데이터가 맞지 않게 되므로 문제가 발생!

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

이때 필요한것이 Fence(울타리)이다.

 

아무튼 Fence를 만들고 프레임 동기화에 사용할 이벤트 핸들을 만든다로 LoadAssets함수가 끝이난다..

 

int Win32Application::Run(DXSample* pSample, HINSTANCE hInstance, int nCmdShow)
{
       /*
            생략....
       */

	// Sample을 초기화하십시오. OnInit은 DXSample의 각 하위 구현에서 정의됩니다.
	pSample->OnInit();

	ShowWindow(m_hwnd, nCmdShow);

	// Main sample 루프.
	MSG msg = {};
	while (msg.message != WM_QUIT)
	{
		// 대기열에있는 메시지를 처리합니다.
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	pSample->OnDestroy();

	// WM_QUIT 메시지의이 부분을 Windows로 반환하십시오.
	return static_cast<char>(msg.wParam);
}

OnInit을 처리하고 하단에 ShowWindow를 통해서 만들어진 윈도우를 보여준다.

 

그리고 하단에 Main Sample 루프가 있는데 여기는 무한 루프로 돌고 있으며 WM_QUIT 메시지가 오기전까지는 무한으로 루프를 돌린다.

보통은 GetMassage로 만들어져 있을텐데(Visual Studio 에서 데스크탑 윈도우 생성 마법사 사용시.) 이는 메시지가 올때까지 대기를 하기 떄문에

게임같은것에는 적절하지 않다 (게임에서 아무런 키보드아 마우스 움직임 등이 없다고 해서 게임진행이 멈추지는 않으므로...하지만 어디 지구상에서 그런 게임이 있을것 같다...)

 

PeekMessage는 대기하는것이 없고 메시지가 오면 그때만 true를 리턴한다. 이를 이용해서 그때 그때 메시지가 오는것만 처리할수 있게끔 해버린다.

 

만일 WM_QUIT 메시지를 받고 루프를 빠져나오면 OnDestroy를 Call 하고 메시지를 리턴함으로 끝.

 

이제 남은것은 Update와 Render 그리고 OnDestroy가 남아있다.

 

보통 PeekMessage의 false부분에 update와 Render가 들어가 있는데 여기에는 그렇게 코드가 있지 않다.(이놈들이?!)

        /*
               MiniEngine 
               ModelViewer_VS15
               GameCore.cpp

               상단 코드 생략....
        */

        ShowWindow( g_hWnd, SW_SHOWDEFAULT );

        do
        {
            MSG msg = {};
            while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            if (msg.message == WM_QUIT)
                break;
        }
        while (UpdateApplication(app));	// Returns false to quit loop

        /*

                 하단코드 생략.

        */

MS DirectX Sample에서 MiniEngine이라는 프로젝트는 그렇게 만들어놓고 튜토리얼급 D3D12HelloWorld 프로젝트에는 다른곳에 넣었다..

-_-

 

 

그래서 여기는 어디에 넣었냐 하면...

바로 여기에 넣어버렸다...

LRESULT CALLBACK Win32Application::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	DXSample* pSample = reinterpret_cast<dxsample*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

	switch (message)
	{
	case WM_CREATE:
		{
			// Save the DXSample* passed in to CreateWindow.
			LPCREATESTRUCT pCreateStruct = reinterpret_cast(lParam);
			SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pCreateStruct->lpCreateParams));
		}
		return 0;

	case WM_KEYDOWN:
		if (pSample)
		{
			pSample->OnKeyDown(static_cast(wParam));
		}
		return 0;

	case WM_KEYUP:
		if (pSample)
		{
			pSample->OnKeyUp(static_cast(wParam));
		}
		return 0;

	case WM_PAINT:
		if (pSample)
		{
			pSample->OnUpdate();
			pSample->OnRender();
		}
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}

	// Handle any messages the switch statement didn't.
	return DefWindowProc(hWnd, message, wParam, lParam);
}
</dxsample*>

-_-... WM_PAINT부분에 넣어버렸다...

 

OnUpdate부터는 다음글에서 설명...

 

 

 

 

 

 

 

 

 

반응형