7.1 프레임 자원

매 프레임 CPU가 수정해야 하는 자원들을 순환 배열로 관리하여 CPU와 GPU가 놀지 않도록 하기

 

프레임 자원마다 명령 할당자가 필요하다. (GPU가 명령을 다 처리하지 않았어도 다음 프레임 자원을 수정해야 하기 때문에)

상수 버퍼를 매 프레임 수정한다면 프레임 자원마다 상수 버퍼가 필요하다.

void ShapesApp::Update(const GameTimer& gt)
{
    OnKeyboardInput(gt);
	UpdateCamera(gt);

    // Cycle through the circular frame resource array.
    // Update 함수 호출 될때마다 다음 인덱스의 프레임 자원이 현재 프레임 자원이 됨
    mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources; 
    mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();

    // Has the GPU finished processing the commands of the current frame resource?
    // If not, wait until the GPU has completed commands up to this fence point.
    // CPU 처리속도가 GPU 처리속도보다 빨라서 한 바퀴를 돌았는데도 아직도 안 끝난 경우에는 기다림
    if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
    { 
        HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
        ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
        WaitForSingleObject(eventHandle, INFINITE);
        CloseHandle(eventHandle);
    }

	UpdateObjectCBs(gt);
	UpdateMainPassCB(gt);
}

void ShapesApp::Draw(const GameTimer& gt){
// 현재 프레임의 명령 목록들을 구축하고 제출
	mcurrFrameResource->Fence = ++mCurrentFence; // CPU는 현재 프레임 명령 제출을 끝냈음
    mCommandQueue->Signal(mFence.Get(), mCurrentFence); // GPU기준 마지막으로 끝낸 프레임 작업 번호가 무엇인지 설정

7.2 렌더 항목 (RenderItem 구조체)

하나의 물체를 그리는데 필요한 설정들을  모아놓은 구조체

 

1. 물체의 세계 행렬

2. numframesDirty // 물체의 자료가 변해서(위치가 이동했거나 한 경우) 상수 버퍼를 갱신해야 하는 경우 numframesdirty 값을 프레임 자원의 개수로 설정하면 된다.

update문에서 모든 renderitem들의 numframesdirty 값을 확인하는데 값이 0보다 크다면 해당 renderitem이 사용하는 상수 버퍼의 값을 갱신하고 numframesdirty 값을 -1 시킨다. CPU가 프레임 자원을 한바퀴 돌면 모든 프레임 자원의 상수 버퍼 값은 갱신된다.

3. 기하구조 (Mesh Geometry) (GPU와 CPU 메모리에 기하구조가 사용하는 정점 버퍼와 색인 버퍼 자원을 만들게 되는데

이 자원들을 가리키는 Com객체를 멤버로 가지고 있는 구조체)

4. 기본도형 위상구조

5. GPU상 해당 RenderItem이 사용하는 상수 버퍼의 index

 

7.3 물체별 상수 버퍼와 패스별 상수 버퍼

물체별 상수 버퍼는 물체의 world행렬만 가지고 있으면 된다.

패스별 상수 버퍼는 시점 위치, 시야 행렬, 투영 행렬, 화면 크기, 게임 시간 측정치 등 한 프레임에 한번만 수정되는 상수 자료를 가진다.

 

7.4 도형 기하구조

원기둥 메시

구 메시

측지구 메시

7.5 도형 예제

7.7 지형과 파도 예제

 

 

7.6 루트 서명 추가 설명

이전 장에서 다 설명함

서술자 테이블

루트 상수

루트 서술자 

ㄴ 서술자 테이블에서는 자원을 묶을 때 서술자 힙의 핸들을 묶어 줬지만 루트 서술자는 그냥 자원의 가상 주소를 묶으면 된다. (업로드 힙에 올린 상수 버퍼 자원의 서술자 힙을 만들지 않고도 가능한 방법이다.)

 

7.7.5 동적 정점 버퍼

파도 구현할때, 복잡한 물리계산과 충돌 검출을 수행해서 입자들의 새 위치를 구할때

 

상수 버퍼들의 배열을 업로드 힙에 올리는 방법과 유사하다. 이번에는 정점들의 배열을 업로드 버퍼에 담는다.

 

동적 버퍼를 사용하면 CPU에서 새 자료를 GPU 메모리에 전송하는 데 추가 부담이 발생하므로 정적 버퍼로 충분 할때에는 정적 버퍼를 사용하자

 

1. 간단한 애니메이션은 정점 셰이더에서 수행할 수 있다.

2. 텍스처로의 렌더링 기능이나 계산 셰이더 또는 정점 텍스처 조회 기능을 이용할 수 있다.

3. 기하 셰이더를 이용하면 GPU에서 기본도형의 생성 및 파괴 작업을 GPU에서 할 수 있다.

4. 테셀레이션 단계를 이용하면 GPU에서 세밀한 기하구조를 추가할 수 있다.

 

응용 프로그램에서 update뒤에 draw가 실행되므로

update에서 매 프레임 정점 버퍼를 업로드 힙에 갱신하고 draw하면 된다.

 

 

연습문제

1.

세부수준 0 1
세부수준 2 3

2.

셰이더 파일에서 상수 0번 레지스터가 받는 형식
정점 셰이더 부분
DrawRenderItems함수에서 각각의 renderitem의 world 행렬 갱신하는 부분
루트 서명 작성하는 부분

 

연습문제 파일

https://github.com/lemonyun/Directx12_study/tree/main/7/Chapter%207%20Drawing%20in%20Direct3D%20Part%20II/Shapes

 

GitHub - lemonyun/Directx12_study: 2022/06/10

2022/06/10. Contribute to lemonyun/Directx12_study development by creating an account on GitHub.

github.com

 

'읽은 책 > DirectX 12를 이용한 3D 게임 프로그래밍 입문' 카테고리의 다른 글

9. 텍스처 적용  (0) 2022.06.21
8. 조명  (0) 2022.06.20
6. Direct3D의 그리기 연산  (0) 2022.06.16
5. 렌더링 파이프라인  (0) 2022.06.14
4. Direct3D의 초기화(2)  (0) 2022.06.13

+ Recent posts