SwapChain์ด๋?
๐โโ๏ธSwapChain
- ๊ตํ ์ฌ์ฌ
- [์ธ์ฃผ ๊ณผ์ ]
- ํ์ฌ ๊ฒ์ ์ธ์์ ์๋ ์ํฉ์ ๋ฌ์ฌ
- ์ด๋ค ๊ณต์์ผ๋ก ์ด๋ป๊ฒ ๊ณ์ฐํ ์ง ๋์ ธ์ค
- GPU๊ฐ ์ด์ฌํ ๊ณ์ฐ (์ธ์ฃผ)
- ๊ฒฐ๊ณผ๋ฌผ ๋ฐ์์ ํ๋ฉด์ ๊ทธ๋ ค์ค๋ค
- [์ธ์ฃผ ๊ฒฐ๊ณผ๋ฌผ]์ ์ด๋์ ๋ฐ์ง?
- ์ด๋ค ์ข ์ด(Buffer)์ ๊ทธ๋ ค์ ๊ฑด๋ด๋ฌ๋ผ๊ณ ๋ถํํด๋ณด์
- ํน์ ์ข ์ด๋ฅผ ๋ง๋ค์ด์ -> ์ฒ์์ ๊ฑด๋ด์ฃผ๊ณ -> ๊ฒฐ๊ณผ๋ฌผ์ ํด๋น ์ข ์ด์ ๋ฐ๋๋ค OK
- ์ฐ๋ฆฌ ํ๋ฉด์ ํน์ ์ข ์ด(์ธ์ฃผ ๊ฒฐ๊ณผ๋ฌผ)๋ฅผ ์ถ๋ ฅํด์ค๋ค
- [?]
- ๊ทธ๋ฐ๋ฐ ํ๋ฉด์ ํ์ฌ ๊ฒฐ๊ณผ๋ฌผ ์ถ๋ ฅํ๋ ์์ค์, ๋ค์ ํ๋ฉด๋ ์ธ์ฃผ๋ฅผ ๋งก๊ฒจ์ผ ํจ
- ํ์ฌ ํ๋ฉด ๊ฒฐ๊ณผ๋ฌผ์ ์ด๋ฏธ ํ๋ฉด ์ถ๋ ฅ์ ์ฌ์ฉ์ค
- ํน์ ์ข ์ด๋ฅผ 2๊ฐ ๋ง๋ค์ด์, ํ๋๋ ํ์ฌ ํ๋ฉด์ ๊ทธ๋ ค์ฃผ๊ณ , ํ๋๋ ์ธ์ฃผ ๋งก๊ธฐ๊ณ โฆ
- Double Buffering!
- [0] [1]
- ํ์ฌ ํ๋ฉด [0] <-> GPU ์์ ์ค [1] BackBuffer
๐ชSwapChain.h ๋ถ์
SwapChain.h ์ ์ฒด ์ฝ๋
#pragma once
class SwapChain
{
public:
void Init(const WindowInfo& info, ComPtr<IDXGIFactory> dxgi, ComPtr<ID3D12CommandQueue> cmdQueue);
void Present();
void SwapIndex();
ComPtr<IDXGISwapChain> GetSwapChain() { return _swapChain; }
ComPtr<ID3D12Resource> GetRenderTarget(int32 index) { return _renderTargets[index]; }
uint32 GetCurrentBackBufferIndex() { return _backBufferIndex; }
ComPtr<ID3D12Resource> GetCurrentBackBufferResource() { return _renderTargets[_backBufferIndex]; }
private:
ComPtr<IDXGISwapChain> _swapChain;
ComPtr<ID3D12Resource> _renderTargets[SWAP_CHAIN_BUFFER_COUNT];
uint32 _backBufferIndex = 0;
};
SWAP_CHAIN_BUFFER_COUNT
์ enum์ผ๋ก 2์ด๋ค. ์ด๊ฑด ์์ ๋น์ ์ ์ ์ฉํ๋ฉด ํน์ ์ข
์ด ๊ฐ์์ด๋ค!!
๐ชSwapChain.cpp ๋ถ์
SwapChain.cpp ์ ์ฒด ์ฝ๋
#include "pch.h"
#include "SwapChain.h"
void SwapChain::Init(const WindowInfo& info, ComPtr<IDXGIFactory> dxgi, ComPtr<ID3D12CommandQueue> cmdQueue)
{
// ์ด์ ์ ๋ง๋ ์ ๋ณด๋ฅผ ๋ ๋ฆฐ๋ค
_swapChain.Reset();
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = static_cast<uint32>(info.width); // ๋ฒํผ์ ํด์๋ ๋๋น
sd.BufferDesc.Height = static_cast<uint32>(info.height); // ๋ฒํผ์ ํด์๋ ๋์ด
sd.BufferDesc.RefreshRate.Numerator = 60; // ํ๋ฉด ๊ฐฑ์ ๋น์จ
sd.BufferDesc.RefreshRate.Denominator = 1; // ํ๋ฉด ๊ฐฑ์ ๋น์จ
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // ๋ฒํผ์ ๋์คํ๋ ์ด ํ์
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
sd.SampleDesc.Count = 1; // ๋ฉํฐ ์ํ๋ง OFF
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // ํ๋ฉด ๋ฒํผ์ ๋ ๋๋งํ ๊ฒ
sd.BufferCount = SWAP_CHAIN_BUFFER_COUNT; // ์ ๋ฉด+ํ๋ฉด ๋ฒํผ
sd.OutputWindow = info.hwnd;
sd.Windowed = info.windowed;
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // ์ ๋ฉด ํ๋ฉด ๋ฒํผ ๊ต์ฒด ์ ์ด์ ํ๋ ์ ์ ๋ณด ๋ฒ๋ฆผ
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
dxgi->CreateSwapChain(cmdQueue.Get(), &sd, &_swapChain);
for (int32 i = 0; i < SWAP_CHAIN_BUFFER_COUNT; ++i)
_swapChain->GetBuffer(i, IID_PPV_ARGS(&_renderTargets[i]));
}
void SwapChain::Present()
{
// Present the frame.
_swapChain->Present(0, 0);
}
void SwapChain::SwapIndex()
{
_backBufferIndex = (_backBufferIndex + 1) % SWAP_CHAIN_BUFFER_COUNT;
}
Init์ ๋ณด๋ฉด ๋จผ์ DXGI_SWAP_CHAIN_DESC
๋ swapChain ์ค๋ช
์๋ฅผ ๋ง๋ค๊ณ ๊ทธ๊ฒ์ ์ฑ์์ค๋ค.
device์ ์์๋ dxgi๋ฅผ ํตํด CreateSwapChain
์ ํ์ฌ SwapChain์ ๋ง๋ค์ด์ค๋ค.