일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- union find
- Stored Procedure
- 다익스트라
- Brute Force
- 이진탐색
- 그래프
- SQL
- two pointer
- Two Points
- MYSQL
- Hash
- Dijkstra
- DP
- binary search
- 스토어드 프로시저
- Trie
- String
- Today
- Total
codingfarm
4. 교환 사슬(Swap Chain)과 더블 버퍼링(Double Buffering) 본문
4. 교환 사슬(Swap Chain)과 더블 버퍼링(Double Buffering)
scarecrow1992 2021. 1. 11. 20:48- 하나의 프레임 버퍼를 가지고 게임 화면을 표현하면 화면 깜빡임(Screen Flickering) 및 화면 찢어짐(Screen Tearing) 현상이 나타난다.
- 화면 깜빡임 : 버퍼를 지우고 그릴경우 발생
- 화면 찢어짐: 이미 그려진 화면 위에 덮어 쓸 경우 발생
더블 버퍼링(Double Buffering)
- 화면 깜빡임 및 찢어짐 현상을 피하고자 사용되는 방법
- 후면 버퍼(Back Buffer)와 전면 버퍼(Front Buffer) 2개의 프레임 버퍼의 교환을 통해 프레임 전환을 구현하는 기술
- 전면 버퍼 : 화면을 표현
- 후면 버퍼 : 다음 화면이 될 장면을 미리 저장
- 후면버퍼는 텍스처 이므로 그 원소를 텍셀(texel)이라 부르지만 여기서는 그냥 픽셀(pixel)이라 부름
- shader input이나 render taget output으로 쓰일 수 있음
- 제시(presenting) : Direct3D에서 두 버퍼간의 역할 교환을 통해 프레임이 전환 되게 하는 것
교환 사슬(Swap Chain)
- 플리핑을 하기 위해 전면/후면 버퍼 간의 관계를 형성하는 인스턴스
- 플리핑(fliping) : 전면/후면 버퍼의 포인터를 서로 맞바꾸는것
IDXGISwapChain
- Direct3D에서 SwapChain을 대표하는 인터페이스
- 전면/후면 버퍼 텍스처를 담는다
- 버퍼 크기 변경(IDXGISwapChain::ResizeBuffers()) 혹은 버퍼의 페레젠팅(IDXGISwapChain::Present())등을 위한 메서드 제공
교환 사슬의 서술과 생성(Describe and Create Swap Chain)
- Swap Chain을 만드는 과정은 크게 서술과 생성으로 나뉜다.
- 서술 : DXGI_SWAP_CHAIN_DESC 인스턴스의 멤버들을 생성하고자 하는 교환사슬에 맞게 설정한다.
- 생성 : IDXGIFactory::CreateSwapChain 메서드를 호출해서 교환사슬을 생성한다.
- DXGI object 이므로 factory를 통해 생성된다.
서술
DXGI_SWAP_CHAIN_DESC 구조체 인스턴스의 멤버들을 지금 생성하고자 하는 교환 사슬에 맞게 설정해야 한다. 이 구조체의 정의는 아래와 같다.
1
2
3
4
5
6
7
8
9
10
|
typedef struct DXGI_SWAP_CHAIN_DESC {
DXGI_MODE_DESC BufferDesc;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
HWND OutputWindow;
BOOL Windowed;
DXGI_SWAP_EFFECT SwapEffect;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC;
|
cs |
DXGI_SWAP_CHAIN_DESC의 각 필드에 대한 설명은 아래와 같다. 이 책의 수준에서 중요한 공통의 플래그들과 옵션들만 이야기 한다.
매개변수 | 기능 |
BufferDesc | 이 구조체는 생성하고자 하는 후면 버퍼의 속성들을 서술한다. 지금 수준에서 중요한 속성은 너비(Width)와 높이(Height) 그리고 픽셀형식(Format)이다. |
SampleDesc | 다중표본화 표본 개수와 품질 수준을 서술하는 구조체이다. 단일표본화를 사용하고 싶으면 표본 개수를 1, 품질 수준을 0으로 설정한다. |
BufferUsage | 후면 버퍼의 surface usage 및 CPU access option에 대해 서술한다. 후면 버퍼에 렌더링할 것이므로 이 멤버에는 DXGI_USAGE_RENDER_TARGET_OUTPUT을 지정한다. |
BufferCount | 교환 사슬이 사용할 버퍼의 갯수이다. 이중 버퍼링에서는 2를 지정한다. |
OutputWindow | 렌더링 결과가 표시될 창의 핸들 CreateWindow 함수의 반환 값을 넣는다. |
Windowed | 창 모드이면 true, 전체화면 모드이면 false |
SwapEffect | 이 멤버에는 DXGI_SWAP_EFFECT_FLIP_DISCARD를 지정한다. |
Flags | 추가적인 플래그들, 여기에 DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH를 지정하면, 응용 프로그램이 전체 화면으로 전환될 때 Direct3D는 응용 프로그램 창의 현재 크기에 가장 잘 맞는 디스플레이 모드를 선택한다. 이 플래그를 지정하지 않으면, 응용 프로그램이 전체 화면으로 전환될 때 Direct3D는 현재 데스크톱 디스플레이 모드를 사용한다. |
생성
교환사슬을 서술하는 구조체를 다 채웠으면, IDXGIFactory::CreateSwapChain 메서드를 호출해서 교환 사슬을 생성한다.
1
2
3
4
5
|
HRESULT CreateSwapChain(
IUnknown *pDevice,
DXGI_SWAP_CHAIN_DESC *pDesc,
IDXGISwapChain **ppSwapChain
);
|
cs |
매개변수 | 기능 |
IUnknown | Direct3D 11 및 초기버전 : swap chain을 위한 Direct3D device 포인터 Direct3D 12 : command queue 포인터 NULL을 전달해선 안된다. |
DXGI_SWAP_CHAIN_DESC | DXGI_SWAP_CHAIN_DESC 서술자 인스턴스의 포인터 NULL을 전달해선 안된다 |
IDXGISwapChain | CreatSwapChain이 만드는 SwapChain 을 받아올 포인터 |
다음 코드는 이 책의 예제 프레임 워크에서 교환사슬을 생성하는 방법을 보여준다. 이 함수가 여러 번 호출되어도 문제가 없도록 설계되어 잇음을 주목하라. 이 함수는 기존 교환 사슬을 먼저 해제한 후 새 교환 사슬을 생성한다. 이 덕분에 응용 프로그램은 이전과는 다른 설정으로 교환 사슬을 다시 생성할 수 있다. 특히, 실행 도중에 다중표본화 설정을 변경할 수 있다.
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
|
void D3DApp::CreateSwapChain()
{
// Release the previous swapchain we will be recreating.
mSwapChain.Reset();
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = mClientWidth;
sd.BufferDesc.Height = mClientHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = mBackBufferFormat;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.SampleDesc.Count = m4xMsaaState ? 4 : 1;
sd.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = SwapChainBufferCount;
sd.OutputWindow = mhMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
// Note: Swap chain uses queue to perform flush.
ThrowIfFailed(mdxgiFactory->CreateSwapChain(
mCommandQueue.Get(),
&sd,
mSwapChain.GetAddressOf()));
}
|
cs |
DXGI_MODE_DESC 형식은 또 다른 구조체로, 다음과 같이 정의되어 있다.
1
2
3
4
5
6
7
8
|
typedef struct DXGI_MODE_DESC {
UINT Width;
UINT Height;
DXGI_RATIONAL RefreshRate;
DXGI_FORMAT Format;
DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
DXGI_MODE_SCALING Scaling;
} DXGI_MODE_DESC;
|
cs |
https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgifactory-createswapchain
MSDN에 의하면, Direct3D 11.1 이후로 swap chain을 만들기 위해 CreateSwapChain 함수의 사용을 권장하지 않으며, 대안으로 CreateSwapChainForHwnd, CreateSwapChainForCoreWindow, or CreateSwapChainForComposition 사용을 제시한다.
'computer graphics > DX12 book' 카테고리의 다른 글
4. 자원과 서술자 / Descriptor Heap, RTV, DSV (0) | 2021.01.11 |
---|---|
4. 깊이 버퍼링(Depth Buffer) (0) | 2021.01.11 |
4. 텍스처 형식 (0) | 2021.01.11 |
4. COM(Component Object Model) (0) | 2021.01.11 |
4. Direct3D 초기화 - 개요 (0) | 2021.01.11 |