일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 이진탐색
- MYSQL
- SQL
- Dijkstra
- 스토어드 프로시저
- two pointer
- Stored Procedure
- binary search
- 다익스트라
- 그래프
- Hash
- Brute Force
- union find
- Two Points
- DP
- String
- Trie
- Today
- Total
codingfarm
4. 자원과 서술자 / Descriptor Heap, RTV, DSV 본문
자원
- GPU가 data를 기록하거나 읽어들이는 대상
- ex : back buffer, depth buffer, stencil buffer, 표면의 모습을 서술하는 texture, 장면안의 기하 구조의 3차원 위치들을 담는 버퍼...
렌더링 시 GPU의 주요 작업
- 자원들에 data를 write
- 자원들에서 data를 read
바인딩(Binding)
- 그리기 명령 제출 전, 해당 그리기 호출이 참조할 자원들을 렌더링 파이프에 묶는(bind)것
- 이를 가리켜 "자원을 파이프 라인에 연결(link)한다 또는 바인딩(binding)한다 라고 말하기도 한다.
- 그리기 호출마다 달라지는 자원도 있으며, 필요에 따라 그리기 호출마다 그런 자원들의 binding을 갱신해 주어야 한다.
- GPU 자원들이 직접 파이프 라인에 묶이는게 아니라, 해당 자원을 참조하는 서술자(Descriptor) 객체가 묶인다.
서술자(Descriptor)
docs.microsoft.com/en-us/windows/win32/direct3d12/descriptors
Descriptors are the primary unit of binding for a single resource in D3D12.
- 자원을 GPU에게 서술해주는 경량의 자료구조, 간접층(level of indirection)
- GPU는 자원서술자를 통해 여러 기능들을 수행한다.
- 자원의 실제 자료에 접근
- 자료를 사용하는데 필요한 정보(resource, mip-map...) 획득
- 존재 이유
- GPU 자원은 범용적인 메모리 조각에 불과하므로 GPU나 프로그래머는 서로의 data의 용도를 알 방법이 없음
- 자원 자체는 자신의 용도(렌더 대상, 깊이 스텐실 버퍼, 셰이더 자원...)에 대한 정보를 담지 않으므로
- 자원자료의 지정 및 자원을 GPU에게 서술하기 위해 존재
- ex
- 동일한 자원일지라도 pipeline의 다른 단계들에서 쓰기 위해
- 자원 자체에는 사용 목적에 대해 명시되어 있지 않으므로
- 가령 texture를 렌더 대상 및 shader 자원으로 사용
- 자원 자체에는 사용 목적에 대해 명시되어 있지 않으므로
- 자원의 일부 영역만 rendering pipeline에 묶고 싶을때
- 자원자체에는 영역에 관한 정보가 없으므로
- 자원을 무형식으로 생성하기 위해
- GPU는 자원의 형식을 모르므로
- 동일한 자원일지라도 pipeline의 다른 단계들에서 쓰기 위해
- ex
$\therefore$ 서술자는 Direct3d에게 자원의 사용법을 설명해준다. (사용법 : 자원을 pipeline 어떤 단계에 묶을지)
- 서술자는 자원의 사용법에 따라 여러 종류(형식)가 있다.
- CBV/SRV/UAV 서술자들 : 각각 상수 버퍼(constant buffer), 셰이더 자원(shader resource), 순서 없는 접근(unordered access view)을 서술
- 표본추출기 서술자 : 텍스처 적용에 쓰이는 표본 추출기(sampler) 자원을 서술
- RTV 서술자 : 렌더 대상(render target) 자원을 서술
- DSV 서술자 : 깊이$\cdot$스텐실(depth/stencil) 자원을 서술
- descriptor들은 GPU에 따라 다양한 크기를 가지며, SRV와 UAV, CBV의 크기를 ID3D12Device::GetDescriptorHandleIncrementSize 함수를 호출하여 구할 수 있다.
- descriptor들은 아래그림처럼 분할될 수 없는 단위로써 다뤄진다.
- API함수를 호출하여 생성된다.
- 하나의 자원을 참조하는 서술자는 여러개일수도 있다.
- ex) 한 자원의 여러 부분영역을 여러 서술자가 참조
- 한 자원을 렌더링 파이프 라인의 여러 단계에 개별적인 서술자로 묶음
- 하나의 텍스쳐를 렌더대상이나 셰이더자원으로 사용
- 이 경우 RTV 및 SRV 서술자가 쓰인다.
- 서술자들은 응용 프로그램의 초기화 시점에 생성되어야 함
- 초기화 시점에 일정정도의 형식점검과 유호셩 검증이 발생함
- 형식이 완전히 지정된 자원은 런타임에 대한 접근을 최적화 할 수 있게 함(DirectX SDK 문서)
- 즉, 무형식 자원은 필요할때만 쓸것
서술자 힙(Desciptor Heap)
- 서술자들의 배열
- 응용 프로그램이 사용하는 서술자들이 저장되는 곳
- 서술자 종류마다 개별적인 서술자 힙이 필요
- 같은 종류의 서술자들은 같은 서술자 힙에 저장됨
- 한 종류에 서술자 힙에 대해 여러 개의 힙을 둘 수도 있음
Descriptor Heap 생성
descriptor heap은 ID3D12DescriptorHeap 인터페이스로 대표된다.
힙을 생성하는 메서드는 ID3D12Device::CreateDescriptorHeap이다.
이번 장의 예제 프로그램에는 SwapChainBuferCount에 설정된 갯수 만큼의 렌더 대상 뷰(render target view, RTV)들과 하나의 깊이$\cdot$스텐실 뷰(depth/stencil view, DSV)가 필요하다.
렌더 대상 뷰는 교환 사슬에서 렌더링의 대상이 되는 버퍼 자원을 서술하고,
깊이$\cdot$스텐실 뷰는 깊이 판정을 위한 버퍼 자원을 서술한다. 서술자 힙은 서술자 종류마다 따로 만들어야 한다.
따라서, 이번 장의 예에서는 SwapChainBufferCount 개의 RTV들을 담을 힙 하나와 하나의 DSV를 담을 힙이 필요하다.
서술자 종류가 다르더라도 생성 함수(CreateDescriptorHeap)는 똑같으며 descriptor heap desc 구조체의 초기화 방법(D3D12_DESCRIPTOR_HEAP_DESC.Type)이 달라질뿐이다.
다음은 이 heap들을 생성하는 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mDsvHeap;
void D3DApp::CreateRtvAndDsvDescriptorHeaps() {
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
rtvHeapDesc.NumDescriptors = SwapChainBufferCount;
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
rtvHeapDesc.NodeMask = 0;
ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
&rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
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.GetAddressOf())));
}
|
cs |
예제 프레임워크에는 다음과 같은 정의가 있다.
1
2
|
static const int SwapChainBufferCount = 2;
int mCurrBackBuffer = 0;
|
cs |
렌더링시 예제 프레임워크는 mCurrBackBuffer를 현재 후면 버퍼의 색인으로 갱신한다.(페이지 전환에 의해 전면 버퍼와 후면 버퍼가 교환되는 작업에서, 어떤 버퍼를 렌더 대상으로 사용해야하는지 알려면 현재 후면 버퍼가 무엇인지 알아야 한다.)
heap을 성공적으로 생성하고 나면 heap에 저장된 descriptor들에 접근할 수 있다. 예제 프로그램은 핸들을 통해서 descriptor들을 참조한다. heap의 첫 descriptor에 대한 핸들은 ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart 메서드로 얻는다. 다음은 각각 현재의 후면 버퍼 RTV와 DSV에 대한 핸들을 얻는 함수들이다.
1
2
3
4
5
6
7
8
9
10
|
D3D12_CPU_DESCRIPTOR_HANDLE D3DApp::CurrentBackBufferView() const {
return CD3DX12_CPU_DESCRIPTOR_HANDLE(
mRtvHeap->GetCPUDescriptorHandleForHeapStart(),
mCurrBackBuffer,
mRtvDescriptorSize);
}
D3D12_CPU_DESCRIPTOR_HANDLE D3DApp::DepthStencilView() const {
return mDsvHeap->GetCPUDescriptorHandleForHeapStart();
}
|
cs |
첫 함수는 descriptor의 크기가 필요한 상황의 예이다. 현재 후면 버퍼 RTV 서술자의 오프셋을 얻으려면 RTV 서술자의 크기(바이트 개수)를 알아야 한다.
렌더 대상 뷰(RTV) 생성
앞서 말했듯이 자원 자체를 직접 파이프라인의 단계에 묶지는 않는다. 대신 반드시 자원에 대한 view(descriptor)를 생성해서 그 view를 파이프라인 단계에 묶어야 한다. 특히, 후면 버퍼를 파이프라인의 출력 병합기(output merger)단계에 묶으려면(그래야 Direct3d가 장면을 후면 버퍼에 렌더링할 수 있다) 후면 버퍼에 대한 렌더 대상 뷰를 생성해야 한다.
우선 할 일은 교환 사슬에 저장되어 있는 버퍼 자원을 얻는것인데, 이를 위해 다음과 같은 메서드를 사용한다.
1
2
3
4
5
|
HRESULT IDXGISwapChain::GetBuffer(
UINT Buffer,
REFIID riid,
void **ppSurface
);
|
cs |
매개변수 | 기능 |
Buffer | 얻고자 하는 특정 후면 버퍼를 식별하는 색인 |
riid | 그 후면 버퍼를 나타내는 ID3D12Resource 인터페이스의 COM ID |
ppSurface | 그 후면 버퍼를 나타내는 ID3D12Resource를 가리키는 포인터가 이 매개변수를 통해서 반환된다. |
SwapChain에 저장된 특정 색인(Buffer)의 버퍼자원을 가져와 ppSurface로 전달된 특정 리소스 변수에 저장한다.
위 메서드를 호출하면 해당 후면 버퍼의 COM 참조 횟수가 증가한다. 따라서 버퍼를 다 사용한 후에는 반드시 해제해야 한다. ComPtr을 사용하면 해제가 자동으로 처리된다.
렌더 대상 뷰를 생성할 때에는 ID3D12Device::CreateRednerTargetView 메서드를 사용한다.
1
2
3
4
5
|
void ID3D12Device::CreateRenderTargetView(
ID3D12Resource *pResource,
const D3D12_RENDER_TARGET_VIEW_DESC *pDesc,
D3D12_CPU_DESCRIPTOR_HANDLE DestDescriptor
);
|
cs |
매개변수 | 기능 |
pResource | 렌더 대상으로 사용할 자원을 가리키는 포인터. 지금 예에서 자원은 후면 버퍼이다. (즉, 후면 버퍼에 대한 렌더 대상 뷰를 생성한다). |
pDesc | D3D12_RENDER_TARGET_VIEW_DESC를 가리키는 포인터. 이 구조체는 렌더 대상 뷰를 서술하는데, 특히 자원에 담긴 원소들의 자료 형식에 관한 멤버를 가지고 있다. 구체적인 자료 형식을 지정해서 자원을 생성했다면(즉, 무형식 자원이 아니면) 이 매개변수에 널 포인터를 지정해도 된다. 그런 경우 이 메서드는 그 자원을 생성할 때 지정한 자료 형식을 적용해서 그 자원의 첫 번째 밉맵 수준에 대한 뷰를 생성한다(후면 버퍼에는 밉맵 수준이 하나뿐이다.) (밉맵은 9장에서 논의한다.) 지금은 후면 버퍼에 대한 뷰를 생성하는 중이므로, 이 매개변수에 널 포인터를 지정한다. |
DescDescriptor | 생성된 렌더 대상 뷰가 저장될 서술자의 핸들 |
서술 구조체 정보(pDesc)를 참조하여 특정 자원(pResource)를 서술할 Descriptor를 생성하고 이를 Descriptor Heap를 가리키는 핸들(DestDescriptor)에 저장한다.
다음은 이 메서드를 이용해서 교환 사슬의 두 버퍼에 대해 가각 RTV를 생성하는 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
Microsoft::WRL::ComPtr<ID3D12Resource> mSwapChainBuffer[SwapChainBufferCount];
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(
mRtvHeap->GetCPUDescriptorHandleForHeapStart());
for (UINT i = 0; i < SwapChainBufferCount; i++) {
// 교환 사슬의 i번째 버퍼를 얻는다.
ThrowIfFailed(mSwapChain->GetBuffer(
i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
// 그 버퍼에 대한 RTV를 생성한다.
md3dDevice->CreateRenderTargetView(
mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
// 힙의 다음 항목으로 넘어간다.
rtvHeapHandle.Offset(1, mRtvDescriptorSize);
}
|
cs |
종류 | resource | descriptor | descriptor heap |
저장 장소 | ComPtr<ID3D12Resource> (back buffer) |
heap 내부 | D3D12_CPU_DESCRIPTOR_HANDLE (heap handle) |
깊이$\cdot$스텐실 버퍼와 뷰(DSV)생성
깊이$\cdot$스텐실 버퍼를 생성해보자
깊이 버퍼는 가장 가까운 가시 물체들의 깊이 정보를 저장하는 2차원 텍스처이다.
텍스처는 GPU 자원의 하나이므로, 텍스처 자원을 서술하는 D3D12_RESOURCE_DESC 구조체를 채운 후 ID3D12Device::CreateCommittedResource를 호출하면 깊이$\cdot$스텐실 버퍼를 생성할 수 있다. D3D12_RESOURCE_DESC 구조체의 정의는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
11
12
|
typedef struct D3D12_RESOURCE_DESC {
D3D12_RESOURCE_DIMENSION Dimension;
UINT64 Alignment;
UINT64 Width;
UINT Height;
UINT16 DepthOrArraySize;
UINT16 MipLevels;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D12_TEXTURE_LAYOUT Layout;
D3D12_RESOURCE_FLAGS Flags;
} D3D12_RESOURCE_DESC;
|
cs |
매개변수 | 기능 |
Dimension | 자원의 차원 D3D12_RESOURCE_DIMENSION 열거값들 중 하나를 지정한다. typedef enum D3D12_RESOURCE_DIMENSION { D3D12_RESOURCE_DIMENSION_UNKNOWN, D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_DIMENSION_TEXTURE1D, D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_DIMENSION_TEXTURE3D } ; |
Width | 텍스처의 너비(텍셀 단위) 버퍼 자원의 경우에는 버퍼의 바이트 갯수를 지정한다. |
Height | 텍스처의 높이(텍셀 단위) |
DepthOrArraySize | 3차원 텍스처의 깊이(텍셀 단위) 또는 1차원 및 2차원 텍스처 배열 크기 3차원 텍스처들의 배열은 지원하지 않음을 주의 |
MipLevels | 밉맵 수준 갯수. 밉맵은 텍스처 적용을 다루는 9장에서 설명한다. 깊이$\cdot$스텐실 버퍼로 사용할 텍스처에는 밉맵 수준이 하나만 있으면 된다. |
Format | 텍셀의 자료 형식. DXGI_FORMAT 열거형의 한 멤버를 지정한다. 깊이$\cdot$스텐실 버퍼에는 "깊이 버퍼링"에서 소개한 타입중 하나를 사용한다. |
SampleDesc | 다중 표본화의 표본 갯수와 품질 수준 다중표본화에 대한 이론을 참고하라 깊이$\cdot$스텐실 버퍼에 적용하는 다중 표본화 설정들은 렌더 대상에 쓰인 설정들과 부합해야 한다. 4X MSAA에서는 픽셀당 네 개의 부분픽셀에 대한 색상과 깊이$\cdot$스텐실 정보를 저장해야 하므로 후면 버퍼와 깊이 버퍼가 화면 해상도의 네 배(4X)이어야 함을 기억할 것이다. |
Layout | 텍스처의 배치(layout). D3D12_TEXTURE_LAYOUT 열거형의 한 멤버를 지정한다. 일단 지금은 텍스처 배치에 신경쓸 필요가 없다. 그냥 D3D12_TEXTURE_LAYOUT_UNKNOWN을 지정하면 된다. |
Flags | 기타 자원 플래그들. 깊이$\cdot$스텐실 버퍼 자원의 경우에는 D3D12_RESOURCE_MISC_DEPTH_STENCIL을 지정한다. |
GPU 자원들은 GPU의 힙에 존재한다. 본질적으로 GPU 힙은 GPU 메모리의 블록인데, 특정한 속성들을 가지고 있다. ID3D12Device::CreateCommittedResource 메서드는 자원을 생성하고, 지정된 속성들에 부합하는 힙에 그 자원을 맡긴다.(commit)
1
2
3
4
5
6
7
8
9
|
HRESULT CreateCommittedResource(
const D3D12_HEAP_PROPERTIES *pHeapProperties,
D3D12_HEAP_FLAGS HeapFlags,
const D3D12_RESOURCE_DESC *pDesc,
D3D12_RESOURCE_STATES InitialResourceState,
const D3D12_CLEAR_VALUE *pOptimizedClearValue,
REFIID riidResource,
void **ppvResource
);
|
cs |
1
2
3
4
5
6
7
|
typedef struct D3D12_HEAP_PROPERTIES {
D3D12_HEAP_TYPE Type;
D3D12_CPU_PAGE_PROPERTY CPUPageProperty;
D3D12_MEMORY_POOL MemoryPoolPreference;
UINT CreationNodeMask;
UINT VisibleNodeMask;
} D3D12_HEAP_PROPERTIES;
|
cs |
매개변수
1. D3D12_HEAP_PROPERTIES *pHeapProperties
자원을 맡길 힙의 속성들을 담은 구조체를 가리키는 포인터.
일부 속성들은 고급 응용에나 필요하다.
현재 우리의 주된 관심사는 heap의 종류를 뜻하는 D3D12_HEAP_TYPE 형식의 멤버인데, 이 열거형에는 다음과 같은 멤버들이 있다.
(a) D3D12_HEAP_TYPE_DEFAULT
기본힙.
전적으로 GPU가 접근할 자원들이 담긴다.
깊이$\cdot$스텐실 버퍼가 그런 자원의 예이다.
깊이$\cdot$스텐실 버퍼를 읽고 쓰는 것은 전적으로 GPU이기 때문이다. CPU가 깊이$\cdot$스텐실 버퍼에 접근할 필요는 전혀 없으므로, 깊이$\cdot$스텐실 버퍼는 기본 힙에 넣는 것이 좋다.
(b) D3D12_HEAP_TYPE_UPLOAD
자료 올리기(upload) 힙.
CPU에서 GPU로 자료를 올려서 갱신해야 할 자원들을 이 힙에 맡긴다.
(c) D3D12_HEAP_TYPE_READBACK
다시 읽기(read-back) 힙.
CPU가 읽어야 할 자원들은 이 힙에 맡긴다.
(d) D3D12_HEAP_TYPE_CUSTOM
고급 응요을 위한것이다.
자세한 사항은 MSDN 문서화 참조
2. D3D12_HEAP_FLAGS HeapFlags
자원을 맡길 힙이 가졌으면 하는 속성들을 나타내는 추가적인 플래그들.
흔히 D3D12_HEAP_MISC_NONE을 지정한다.
3. D3D12_RESOURCE_DESC *pDesc
생성하고자 하는 자원을 서술하는 D3D12_RESOURCE_DESC 인스턴스의 포인터
4. InitialResourceStateD3D12_RESOURCE_STATES InitialResourceState
앞서 이야기 했듯이. 자원에는 상태(현재 어떤 용도인지 나타내는)가 있다.
이 매개변수에는 자원의 초기 상태를 지정한다.
깊이$\cdot$스텐실 버퍼로 사용할 자원은 D3D12_RESOURCE_USAGE_INITIAL을 초기 상태로 지정하고, 생성 후 D3D12_RESOURCE_USAGE_DEPTH 상태로 전이해서 깊이$\cdot$스텐실 버퍼로서 파이프라인에 묶으면 된다.
5. pOptimizedClearValueD3D12_CLEAR_VALUE *pOptimizedClearValue
자원 지우기에 최적화 된 값을 나타내는 D3D12_CLEAR_VALUE 구조체를 가리키는 포인터.
최적화된 지우기 값과 지우기 호출은 부합하지 않는 호출보다 빠를 수 있다.
최적화된 지우기 값을 설정하지 않으려면 NULL을 지정하면 된다.
1
2
3
4
5
6
7
8
9
|
typedef struct D3D12_CLEAR_VALUE
{
DXGI_FORMAT Format;
union
{
FLOAT Color[4];
D3D12_DEPTH_STENCIL_VALUE DepthStencil;
};
} D3D12_CLEAR_VALUE;
|
cs |
6. riidResource REFIID riidResource
생성하려는 자원에 해당하는 ID3D12Resource 인터페이스의 COM ID
7. ppvResourcevoid **ppvResource
새로 성생된 자원을 나타내는 ID3D12Resource의 포인터를 이 매개변수를 통해 돌려준다.
참고 : 최적의 성능을 위해서는 자원들을 기본 힙에 넣어야 한다. 자료 올리기 힙이나 다시 읽기 힙은 해당 기능이 필요할 때에만 사용한다.
깊이$\cdot$스텐실 버퍼를 사용하기 전에 반드시 그와 연관된 깊이$\cdot$스텐실 뷰를 생성해서 파이프라인에 묶어야 한다. 구체적인 방법은 렌더 대상 뷰를 생성할 때와 비슷하다.
다은은 깊이$\cdot$스텐실 텍스처와 해당 깊이$\cdot$스텐실 뷰를 생성하는 방법을 보여주는 예제 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
// 깊이/스텐실 버퍼와 뷰를 생성한다.
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;
// Correction 11/12/2016: SSAO chapter requires an SRV to the depth buffer to read from
// the depth buffer. Therefore, because we need to create two views to the same resource:
// 1. SRV format: DXGI_FORMAT_R24_UNORM_X8_TYPELESS
// 2. DSV Format: DXGI_FORMAT_D24_UNORM_S8_UINT
// we need to create the depth buffer resource with a typeless format.
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.GetAddressOf())));
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;
// 전체 자원이 밉맵 수준 0에 대한 서술자를,
// 해당 자원의 픽셀 형식을 적용해서 생성한다.
md3dDevice->CreateDepthStencilView(
mDepthStencilBuffer.Get(),
&dsvDesc,
DepthStencilView());
// 자원을 초기 상태에서 깊이 버퍼로 사용할 수 있는 상태로 전이한다.
mCommandList->ResourceBarrier(
1,
&CD3DX12_RESOURCE_BARRIER::Transition(mDepthStencilBuffer.Get(),
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_DEPTH_WRITE));
|
cs |
힙 속성 구조체를 생성할 때, 그 구조체의 확장 버전인 CD3DX12_HEAP_PROPERTIES의 생성자를 사용했음을 주목하기 바란다. 이 생성자의 구현은 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
|
explicit CD3DX12_HEAP_PROPERTIES(
D3D12_HEAP_TYPE type,
UINT creationNodeMask = 1,
UINT nodeMask = 1 )
{
Type = type;
CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
CreationNodeMask = creationNodeMask;
VisibleNodeMask = nodeMask;
}
|
cs |
CreateDepthStencilView 메서드의 둘째 매개변수는 D3D12_DEPTH_STENCIL_VIEW_DESC를 가리키는 포인터이다. 이 구조체는 깊이$\cdot$스텐실 뷰를 서술하는데, 특히 자원에 담긴 원소들의 자료 형식에 관한 멤버를 가지고 있다. 구체적인 자료 형식을 지정해서 자원을 생성했다면(즉, 무형식 자원이 아니면) 이 매개변수에 널 포인터를 지정해도 된다. 그런 경우 이 메서드는 그 자원을 새성할 때 지정한 자료 형식을 적용해서 그 자원의 첫 번째 밉맵 수준에 대한 뷰를 생성한다(깊이$\cdot$스텐실 버퍼에는 밉맵 수준이 하나뿐이다). (밉맵은 9장에서 논의한다) 지금은 깊이$\cdot$스텐실 버퍼에 대한 뷰를 생성하는 중이므로, 이 매개변수에 널 포인터를 지정한다.
Depth Stencil Buffer 를 생성한다(CreateCommittedResource)
그리고 생성된 resource를 서술할 descriptor인 DSV를 생성한다(CreateDepthStencilView) 이때 생성될 descriptor가 서술할 대상이 될 resource와 저장될 descriptor heap에 대한 정보가 전달되어야 한다.
'computer graphics > DX12 book' 카테고리의 다른 글
4. 기능 수준(feature level) (0) | 2021.01.11 |
---|---|
4. 다중표본화(multisampling) (0) | 2021.01.11 |
4. 깊이 버퍼링(Depth Buffer) (0) | 2021.01.11 |
4. 교환 사슬(Swap Chain)과 더블 버퍼링(Double Buffering) (0) | 2021.01.11 |
4. 텍스처 형식 (0) | 2021.01.11 |