๐Ÿ™‡โ€โ™€๏ธ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์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

ํƒœ๊ทธ:

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ: