[DX12] 장치 초기화(3) (Descriptor 크기 얻기, Descriptor Heap 생성, Render Target View 생성, Depth Stencil View 생성)

도윤·2024년 1월 28일
1

DX12

목록 보기
4/7
post-thumbnail
  • Device 생성
  • 4X MSAA 품질 수준 지원 점검 ( 생략 가능 )
  • CommandQueue, CommandList 생성
  • Fence 생성
  • SwapChain 설정
  • Descriptor 크기 얻기
  • Descriptor Heap 생성, Render Target View 생성, Depth Stencil View 생성

이전 글에서는 DirectX의 명령들을 관리하기 위해 CommandQueue와 CommandList를 생성하고 이 과정에서 CPU와 GPU의 동기화를 맞추기 위해 Fence를 생성해주었다. 마지막으로 렌더링 과정의 SwapChain을 설정하여주었다.

이어서 관리할 Descriptor의 크기를 구한 후, Descriptor Heap들을 만들어보자.

Descriptor 크기 구하기

서술자를 관리할 Heap을 생성하기 이전 서술자의 크기가 GPU마다 다를 수 있기에, 서술자의 크기를 구하여준다.

서술사의 크기를 지정할 변수 선언

// Render Target View
UINT mRtvDescriptorSize = 0;

// Depth Stencil View
UINT mDsvDescriptorSize = 0;

// Constant Buffer View, Shader Resource View, Unordered Access View
UINT mCbvSrvUavDesciptorSize = 0;

서술자 크기 구하기

// Render Target View
mRtvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);

// Depth Stencil View
mDsvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);

// Constant Buffer View, Shader Resource View, Unordered Access Buffer
mCbvSrvUavDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);

Descriptor Heap 생성

모든 서술자들의 크기를 구하였으니, 응용 프로그램에 필요한 서술자/뷰들을 담을 서술자 힙을 만들어야한다.

서술자 힙은 서술자의 종류마다 따로 만들어야 하기에, 이전 글에서 SwapChain이 사용하는 버퍼의 수 만큼의 Render Target View를 담을 서술자 힙과 하나의 Depth Stencil View를 담을 힙이 필요하다.

Render Target View 생성

앞서 말했듯이 SwapChain이 사용하는 버퍼의 수 만큼의 Render Target View가 필요하기에 서술자 힙과 서술자들을 담을 배열 변수를 선언하여준다.

// Render Target View 서술자 힙;
ComPtr<ID3D12DescriptorHeap> mRtvHeap;

// 서술자들을 담을 배열
D3D12_CPU_DESCRIPTOR_HANDLE mSwapChainViews[SwapChainBufferCount] = {};

SwapChain에서 해주었던 것처럼 현재 백버퍼를 바로 가져올 수 있도록 Get 함수를 만들어준다.

D3D12_CPU_DESCRIPTOR_HANDLE GetCurrentBackBufferView() const {
	return mSwapChainViews[mCurBackBuffer];
}

서술자 힙을 생성하여준 후 미리 만들었던 버퍼들을 서술자 뷰에 넣어주는 작업을 해준다.

// 서술자 설정
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
rtvHeadDesc.NumDescriptors = SwapChainBufferCount;		// SwapChain에서 사용할 버퍼의 수만큼 만들어야 한다.
rtvHeadDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeadDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
rtvHeadDesc.NodeMask = 0;

// 서술자 힙 생성
ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&mRtvHeap)));

// Swap Chain을 생성할 때 만들어둔 Buffer들을 RtvView에 넣어줌
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
for(UINT i = 0; i < SwapChainBufferCount; ++i) {
	mSwapChainView[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE(rtvHeapHandle, i * mRtvDescriptorSize);
    md3dDevice->CreateRenderTargetView(mSwapChainBuffers[i].Get(), nullptr, mSwapChainViews[i]);
}

Depth Stencil Buffer, View 생성

이제 깊이 스텐실 버퍼와 뷰를 생성해야 한다. 깊이 버퍼는 가시 물체들의 깊이 정보를 저장하는 텍스쳐. 즉 리소스이므로 서술자를 채운 후 Device를 통해 생성하여 준다.

먼저 Depth Stencil Buffer와 서술자 힙를 선언하여준 후 Render Target View와 같이 View 객체를 담을 배열또한 선언한다. 이 때 Depth Stencil Buffer는 하나만 존재할 것이기에 배열의 크기또한 1로 잡아준다.

// Depth Stencil Buffer 객체
ComPtr<ID3D12Resource> mDepthStencilBuffer;

// 서술자 힙
ComPtr<ID3D12DescriptorHeap> mDsvHeap;

// Depth Stencil View를 담을 배열
D3D12_CPU_DESCRIPTOR_HANDLE mDepthStencilView = {};

마찬가지로 Depth Stencil View도 외부에서 쉽게 접근 할 수 있도록 Get 함수를 만들어준다.

D3D12_CPU_DESCRIPTOR_HANDLE GetDepthStencilView() const {
	return mDepthStencilView;
}

Render Target Bufferd와 Render Target View를 생성할 때와 동일한 과정으로 Depth Stencil Buffer와 Depth Stencil View도 생성하여 주면 된다.

// ----------------------서술자 힙 생성---------------------------------
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
dsvHeapDesc.NumDescriptors = 1;
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
dsvHeapDesc.NodeMask = 0;

ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&mDsvHeap)));
// ------------------------------------------------------------------


// ----------------------Depth Stencil Buffer 생성--------------------
D3D12_RESOURCE_DESC depthStencilDesc;
depthStencilDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
depthStencilDesc.Alignment = 0;
depthStencilDesc.Width = mClientWidth;
depthStencilDesc.Height = mClientHeight;
depthStencilDesc.DepthOrArraySize = 1;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
depthStencilDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
depthStencilDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
depthStencilDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
depthStencilDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

D3D12_CLEAR_VALUE optClear;
optClear.Format = mDepthStencilFormat;
optClear.DepthStencil.Depth = 1.0f;
optClear.DepthStencil.Stencil = 0;

ThrowIfFailed(md3dDevice->CreateCommittedResource(
	&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    D3D12_HEAP_FLAG_NONE,
    &depthStencilDesc,
    D3D12_RESOURCE_STATE_COMMON,
    &optClear,
    IID_PPV_ARGS(&mDepthStencilBuffer)
));
// -----------------------------------------------------------------


// -------------------------Depth Stencil View 생성------------------
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Format = mDepthStencilFormat;
dsvDesc.Texture2D.MipSlice = 0;

mDepthStencilView = mDsvHeap->GetCPUDescriptorHandleForHeapStart();
md3dDevice->CreateDepthStencilView(mDepthStencilBuffer.Get(), &dsvDesc, mDepthStencilView);
// -----------------------------------------------------------------
profile
Game Client Developer

0개의 댓글

관련 채용 정보