Link

์ด์ œ ์Šค์™‘์ฒด์ธ๊ณผ ์ปค๋งจ๋“œ ๋ฒ„ํผ, ๊ทธ๋ฆฌ๊ณ  Vulkan์ด ๋ชจ๋‘ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ณธ๊ฒฉ์ ์œผ๋กœ ๋ Œ๋”๋ง ๋ฃจํ”„๋ฅผ ์ž‘์„ฑํ•  ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” VkCmdClearColorImage๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ ˆ์ž„์„ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ™”๋ฉด์— ๊นœ๋นก์ด๋Š” ์ƒ‰์ƒ์ด ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์Šค์™‘์ฒด์ธ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์˜จ ๋’ค, ์ง€์ •ํ•œ ์ƒ‰์ƒ์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, OS์™€ GPU๊ฐ€ ์Šค์™‘์ฒด์ธ ๋ฐ ์ดˆ๊ธฐํ™” ๋ช…๋ น๊ณผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ๋™๊ธฐํ™” ๊ตฌ์กฐ์ฒด๋ฅผ ์„ค์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋™๊ธฐํ™”

Vulkan์€ CPU๊ฐ€ GPU์˜ ๋ช…๋ น ์‹คํ–‰๊ณผ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ช…์‹œ์ ์ธ ๋™๊ธฐํ™” ๊ตฌ์กฐ์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ GPU์—์„œ ์‹คํ–‰๋˜๋Š” ๋ช…๋ น์˜ ์ˆœ์„œ๋„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋ช…๋ น์ด ํ ํ˜น์€ ๋‹ค๋ฅธ ๋ช…๋ น์„ ํ†ตํ•ด GPU๋กœ ์ „๋‹ฌ๋˜๋ฉด ๋“œ๋ผ์ด๋ฒ„์™€ GPU๊ฐ€ ์ด๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๋ช…๋ น์„ ์ฃผ์–ด์ง„ ์ˆœ์„œ์— ๋”ฐ๋ผ ์‹คํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๋ฉด ๋™๊ธฐํ™” ์‹œ์Šคํ…œ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด Vulkan์—์„œ๋Š” ํŽœ์Šค(Fence)์™€ ์„ธ๋งˆํฌ์–ด(Semaphore)๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

VkFence

์ด๋Š” GPU์—์„œ CPU๋ฐฉํ–ฅ์œผ๋กœ์˜ ๋™๊ธฐํ™”์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. vkQueueSubmit๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ Vulkan ๋ช…๋ น์—์„œ๋Š” ์„ ํƒ์ ์œผ๋กœ ํŽœ์Šค ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŽœ์Šค๋ฅผ ์„ค์ •ํ•˜๋ฉด, CPU์—์„œ GPU๊ฐ€ ํ•ด๋‹น ์ž‘์—…์„ ์™„๋ฃŒํ–ˆ๋Š” ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŽœ์Šค๋Š” ๋ช…๋ น์ด ์ œ์ถœ๋˜๋ฉด ์‹ ํ˜ธ(signal)๊ฐ€ ์„ค์ •๋˜๋ฉฐ, VkWaitForFences๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ CPU๊ฐ€ ํ•ด๋‹น ๋ช…๋ น์ด ์‹คํ–‰๋  ๋•Œ ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” 2๊ฐœ์˜ ํŽœ์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ณ  ์ด์ค‘ ํ•˜๋‚˜๋ฅผ FrameData ๊ตฌ์กฐ์ฒด์— ์ถ”๊ฐ€ํ•ฉ์‹œ๋‹ค.

์˜์‚ฌ ์ฝ”๋“œ ์˜ˆ์ œ:

//we have a fence object created from somewhere
VkFence myFence;

//start some operation on the GPU
VkSomeOperation(whatever, myFence);

// block the CPU until the GPU operation finishes
VkWaitForFences(myFence);
//fences always have to be reset before they can be used again
VkResetFences(myFence);

VkSemaphore

์ด๋Š” GPU ๋‚ด๋ถ€ ์—ฐ์‚ฐ ๊ฐ„ ๋™๊ธฐํ™”์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์„ธ๋งˆํฌ์–ด๋Š” GPU ๋ช…๋ น์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ •์˜ํ•˜์—ฌ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜๋„๋ก ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. VkQueueSubmit๊ณผ ๊ฐ™์€ ๋ช‡๋ช‡ Vulkan ๋ช…๋ น์€ ์‹ ํ˜ธ(Signal) ํ˜น์€ ๋Œ€๊ธฐ(Wait) ์„ธ๋งˆํฌ์–ด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์„ธ๋งˆํฌ์–ด๋Š” ์—ฌ๋Ÿฌ GPU ํ ๋ช…๋ น ๊ฐ„ ์—ฐ๊ฒฐ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋ช…๋ น์€ ์„ค์ •ํ•œ ์„ธ๋งˆํฌ์–ด๋ฅผ ์‹ ํ˜ธํ•˜๋ฉฐ, ๋‹ค๋ฅธ ๋ช…๋ น์€ ์ด๋ฅผ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ GPU ๋ช…๋ น์ด ํ•˜๋‚˜์˜ ์„ธ๋งˆํฌ์–ด๋ฅผ ๋Œ€๊ธฐํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ํ•œ ๋ช…๋ น์— ํ•˜๋‚˜์˜ ์„ธ๋งˆํฌ์–ด๋งŒ์„ ์‹ ํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช…๋ น์ด ์„ธ๋งˆํฌ์–ด๋ฅผ ๋Œ€๊ธฐํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์„ธ๋งˆํฌ์–ด์— ์‹ ํ˜ธ๊ฐ€ ์˜ฌ ๋•Œ ๊นŒ์ง€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

3๊ฐ€์ง€ ๋ช…๋ น์„ ์ง๋ ฌํ™”ํ•˜๋Š” ์˜์‚ฌ ์ฝ”๋“œ ์˜ˆ์ œ:

VkSemaphore Task1Semaphore;
VkSemaphore Task2Semaphore;

VkOperationInfo OpAlphaInfo;
// Operation Alpha will signal the semaphore 1
OpAlphaInfo.signalSemaphore = Task1Semaphore;

VkDoSomething(OpAlphaInfo);

VkOperationInfo OpBetaInfo;

// Operation Beta signals semaphore 2, and waits on semaphore 1
OpBetaInfo.signalSemaphore = Task2Semaphore;
OpBetaInfo.waitSemaphore = Task1Semaphore;

VkDoSomething(OpBetaInfo);

VkOperationInfo OpGammaInfo;
//Operation gamma waits on semaphore 2
OpGammaInfo.waitSemaphore = Task2Semaphore;

VkDoSomething(OpGammaInfo);

์ด ์ฝ”๋“œ๋Š” 3๊ฐœ์˜ DoSomething์„ GPU์—์„œ ์—„๊ฒฉํ•œ ์ˆœ์„œ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. GPU์—์„œ ์‹คํ–‰๋˜๋Š” ๋ช…๋ น์˜ ์ˆœ์„œ๋Š” Alpha->Beta->Gamma์ž…๋‹ˆ๋‹ค. Alpha๊ฐ€ ์‹คํ–‰๋˜๋ฉด Task1์„ ์‹ ํ˜ธํ•˜๊ณ , ์ด๋Š” Beta๋ฅผ ์‹คํ–‰์‹œ์ผœ Beta๊ฐ€ ์‹คํ–‰์„ ๋งˆ์น˜๋ฉด ๋งˆ์ง€๋ง‰์œผ๋กœ Gamma๋ฅผ ์‹ ํ˜ธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ์„ธ๋งˆํฌ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด 3๊ฐœ์˜ ๋ช…๋ น์€ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋˜์–ด ์„œ๋กœ ์–ฝํ˜€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋กœ ๋‹ค๋ฅธ ํ ๊ฐ„ ๋ช…๋ น์—๋„ ์„ธ๋งˆํฌ์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฉ”์ธ ๊ทธ๋ž˜ํ”ฝ์Šค ํ๊ฐ€ ํŠน์ • ํŒจ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ๋Š” ์ปดํ“จํŠธ ์…ฐ์ด๋”๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ์ถœ๋ ฅํ•˜๋Š” ํ‘œ์‹œ(Present) ํ์™€ ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ทธ๋ž˜ํ”ฝ์Šค ํ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ Œ๋”๋ง ๋ฃจํ”„

์šฐ๋ฆฌ์˜ ๋ Œ๋”๋ง ๋ฃจํ”„์—์„œ๋Š” ๋”๋ธ” ๋ฒ„ํผ๋ง ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด GPU๊ฐ€ ํ•œ ํ”„๋ ˆ์ž„ ๋ถ„๋Ÿ‰์˜ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ CPU๊ฐ€ ๋‹ค์Œ ํ”„๋ ˆ์ž„์„ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ํ”„๋ ˆ์ž„์ด ๊ณ„์‚ฐ๋˜๋ฉด ์ฒซ ํ”„๋ ˆ์ž„์ด ์‹คํ–‰ ์™„๋ฃŒ๋˜์–ด ์ปค๋งจ๋“œ ๋ฒ„ํผ์— ๋‹ค์‹œ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ๊นŒ์ง€ CPU๋Š” ๋Œ€๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ Œ๋”๋ง ์ž‘์—…์—์„œ๋Š” ์Šค์™‘์ฒด์ธ๊ณผ ๋™๊ธฐํ™”๋ฅผ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํ™”๋ฉด์— ํ‘œ์‹œํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ํ—ค๋“œ๋ฆฌ์Šค ๋ Œ๋”๋ง์ด๋ผ๋ฉด, ์ด ๊ณผ์ •์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์ฐฝ์— ๋ Œ๋”๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ OS์—์„œ ์‚ฌ์šฉํ•  ์ด๋ฏธ์ง€๋ฅผ ์š”์ฒญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ์ด๋ฏธ์ง€์— ๋ Œ๋”๋งํ•œ ํ›„, ๊ทธ ์ด๋ฏธ์ง€๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋„๋ก OS์— ์•Œ๋ ค์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ๋ ˆ์ด์•„์›ƒ

GPU๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์ด๋ฏธ์ง€๋ฅผ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํฌ๋งท์œผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. Vulkan์—์„œ๋Š” ์ด๋Ÿฌํ•œ ํฌ๋งท์„ ์ด๋ฏธ์ง€ ๋ ˆ์ด์•„์›ƒ์ด๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ ์ถ”์ƒํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ ์ด๋ฏธ์ง€๋Š” ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ์ด๋ฏธ์ง€์™€ ๋‹ค๋ฅธ ๋ ˆ์ด์•„์›ƒ์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€์˜ ๋ ˆ์ด์•„์›ƒ์„ ๋ณ€๊ฒฝํ•  ๋•Œ Vulkan์€ ํŒŒ์ดํ”„๋ผ์ธ ๋ฐฐ๋ฆฌ์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ ๋ฐฐ๋ฆฌ์–ด๋Š” ๋‹จ์ผ ์ปค๋งจ๋“œ ๋ฒ„ํผ ๋‚ด์—์„œ ๋ช…๋ น์„ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ด๋ฏธ์ง€ ๋ ˆ์ด์•„์›ƒ ๋ณ€ํ™˜๋„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ๋ ˆ์ด์•„์›ƒ์ด ํ•˜๋“œ์›จ์–ด๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ผ๋ถ€ ๋ณ€ํ™˜์€ ํŠน์ • ํ•˜๋“œ์›จ์–ด์—์„œ ์‹ค์ œ๋กœ ์•„๋ฌด๋Ÿฐ ๋™์ž‘๋„ ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๊ฒ€์ฆ ๋ ˆ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GPU ๋ช…๋ น์ด ์ ์ ˆํ•œ ๋ ˆ์ด์•„์›ƒ์—์„œ ์‹คํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.๊ฒ€์ฆ ๋ ˆ์ด์–ด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, NVIDIA ํ•˜๋“œ์›จ์–ด์—์„œ๋Š” ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋”๋ผ๋„ AMD๋‚˜ ๋‹ค๋ฅธ ํ•˜๋“œ์›จ์–ด์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์Šค์™‘์ฒด์ธ์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ด๋ฏธ์ง€๋Š” ์œ ํšจํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ์ด๋ฏธ์ง€์— VkCmdDraw ํ˜น์€ ๋‹ค๋ฅธ ๊ทธ๋ฆฌ๊ธฐ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด, ๋จผ์ € ์ด๋ฏธ์ง€์˜ ๋ ˆ์ด์•„์›ƒ์„ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ฆฌ๊ธฐ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•œ ํ›„์—๋Š”, ์ตœ์ข…์ ์œผ๋กœ ํ™”๋ฉด ์ถœ๋ ฅ์— ์ ํ•ฉํ•œ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๋ฒ„์ „์˜ Vulkan์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ ˆ์ด์•„์›ƒ ๋ณ€ํ™˜์ด ๋ Œ๋”ํŒจ์Šค์˜ ์ผ๋ถ€๋กœ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Vulkan 1.3์—์„œ๋Š” ๋™์  ๋ Œ๋”๋ง์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณ€ํ™˜์„ ์ง์ ‘ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์—, ์ „์ฒด ๋ Œ๋”ํŒจ์Šค ๊ตฌ์„ฑํ•  ๋•Œ ๋ณต์žก์„ฑ๊ณผ ์ž‘์—…๋Ÿ‰์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ Œ๋”ํŒจ์Šค์— ๋Œ€ํ•ด ๋” ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ๊ตฌ๋ฒ„์ „์˜ ํŠœํ† ๋ฆฌ์–ผ์„ ํ™•์ธํ•˜์„ธ์š”.

์ด์ œ ๋ Œ๋”๋ง ๋ฃจํ”„ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Next: Mainloop Code