Link

์ฐฝ ํฌ๊ธฐ ์žฌ์กฐ์ •ํ•˜๊ธฐ

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

์ฐฝ ํฌ๊ธฐ๊ฐ€ ์กฐ์ •๋  ๋•Œ ์Šค์™‘์ฒด์ธ์€ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋ฉฐ, vkAcquireNextImageKHR, vkQueuePresentKHR๊ณผ ๊ฐ™์€ Vulkan์˜ ์Šค์™‘์ฒด์ธ ๋ช…๋ น์€ VK_ERROR_OUT_OF_DATE_KHR ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜์—ฌ ์Šค์™‘์ฒด์ธ์„ ์ƒˆ๋กœ์šด ํฌ๊ธฐ๋กœ ์žฌ์ƒ์„ฑํ•˜๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํšจ์œจ์„ฑ์„ ์œ„ํ•ด drawImage๋ฅผ ์žฌํ• ๋‹นํ•˜์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ์€ drawImage์™€ depthImage๋งŒ์„ ๊ฐ–์ง€๋งŒ ์กฐ๊ธˆ ๋” ๊ณ ๋„ํ™”๋œ ์—”์ง„์—์„œ๋Š” ์ƒ๋‹นํžˆ ๋งŽ์€ ์ด๋ฏธ์ง€๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋ฉฐ ์ด ๋ชจ๋“  ๊ฒƒ์„ ์žฌ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ๋น„์šฉ์ด ํฝ๋‹ˆ๋‹ค. ๋Œ€์‹ , drawImage์™€ depthImage๋ฅผ ์‹œ์ž‘ ์‹œ ํ”„๋ฆฌ์…‹๋œ ํฌ๊ธฐ๋กœ ์ƒ์„ฑํ•ด ์ฐฝ์ด ์ž‘์„ ๊ฒฝ์šฐ ํ•ด๋‹น ์ด๋ฏธ์ง€์˜ ์ผ๋ถ€๋ถ„์— ๋ Œ๋”๋งํ•˜๊ณ , ์ฐฝ์ด ์ปค์ง€๋ฉด ๋” ๋„“์€ ์˜์—ญ์— ๋ Œ๋”๋งํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€๋ฅผ ์žฌํ• ๋‹นํ•˜์ง€ ์•Š๊ณ  ๊ตฌ์„์—๋งŒ ๋ Œ๋”๋งํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋กœ์ง์€ ๋™์  ํ•ด์ƒ๋„ ๊ตฌํ˜„์—๋„ ์‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์  ํ•ด์ƒ๋„๋Š” ์„ฑ๋Šฅ์„ ์œ ์—ฐํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ฉฐ, ๋””๋ฒ„๊น… ์‹œ์—๋„ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ drawImage์—์„œ ์Šค์™‘์ฒด์ธ ์ด๋ฏธ์ง€๋กœ VkCmdBlit์„ ์‚ฌ์šฉํ•ด ๋ณต์‚ฌํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ด ์—ฐ์‚ฐ์€ ํ™•๋Œ€ ์ถ•์†Œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์—์„œ๋„ ์ž˜ ์ž‘๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์˜ ํ™•๋Œ€ ์ถ•์†Œ๋Š” ์ตœ๊ณ  ํ’ˆ์งˆ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ํ™•๋Œ€ ์‹œ sharpening๊ฐ™์€ ์ถ”๊ฐ€ ํ•„ํ„ฐ๋ฅผ ์ ์š”ํ•˜๊ฑฐ๋‚˜, ์•ˆํ‹ฐ์•จ๋ฆฌ์–ด์‹ฑ ํšจ๊ณผ๋ฅผ ํ‰๋‚ด๋‚ด๋Š” ๋“ฑ์˜ ๋ณต์žกํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๋”ํ•ด์ ธ์•ผ ์ข‹์€ ํ’ˆ์งˆ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ImGui UI๋Š” ์—ฌ์ „ํžˆ ์Šค์™‘์ฒด์ธ ์ด๋ฏธ์ง€์— ์ง์ ‘ ๊ทธ๋ฆด ๊ฒƒ์ด๋ฏ€๋กœ, ํ•ญ์ƒ ๋„ค์ดํ‹ฐ๋ธŒ ํ•ด์ƒ๋„๋กœ ๋ Œ๋”๋งํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ์ฐฝ ์ƒ์„ฑ ์‹œ ์ฐฝ ํฌ๊ธฐ ์กฐ์ • ๊ฐ€๋Šฅ(resizable) ํ”Œ๋ž˜๊ทธ๋ฅผ ํ™œ์„ฑํ™”ํ•ด๋ด…์‹œ๋‹ค. ๊ทธํ›„ ์‹ค์ œ๋กœ ์ฐฝ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•ด ๋ณด๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

VulkanEngine::init์˜ ์ƒ๋‹จ์— window_flags๋ฅผ ๋ฐ”๊พธ์–ด resizable ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ฐ–๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);

SDL์€ ์ฐฝ ํฌ๊ธฐ ์กฐ์ •๊ณผ ๊ด€๋ จ๋œ ์šด์˜์ฒด์ œ ๋ ˆ๋ฒจ์˜ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋ฏ€๋กœ, ์ง€๊ธˆ ๋‹น์žฅ ์ฐฝ ํฌ๊ธฐ ์กฐ์ •์„ ์‹œ๋„ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—”์ง„์„ ์‹คํ–‰ํ•ด ์ฐฝ์„ ์žฌ์กฐ์ •ํ•ด๋ด…์‹œ๋‹ค.

์ด ์ž‘์—…์„ ํ•˜๋ฉด vkAcquireNextImageKHR ํ˜น์€ vkQueuePresentKHR ์ค‘ ํ•˜๋‚˜์—์„œ VK_CHECK ๋งคํฌ๋กœ๊ฐ€ ์—๋Ÿฌ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ํฌ๋ž˜์‹œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋Š” VK_ERROR_OUT_OF_DATE_KHR์ผ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์—๋Ÿฌ๋ฅผ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด, ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ Œ๋”๋ง์„ ์ค‘๋‹จํ•˜๊ณ  ์Šค์™‘์ฒด์ธ์„ ๋‹ค์‹œ ์ƒ์„ฑํ•ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ €, VulkanEngine ํด๋ž˜์Šค์— resize_requested๋ผ๋Š” ์ด๋ฆ„์˜ bool ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

draw()ํ•จ์ˆ˜์— vkAcquireNextImageKHR ํ˜ธ์ถœ์„ ์—๋Ÿฌ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

	VkResult e = vkAcquireNextImageKHR(_device, _swapchain, 1000000000, get_current_frame()._swapchainSemaphore, nullptr, &swapchainImageIndex);
	if (e == VK_ERROR_OUT_OF_DATE_KHR) {
        resize_requested = true;       
		return ;
	}

๋˜ํ•œ vkQueuePresentKHR๋„ ๋™์ผํ•˜๊ฒŒ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฏธ ํ•จ์ˆ˜์˜ ๋์ด๊ธฐ ๋•Œ๋ฌธ์— return์€ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

VkResult presentResult = vkQueuePresentKHR(_graphicsQueue, &presentInfo);
if (presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
    resize_requested = true;
}

์ด์ œ ํ•ด๋‹น ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ Œ๋”๋ง์„ ์ค‘๋‹จํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ, ์ฐฝ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•ด๋„ ํฌ๋ž˜์‹œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ฒ ์ง€๋งŒ, ํ™”๋ฉด์ด ๋‹ค์‹œ ๊ทธ๋ ค์ง€์ง€ ์•Š๊ณ  ์ด๋ฏธ์ง€๊ฐ€ ๋ฉˆ์ถ˜ ์ƒํƒœ๋กœ ์œ ์ง€๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

resize_swapchain()ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ VulkanEngine์ด ์Šค์™‘์ฒด์ธ์„ ์žฌ์ƒ์„ฑํ•˜๋„๋ก ํ•ฉ์‹œ๋‹ค.

void VulkanEngine::resize_swapchain()
{
	vkDeviceWaitIdle(_device);

	destroy_swapchain();

	int w, h;
	SDL_GetWindowSize(_window, &w, &h);
	_windowExtent.width = w;
	_windowExtent.height = h;

	create_swapchain(_windowExtent.width, _windowExtent.height);

	resize_requested = false;
}

์Šค์™‘์ฒด์ธ์„ ์žฌ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด GPU๊ฐ€ ๋ชจ๋“  ๋ Œ๋”๋ง ์ž‘์—…์„ ์™„๋ฃŒํ•  ๋•Œ ๊นŒ์ง€ ๋Œ€๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. GPU๊ฐ€ ์—ฌ์ „ํžˆ ์ด๋ฏธ์ง€์™€ ์ด๋ฏธ์ง€ ๋ทฐ๋ฅผ ์‚ฌ์šฉ์ค‘์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ ์ƒํƒœ์—์„œ ๋ณ€๊ฒฝํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๊ทธํ›„ ์Šค์™‘์ฒด์ธ์„ ํŒŒ๊ดดํ•˜๊ณ  SDL๋กœ๋ถ€ํ„ฐ ์ฐฝํฌ๊ธฐ๋ฅผ ์กฐํšŒํ•˜์—ฌ ๊ทธ์— ๋งž๊ฒŒ ์ƒˆ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ run() ๋ฐ˜๋ณต๋ฌธ์—์„œ ์ด๋ฏธ์ง€๊ฐ€ ์žฌ์กฐ์ •๋  ๋•Œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

SDL ์ด๋ฒคํŠธ ๋ฃจํ”„์™€ freeze_rendering ํ™•์ธ ์ดํ›„, ์ƒˆ๋กœ์šด ImGui ํ”„๋ ˆ์ž„์„ ์‹œ์ž‘ํ•˜๋Š” ํ•จ์ˆ˜๋“ค๋ณด๋‹ค ๋จผ์ € ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

if (resize_requested) {
	resize_swapchain();
}

์ด์ œ ์žฌ์กฐ์ • ๊ธฐ๋Šฅ์ด ๊ตฌํ˜„๋˜์—ˆ์œผ๋‹ˆ ํ•œ๋ฒˆ ์‹œ๋„ํ•ด๋ณด์„ธ์š”. ์ด์ œ ์—๋Ÿฌ ์—†์ด ์ด๋ฏธ์ง€ ์ถ•์†Œ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฐฝ์„ ๋” ํฌ๊ฒŒ ๋งŒ๋“ ๋‹ค๋ฉด ์‹คํŒจํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. drawImage ์˜์—ญ ๋ฐ–์œผ๋กœ ๋ Œ๋”๋งํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” _drawExtent ๋ณ€์ˆ˜๋ฅผ ๋„์ž…ํ•˜๊ณ  ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ drawImage ํฌ๊ธฐ๋ฅผ ์ดˆ๊ณผํ•˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•จ์œผ๋กœ์จ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

_drawExtent์™€ ๋™์  ํ•ด์ƒ๋„ ์กฐ์ ˆ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  renderScale float๋ฅผ VulkanEngine ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

VkExtent2D _drawExtent;
float renderScale = 1.f;

draw() ํ•จ์ˆ˜๋กœ ๋Œ์•„์™€ ์‹œ์ž‘ํ•  ๋•Œ ๊ธฐ์กด์— drawImage Extent๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„ ๋Œ€์‹  drawExtent๋ฅผ ๊ณ„์‚ฐํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

_drawExtent.height = std::min(_swapchainExtent.height, _drawImage.imageExtent.height) * renderScale;
_drawExtent.width= std::min(_swapchainExtent.width, _drawImage.imageExtent.width) * renderScale;

์ด์ œ ImGui์— ์Šฌ๋ผ์ด๋”๋ฅผ ์ถ”๊ฐ€ํ•ด drawScale ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

run()ํ•จ์ˆ˜์—์„œ ๋ฐฐ๊ฒฝ ๊ด€๋ จ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ImGui ์ฐฝ ๋‚ด๋ถ€์˜ ์ƒ๋‹จ์— ์ด ์Šฌ๋ผ์ด๋” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”.

if (ImGui::Begin("background")) {
ImGui::SliderFloat("Render Scale",&renderScale, 0.3f, 1.f);
//other code
}

์ด๋Š” 0.3์—์„œ 1.0๊นŒ์ง€์˜ ๋ Œ๋”๋ง ๋ฐฐ์œจ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์Šฌ๋ผ์ด๋”์ž…๋‹ˆ๋‹ค. 1์„ ์ดˆ๊ณผํ•˜๋ฉด ํ•ด์ƒ๋„๋ฅผ ๊นจํŠธ๋ฆด ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ด ์ฐฝ ํฌ๊ธฐ๋ฅผ ์žฌ์กฐ์ •ํ•˜๊ณ  ๋ Œ๋”๋ง ๋ฐฐ์œจ์„ ์กฐ์ •ํ•ด๋ณด์„ธ์š”. ์ด์ œ ๋™์ ์œผ๋กœ ํ•ด์ƒ๋„๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์ฐฝ์„ ์ตœ๋Œ€ํ™”ํ•˜๊ฑฐ๋‚˜ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ drawImage๋ฅผ ๋‹ค์†Œ ์ž‘์€ ํฌ๊ธฐ๋กœ ์„ค์ •ํ–ˆ์ง€๋งŒ ์›ํ•œ๋‹ค๋ฉด init_swapchain()์—์„œ ์ƒ์„ฑ๋˜๋Š” drawImage์˜ ํฌ๊ธฐ๋ฅผ ํ‚ค์›Œ๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. _windowExntent ๋Œ€์‹  ๋ชจ๋‹ˆํ„ฐ ํ•ด์ƒ๋„๋ฅผ drawImageExtent์— ์ง์ ‘ ์ง€์ •ํ•ด๋ณด์„ธ์š”.

์ด๊ฒƒ์œผ๋กœ 3์žฅ์ด ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค์Œ ์žฅ์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

Next: Chapter 4: New Descriptor Abstractions