Link

FrameData ๊ตฌ์กฐ์ฒด๋ฅผ vk_engine.h์— ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ์ฒด๋Š” ์ฃผ์–ด์ง„ ํ”„๋ ˆ์ž„์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ตฌ์กฐ์ฒด์™€ ๋ช…๋ น์„ ์ €์žฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”๋ธ” ๋ฒ„ํผ๋ง์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ, GPU๊ฐ€ ํ•œ์ชฝ ๋ฒ„ํผ์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ๋ฒ„ํผ์—์„œ ๋ช…๋ น์„ ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

struct FrameData {

	VkCommandPool _commandPool;
	VkCommandBuffer _mainCommandBuffer;
};

constexpr unsigned int FRAME_OVERLAP = 2;

์ด๋ฅผ ํ๋ฅผ ์ €์žฅํ•  ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ VulkanEngine ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

class VulkanEngine{
public:
	FrameData _frames[FRAME_OVERLAP];

	FrameData& get_current_frame() { return _frames[_frameNumber % FRAME_OVERLAP]; };

	VkQueue _graphicsQueue;
	uint32_t _graphicsQueueFamily;
}

์ดˆ๊ธฐํ™” ๋กœ์ง ์™ธ๋ถ€์—์„œ _frames ๋ฐฐ์—ด์— ์ง์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•˜์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ _frameNumber๋ฉค๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ๋ฐฐ์—ด์„ ์ฐธ์กฐํ•˜๋Š” getter๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‘ ๊ฐœ์˜ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฒˆ๊ฐˆ์•„ ๊ฐ€๋ฉฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ ๊ฐ€์ ธ์˜ค๊ธฐ

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

๋‹คํ–‰ํžˆ VkBootstrap ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ์™€ ํ ํŒจ๋ฐ€๋ฆฌ๋ฅผ ์ง์ ‘ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

init_vulkan()ํ•จ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์œผ๋กœ ๊ฐ€๋ด…์‹œ๋‹ค.

๋งจ ๋งˆ์ง€๋ง‰์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

void VulkanEngine::init_vulkan(){

// ---- other code, initializing vulkan device ----

	// use vkbootstrap to get a Graphics queue
	_graphicsQueue = vkbDevice.get_queue(vkb::QueueType::graphics).value();
	_graphicsQueueFamily = vkbDevice.get_queue_index(vkb::QueueType::graphics).value();
}

vkbootstrap์„ ํ†ตํ•ด ๊ทธ๋ž˜ํ”ฝ์Šค ํ์™€ ํ ํŒจ๋ฐ€๋ฆฌ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

์ปค๋งจ๋“œ ๊ตฌ์กฐ์ฒด ์ƒ์„ฑํ•˜๊ธฐ

์ปค๋งจ๋“œ ํ’€์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด init_commands() ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์ด์ „๊ณผ๋Š” ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” VkBootstrap ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ฉฐ, ์ง์ ‘ Vulkan ๋ช…๋ น์„ ํ˜ธ์ถœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

void VulkanEngine::init_commands()
{
	//create a command pool for commands submitted to the graphics queue.
	//we also want the pool to allow for resetting of individual command buffers
	VkCommandPoolCreateInfo commandPoolInfo =  {};
	commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
	commandPoolInfo.pNext = nullptr;
	commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
	commandPoolInfo.queueFamilyIndex = _graphicsQueueFamily;
	
	for (int i = 0; i < FRAME_OVERLAP; i++) {

		VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool));

		// allocate the default command buffer that we will use for rendering
		VkCommandBufferAllocateInfo cmdAllocInfo = {};
		cmdAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
		cmdAllocInfo.pNext = nullptr;
		cmdAllocInfo.commandPool = _frames[i]._commandPool;
		cmdAllocInfo.commandBufferCount = 1;
		cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;

		VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer));
	}
}

vkCreateX ํ•จ์ˆ˜์— ์‚ฌ์šฉ๋˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ Vulkan Info ๊ตฌ์กฐ์ฒด๋“ค๊ณผ ๋งŽ์€ ๋‹ค์–‘ํ•œ Vulkan ๊ตฌ์กฐ์ฒด๋“ค์€ sType๊ณผ pNext๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ™•์žฅ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ, ์ผ๋ถ€ ํ™•์žฅ์€ ๋™์ผํ•œ vkCreateX ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ๊ตฌ์กฐ์ฒด๋ฅผ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. sType์€ ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ์กฐ์ฒด์˜ ์ข…๋ฅ˜๋ฅผ Vulkan ๊ตฌํ˜„์ฒด๊ฐ€ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

Vulkan ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ด๋ฅผ ๋ฐ˜๋“œ์‹œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

VkCommandPoolCreateInfo commandPoolInfo = {};

` = {}`๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ตฌ์กฐ์ฒด์˜ ๋ชจ๋“  ๊ฐ’์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ Vulkan ๊ตฌ์กฐ์ฒด๋Š” 0์œผ๋กœ ์„ค์ •๋˜์—ˆ์„ ๋•Œ ๋น„๊ต์  ์•ˆ์ „ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ตฌ์กฐ์ฒด ๋‚ด์— ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ๊ฐ’์ด ๋‚จ์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

queueFamilyIndex์— ์ด์ „์— ๊ฐ€์ ธ์˜จ _graphicsQueueFamily๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ปค๋งจ๋“œ ํ’€์ด โ€œ๊ทธ๋ž˜ํ”ฝ์Šคโ€ ํŒจ๋ฐ€๋ฆฌ์˜ ํ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋งจ๋“œ ๋ฒ„ํผ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ .flags ์ธ์ž๋„ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ Vulkan ๊ตฌ์กฐ์ฒด๋“ค์€ ์ถ”๊ฐ€ ์˜ต์…˜์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด .flags ์ธ์ง€๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT์„ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋Š” Vulkan์—๊ฒŒ ํ•ด๋‹น ํ’€์—์„œ ์ƒ์„ฑ๋œ ๊ฐœ๋ณ„ ์ปค๋งจ๋“œ ๋ฒ„ํผ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๋ฆฌ์…‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ์„ค์ •์ž…๋‹ˆ๋‹ค. ๋Œ€์•ˆ์œผ๋กœ๋Š” ์ „์ฒด ์ปค๋งจ๋“œ ํ’€์„ ํ•œ๋ฒˆ์— ๋ฆฌ์…‹ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ’€์— ์†ํ•œ ๋ชจ๋“  ์ปค๋งจ๋“œ ๋ฒ„ํผ๊ฐ€ ํ•จ๊ป˜ ์ดˆ๊ธฐํ™”๋˜๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์—์„œ๋Š” ํ•ด๋‹น ํ”Œ๋ž˜๊ทธ๋ฅผ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ VkCreateCommandPool๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, VkDevice, ์ƒ์„ฑ ์ธ์ž๋กœ ์‚ฌ์šฉํ•  commandPoolInfo, ๊ทธ๋ฆฌ๊ณ  _commandPool๋ฉค๋ฒ„์˜ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ์ด ์„ฑ๊ณตํ•˜๋ฉด _commandPool ๋ฉค๋ฒ„๊ฐ€ ์ƒˆ๋กœ์šด ํ•ธ๋“ค๋กœ ๋ฎ์–ด์”Œ์›Œ์ง‘๋‹ˆ๋‹ค.

๋ช…๋ น์ด ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด VK_CHECK() ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ฆ‰์‹œ ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘๋‹จํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค

์ด์ œ VkCommandPool์ด ์ƒ์„ฑ๋˜์–ด _commandPool๋ฉค๋ฒ„์— ์ €์žฅ๋˜์—ˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ํ†ตํ•ด ์ปค๋งจ๋“œ ๋ฒ„ํผ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋งจ๋“œ ํ’€๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, sType๊ณผ pNext๋ฅผ ์„ค์ •ํ•˜๊ณ  ๋‚˜๋จธ์ง€ Info ๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ๋ฅผ ์ฑ„์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Vulkan์—๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ _commandPool์„ ์ปค๋งจ๋“œ ๋ฒ„ํผ์˜ ๋ถ€๋ชจ๋กœ ์ง€์ •ํ•˜๋ฉฐ, ํ•˜๋‚˜์˜ ์ปค๋งจ๋“œ ๋ฒ„ํผ๋งŒ์„ ์ƒ์„ฑํ•˜๊ฒ ๋‹ค๊ณ  ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

.commandBufferCount ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ์ปค๋งจ๋“œ ๋ฒ„ํผ๋ฅผ ํ•œ ๋ฒˆ์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. VkAllocateCommandBuffer๋กœ ์ „๋‹ฌํ•˜๋Š” ํฌ์ธํ„ฐ๊ฐ€ ํ•ด๋‹น ๊ฐœ์ˆ˜ ๋งŒํผ์˜ ๊ณต๊ฐ„์ด ํ™•๋ณดํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

.level์€ Primary๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ปค๋งจ๋“œ ๋ฒ„ํผ์˜ ๋ ˆ๋ฒจ์€ Primary ํ˜น์€ Secondary๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Primary ๋ ˆ๋ฒจ์€ VkQueue๋กœ ์ „๋‹ฌ๋˜์–ด ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” Primary๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Secondary ๋ ˆ๋ฒจ์€ Primary ๋ฒ„ํผ์˜ โ€œํ•˜์œ„๋ช…๋ นโ€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ๋‹จ์ผ ํŒจ์Šค ํ™˜๊ฒฝ์—์„œ ๋ช…๋ น์„ ๊ธฐ๋กํ•  ๋•Œ ํ”ํžˆ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๊ฐ€ ๊ตฌ์ถ•ํ•  ์•„ํ‚คํ…์ฒ˜์—์„œ๋Š” ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ Secondary ์ปค๋งจ๋“œ ๋ฒ„ํผ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ info ๊ตฌ์กฐ์ฒด์— ์‚ฌ์šฉ๋˜๋Š” ์ธ์ž์™€ ์„ธ๋ถ€์‚ฌํ•ญ์— ๊ด€ํ•œ ์ •๋ณด๋Š” ์•„๋ž˜ ๋งํฌ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

VkInit ๋ชจ๋“ˆ

ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์„ ๋‹ค๋ฃฌ ๊ธ€์„ ๊ธฐ์–ตํ•œ๋‹ค๋ฉด, vk_initializers ๋ชจ๋“ˆ์ด ๋‹ค์–‘ํ•œ Vulkan ๊ตฌ์กฐ์ฒด ์ดˆ๊ธฐํ™” ๊ณผ์ •์˜ ์ถ”์ƒํ™”๋ฅผ ํฌํ•จํ•œ๋‹ค๊ณ  ์–ธ๊ธ‰ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๋‘ ๊ตฌ์กฐ์ฒด์˜ ๊ตฌํ˜„์„ ์‚ดํŽด๋ด…์‹œ๋‹ค.

VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex,
    VkCommandPoolCreateFlags flags /*= 0*/)
{
    VkCommandPoolCreateInfo info = {};
    info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    info.pNext = nullptr;
    info.queueFamilyIndex = queueFamilyIndex;
    info.flags = flags;
    return info;
}


VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info(
    VkCommandPool pool, uint32_t count /*= 1*/)
{
    VkCommandBufferAllocateInfo info = {};
    info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    info.pNext = nullptr;

    info.commandPool = pool;
    info.commandBufferCount = count;
    info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    return info;
}

์ปค๋งจ๋“œ ๋ฒ„ํผ์˜ ๋ ˆ๋ฒจ์„ VK_COMMAND_BUFFER_LEVEL_PRIMARY๋กœ ํ•˜๋“œ์ฝ”๋”ฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์„ธ์ปจ๋”๋ฆฌ ์ปค๋งจ๋“œ ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—”์ง„์— ๋งž๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•จ์œผ๋กœ์„œ ์ „์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ๋‹จ์ˆœํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

void VulkanEngine::init_commands()
{
	//create a command pool for commands submitted to the graphics queue.
	//we also want the pool to allow for resetting of individual command buffers
	VkCommandPoolCreateInfo commandPoolInfo = vkinit::command_pool_create_info(_graphicsQueueFamily, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);

	for (int i = 0; i < FRAME_OVERLAP; i++) {

		VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool));

		// allocate the default command buffer that we will use for rendering
		VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_frames[i]._commandPool, 1);

		VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer));
	}
}

๋” ๋‚ซ๊ณ  ๋” ์งง์•„์กŒ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ด๋“œ๋ฅผ ๊ฑฐ์น˜๋ฉฐ vkinit ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋ฏ€๋กœ, ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 0์žฅ์—์„œ ์„ค๋ช…ํ•œ๋Œ€๋กœ starting_point ๋ธŒ๋žœ์น˜์— ์ž‘์„ฑ๋˜์—ˆ์Œ์„ ์œ ์˜ํ•˜์„ธ์š”.

์ •๋ฆฌ

์ด์ „๊ณผ ๊ฐ™์ด ์ƒ์„ฑํ•œ ๊ฐ์ฒด๋ฅผ ํŒŒ๊ดดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

void VulkanEngine::cleanup()
{
	if (_isInitialized) {
		//make sure the gpu has stopped doing its things
		vkDeviceWaitIdle(_device);

		for (int i = 0; i < FRAME_OVERLAP; i++) {
			vkDestroyCommandPool(_device, _frames[i]._commandPool, nullptr);
		}

		// --- rest of code
	}
}

์ปค๋งจ๋“œ ํ’€์ด ๊ฐ€์žฅ ์ตœ๊ทผ์— ์ƒ์„ฑํ•œ Vulkan ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๊ฐ์ฒด๋ณด๋‹ค ๋จผ์ € ํŒŒ๊ดดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. VkCommandBuffer๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ํŒŒ๊ดดํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ปค๋งจ๋“œ ํ’€์ด ํŒŒ๊ดด๋˜๋ฉด ํ•ด๋‹น ํ’€์—์„œ ํ• ๋‹น๋œ ๋ชจ๋“  ์ปค๋งจ๋“œ ๋ฒ„ํผ๊ฐ€ ํ•จ๊ป˜ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ VkQueue๋“ค์€ VkPhysicalDevice์ฒ˜๋Ÿผ ํŒŒ๊ดด๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋“ค์€ ์‹ค์ œ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ VkInstance์˜ ์ผ๋ถ€์— ๋Œ€ํ•œ ํ•ธ๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด์ œ GPU๋กœ ๋ช…๋ น์„ ์ „์†กํ•  ๋ฐฉ๋ฒ•์„ ๋งˆ๋ จํ–ˆ์ง€๋งŒ, CPU์™€ GPU๊ฐ„ ์‹คํ–‰์„ ๋™๊ธฐํ™”ํ•  ๊ตฌ์กฐ์ฒด๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Next: Rendering Loop