ํต์ฌ Vulkan ๊ตฌ์กฐ์ฒด ์ด๊ธฐํํ๊ธฐ
0์ฅ์ ์ฝ๋์์ ์์ํ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. ํ๋ก์ ํธ ์ค์ ์ ํ์ง ์์๋ค๋ฉด 0์ฅ์์ ํ๋ก์ ํธ๋ฅผ ์ค์ ํ ํ ์ฝ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
์ฐ์ ์ด๊ธฐํ ์ฝ๋๋ฅผ ๊ฐ๋จํ ํ๊ธฐ ์ํ vkBootstrap ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ #include
๋ก ๊ฐ์ ธ์ต๋๋ค. ์ด๋ฅผ ์ํด vk_engine.cpp
์๋จ์ "VkBootstrap.h"
ํค๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
// --- other includes ---
#include <vk_types.h>
#include <vk_initializers.h>
//bootstrap library
#include "VkBootstrap.h"
VkBootstrap์ ์์ง์ ์ด๊ธฐํ ์ฝ๋๋ฅผ ๋ํญ ์ค์ฌ ์๋ฐฑ ์ค์ ์ฝ๋๋ฅผ ์๋ตํ ์ ์๋๋ก ํฉ๋๋ค. VkBootstrap์์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์๊ณ ์ถ๋ค๋ฉด vulkan-tutorial์ ์ฝ์ด๋ณด๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค.
๊ฐ์ฅ ๋จผ์ ์ด๊ธฐํํด์ผ๋๋ ๊ฒ์ Vulkan Instance์
๋๋ค. ์ด๋ฅผ ์ํด ์๋ก์ด ํจ์์ ํธ๋ค์ ์ ์ฅํ ๋ณ์๋ฅผ VulkanEngine
ํด๋์ค์ ์ถ๊ฐํฉ๋๋ค. ๋ํ, ๋ค๋ฅธ ์ด๊ธฐํ๋ฅผ ์ํ ๋ช๊ฐ์ง ํจ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
vk_engine.h
class VulkanEngine {
public:
// --- omitted ---
VkInstance _instance;// Vulkan library handle
VkDebugUtilsMessengerEXT _debug_messenger;// Vulkan debug output handle
VkPhysicalDevice _chosenGPU;// GPU chosen as the default device
VkDevice _device; // Vulkan device for commands
VkSurfaceKHR _surface;// Vulkan window surface
private:
void init_vulkan();
void init_swapchain();
void init_commands();
void init_sync_structures();
์ด์ ์ด๋ฌํ init
ํจ์๋ค์ ์์ง์ init
ํจ์์์ ํธ์ถํ ๊ฒ์
๋๋ค.
vk_engine.cpp
constexpr bool bUseValidationLayers = false;
void VulkanEngine::init()
{
// We initialize SDL and create a window with it.
SDL_Init(SDL_INIT_VIDEO);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN);
_window = SDL_CreateWindow(
"Vulkan Engine",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
_windowExtent.width,
_windowExtent.height,
window_flags
);
init_vulkan();
init_swapchain();
init_commands();
init_sync_structures();
//everything went fine
_isInitialized = true;
}
void VulkanEngine::init_vulkan()
{
//nothing yet
}
void VulkanEngine::init_swapchain()
{
//nothing yet
}
void VulkanEngine::init_commands()
{
//nothing yet
}
void VulkanEngine::init_sync_structures()
{
//nothing yet
}
๋ฉ์ธ ํด๋์ค์ VkDevice
, VkPhysicalDevice
, VkInstance
, VkDebugUtilsMessengerEXT
4๊ฐ์ ํธ๋ค์ ์ถ๊ฐํฉ๋๋ค.
Instance
์ด์ ์๋ก์ด init_Vulkan
ํจ์๊ฐ ์ถ๊ฐ๋์์ผ๋ฏ๋ก VkInstance
๋ฅผ ์์ฑํ๋ ์ฝ๋๋ฅผ ์์ฑํด๋ด
์๋ค.
void VulkanEngine::init_vulkan()
{
vkb::InstanceBuilder builder;
//make the vulkan instance, with basic debug features
auto inst_ret = builder.set_app_name("Example Vulkan Application")
.request_validation_layers(bUseValidationLayers)
.use_default_debug_messenger()
.require_api_version(1, 3, 0)
.build();
vkb::Instance vkb_inst = inst_ret.value();
//grab the instance
_instance = vkb_inst.instance;
_debug_messenger = vkb_inst.debug_messenger;
}
vkb::InstanceBuilder
๋ฅผ ๋ง๋ค ๊ฒ์
๋๋ค. ์ด๋ VkBootstrap ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ์ฒด๋ก, VkInstance
์์ฑ์ ๋ณด๋ค ๊ฐ๋จํ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ถ์ํํฉ๋๋ค.
์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ โExample Vulkan Applicationโ์ด๋ผ๋ ์ด๋ฆ์ ์ฌ์ฉํ๊ณ , ๊ฒ์ฆ ๋ ์ด์ด๋ฅผ ํ์ฑํ ํ๋ฉฐ, ๊ธฐ๋ณธ ๋๋ฒ๊ทธ ๋ก๊ฑฐ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. โExample Vulkan Applicationโ์ด๋ผ๋ ์ด๋ฆ์ ์ํ๋ ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ๋์ฒดํด๋ ์ข์ต๋๋ค. VkInstance
๋ฅผ ์ด๊ธฐํํ ๋, ์์ง๊ณผ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์ด๋ ๋๋ผ์ด๋ฒ ์ ์กฐ์ฌ๊ฐ ๊ฒ์/์์ง์ ์ด๋ฆ์ ์ฝ๊ฒ ์ฐพ์, ํด๋น ์ํํธ์จ์ด์ ๋ง๊ฒ ๋ด๋ถ ๋๋ผ์ด๋ฒ ๋ก์ง์ ์ต์ ํํ ์ ์๋๋ก ํ๊ธฐ ์ํจ์
๋๋ค. ์ฐ๋ฆฌ์๊ฒ๋ ๊ทธ๋ฆฌ ์ค์ํ ์ฌํญ์ ์๋๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๊ฒ์ฆ ๋ ์ด์ด๋ฅผ ํ์ฑํํด์ผํฉ๋๋ค. ์ด ๊ฐ์ด๋๋ฅผ ์งํํ๋ฉด์ ๊ฒ์ฆ ๋ ์ด์ด๊ฐ ์ค๋ฅ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ก์์ฃผ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋นํ์ฑํ ํ ํ์๋ ์์ต๋๋ค. ๋ ๊ณ ๊ธ ์์ง์์๋ ๋๋ฒ๊ทธ ๋ชจ๋์์๋ง ํ์ฑํํ๊ฑฐ๋, ํน์ ์ค์ ์ ํตํด ์กฐ์ ํ ์ ์์ต๋๋ค. Vulkan ๊ฒ์ฆ ๋ ์ด์ด๋ Vulkan ํธ์ถ ์ฑ๋ฅ์ ์๋นํ ์ ํ์ํฌ ์ ์์ผ๋ฉฐ, ๋ฐ๋ผ์ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๋ณต์กํ ์ฌ์ด ๋ถ๋ฌ์ฌ ๋ ์ค์ ์ฝ๋์ ์ฑ๋ฅ์ ํ๋ ค๋ฉด ์ด๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
Vulkan API 1.3๋ฒ์ ์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ด๋ ๋น๊ต์ ์ต์ GPU์์ ์ง์๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ Vulkan 1.3์ด ์ ๊ณตํ๋ ๊ธฐ๋ฅ๋ค์ ํ์ฉํ ๊ฒ์ ๋๋ค. ๋ง์ฝ ํด๋น ๊ธฐ๋ฅ์ ์ง์ํ์ง ์๋ ์ค๋๋ PC/GPU๋ฅผ ์ฌ์ฉ์ค์ด๋ผ๋ฉด Vulkan 1.1๋ฒ์ ์ ์ฌ์ฉํ๋ ์ด์ ๋ฒ์ ์ vkguide๋ฅผ ๋ณด๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ฒ๊ทธ ๋ฉ์ ์ ๋ฅผ ์ฌ์ฉ์ ์์ฒญํฉ๋๋ค. ์ด๋ ๊ฒ์ฆ ๋ ์ด์ด์ ์ถ๋ ฅ์ ๋ก๊ทธ๋ก ์์งํฉ๋๋ค. ์ฌ์ฉ์ ์ ์ ๋๋ฒ๊ทธ ๋ฉ์ ์ ๊ฐ ํ์ ์์ผ๋ฏ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ธฐ๋ณธ๊ฐ(์ฝ์ ์ฐฝ ์ถ๋ ฅ)์ ์ฌ์ฉํ๋๋ก ์ค์ ํฉ๋๋ค.
์ด์ vkb::Instance
๊ฐ์ฒด์์ VkInstance
ํธ๋ค๊ณผ VkDebugUtilsMessengerEXT
ํธ๋ค์ ๊ฐ์ ธ์ต๋๋ค. ํ๋ก๊ทธ๋จ ์ข
๋ฃ ์ ์ด๋ฅผ ์์ ํ๊ฒ ํด์ ํ ์ ์๋๋ก VkDebugUtilsMessengerEXT
๋ฅผ ๋ฐ๋ก ์ ์ฅํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
Device
void VulkanEngine::init_vulkan()
{
// other code ------
SDL_Vulkan_CreateSurface(_window, _instance, &_surface);
//vulkan 1.3 features
VkPhysicalDeviceVulkan13Features features{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES };
features.dynamicRendering = true;
features.synchronization2 = true;
//vulkan 1.2 features
VkPhysicalDeviceVulkan12Features features12{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES };
features12.bufferDeviceAddress = true;
features12.descriptorIndexing = true;
//use vkbootstrap to select a gpu.
//We want a gpu that can write to the SDL surface and supports vulkan 1.3 with the correct features
vkb::PhysicalDeviceSelector selector{ vkb_inst };
vkb::PhysicalDevice physicalDevice = selector
.set_minimum_version(1, 3)
.set_required_features_13(features)
.set_required_features_12(features12)
.set_surface(_surface)
.select()
.value();
//create the final vulkan device
vkb::DeviceBuilder deviceBuilder{ physicalDevice };
vkb::Device vkbDevice = deviceBuilder.build().value();
// Get the VkDevice handle used in the rest of a vulkan application
_device = vkbDevice.device;
_chosenGPU = physicalDevice.physical_device;
}
์ฌ์ฉํ GPU๋ฅผ ์ ํํ๊ธฐ ์ํด vkb::PhysicalDeviceSelector
๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค.
๊ฐ์ฅ ๋จผ์ , SDL ์ฐฝ์ผ๋ก๋ถํฐ VkSurfaceKHR
๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์ด ๊ฐ์ฒด๋ ์ค์ ๋ก ๋ ๋๋ง์ด ์ด๋ฃจ์ด์ง ์ฐฝ์ด๋ฏ๋ก, PhysicalDeviceSelector
์๊ฒ ํด๋น ์ฐฝ์ ๋ ๋๋งํ ์ ์๋ GPU๋ฅผ ์ ํํ๋๋ก ์ง์ํด์ผ ํฉ๋๋ค.
๋ช ๊ฐ์ง ๊ธฐ๋ฅ๋ ํ์ฑํํด์ผ ํฉ๋๋ค. ์ฐ์ Vulkan 1.3 ๊ธฐ๋ฅ์ผ๋ก๋ Dynamic Rendering๊ณผ Synchronization 2๊ฐ ์์ต๋๋ค. ์ด๋ค์ Vulkan 1.3์์ ์ ๊ณตํ๋ ์ ํ์ ์ธ ๊ธฐ๋ฅ์ผ๋ก, Dynamic rendering์ ์ฌ์ฉํ๋ฉด ๋ ๋ํจ์ค์ ํ๋ ์๋ฒํผ๋ฅผ ์๋ตํ ์ ์์ต๋๋ค(์ด์ ๋ํด ๋ ์๊ณ ์ถ๋ค๋ฉด ๊ตฌ๋ฒ์ ์ VkGuide๋ฅผ ์ฐธ๊ณ ํ์ธ์). ๋ํ ์๋ก์ด ๋๊ธฐํ ํจ์๋ค์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ด์ ํจ๊ป Vulkan1.2 ๊ธฐ๋ฅ์ธ BufferDeviceAddress์ descriptorIndexing๋ ์ฌ์ฉํ ์์ ์ ๋๋ค. BufferDeviceAddress๋ ๋ฒํผ๋ฅผ ๋ฐ์ธ๋ฉํ์ง ์๊ณ ๋ GPU ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ฉฐ, descriptorIndexing์ ๋ฐ์ธ๋๋ฆฌ์ค ํ ์ค์ณ๋ฅผ ์ง์ํฉ๋๋ค.
vkb::PhysicalDeviceSelector
์ VkPhysicalDeviceVulkan13Features
๊ตฌ์กฐ์ฒด๋ฅผ ์ ๋ฌํจ์ผ๋ก์จ, vkbootstrap์๊ฒ ํด๋น ๊ธฐ๋ฅ๋ค์ ์ง์ํ๋ GPU๋ฅผ ์ฐพ๋๋ก ์์ฒญํ ์ ์์ต๋๋ค.
Vulkan ๋ฒ์ ์ ๋ฐ๋ผ ์ฌ์ฉํ ์ ์๋ ๋ค์ํ ๋ ๋ฒจ์ ๊ธฐ๋ฅ ๊ตฌ์กฐ์ฒด๊ฐ ์์ผ๋ฉฐ, ์๋ ๋งํฌ์์ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
Vulkan Spec: 1.0 physical device features Vulkan Spec: 1.1 physical device features Vulkan Spec: 1.2 physical device features Vulkan Spec: 1.3 physical device features
VkPhysicalDevice
๋ฅผ ์ป์์ผ๋ฉด ์ด๋ก๋ถํฐ VkDevice
๋ฅผ ์ง์ ์์ฑํ ์ ์์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก ์์ฑ๋ ํธ๋ค์ ํด๋์ค์ ์ ์ฅํฉ๋๋ค.
์ด๊ฒ์ผ๋ก ๋๋ฌ์ต๋๋ค. Vulkan์ด ์ด๊ธฐํ๋์์ต๋๋ค. ์ด์ Vulkan ๋ช ๋ น์ ํธ์ถํ ์ ์์ต๋๋ค.
์ด ์์ ์์ ํ๋ก์ ํธ๋ฅผ ์คํํ๋ฉด, ํ์ํ ๊ธฐ๋ฅ์ ์ง์ํ์ง ์๊ฑฐ๋ Vulkan ๋๋ผ์ด๋ฒ๊ฐ ์ค์น๋์ด ์์ง ์์ GPU๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ํฌ๋์๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ, ๋๋ผ์ด๋ฒ๊ฐ ์ต์ ์ธ์ง ํ์ธํ์ธ์. ๋ง์ฝ GPU ์์ฒด๊ฐ ํด๋น ๊ธฐ๋ฅ์ ์ง์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ ์ด ํํ ๋ฆฌ์ผ์ ๋ฐ๋ผ๊ฐ ์ ์์ผ๋ฏ๋ก ๊ตฌ๋ฒ์ ์ VkGuide๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์.
์ค์์ฒด์ธ ์ค์ ํ๊ธฐ
ํต์ฌ ์ด๊ธฐํ ๊ณผ์ ์ ๋ง์ง๋ง ๋จ๊ณ๋ ์ค์์ฒด์ธ์ ์ด๊ธฐํํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋์ผ ๋ ๋๋งํ ์ ์๋ ๋์์ด ์๊น๋๋ค.
๋จผ์ VulkanEngine
์ ์๋ก์ด ๋ฉค๋ฒ์ ํจ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
class VulkanEngine {
public:
// --- other code ---
VkSwapchainKHR _swapchain;
VkFormat _swapchainImageFormat;
std::vector<VkImage> _swapchainImages;
std::vector<VkImageView> _swapchainImageViews;
VkExtent2D _swapchainExtent;
private:
void create_swapchain(uint32_t width, uint32_t height);
void destroy_swapchain();
}
VkSwapchainKHR
์์ฒด์ ํจ๊ป, ์ค์์ฒด์ธ ์ด๋ฏธ์ง๋ค์ด ๋ ๋๋ง์ ์ฌ์ฉํ ํฌ๋งท๋ ์ ์ฅํฉ๋๋ค.
๋ํ ๋ ๊ฐ์ ๋ฐฐ์ด์ ์ ์ฅํ๋๋ฐ, ํ๋๋ VkImage
์ ๋ฐฐ์ด์ด๊ณ ๋ค๋ฅธ ํ๋๋ VkImageView
์ ๋ฐฐ์ด์
๋๋ค.
VkImage
๋ ํ
์ค์ณ๋ก ์ฌ์ฉํ๊ฑฐ๋ ๋ ๋๋ง ๋์์ด ๋๋ ์ค์ ์ด๋ฏธ์ง ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ํธ๋ค์
๋๋ค. VkImageView
๋ ํด๋น ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ธ๋ ๋ํผ๋ก, ์์ ํฌ๋งท์ ๋ณ๊ฒฝํ๋ ๋ฑ์ ์์
์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด์ ๋ํด์๋ ์ดํ์ ๋ ์์ธํ ๋ค๋ฃฐ ์์ ์
๋๋ค.
๋ํ ์ค์์ฒด์ธ์ ์ํ ์์ฑ ๋ฐ ์ ๊ฑฐ ํจ์๋ ์ถ๊ฐํฉ๋๋ค.
๋ค๋ฅธ ์ด๊ธฐํ ํจ์๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, vkb
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์ค์์ฒด์ธ์ ์์ฑํ ๊ฒ์
๋๋ค. ์ด๋ VkInstance
์ VkDevice
๋ฅผ ๋ง๋ค ๋ ์ฌ์ฉํ ๊ฒ๊ณผ ์ ์ฌํ ๊ฒ์
๋๋ค.
void VulkanEngine::create_swapchain(uint32_t width, uint32_t height)
{
vkb::SwapchainBuilder swapchainBuilder{ _chosenGPU,_device,_surface };
_swapchainImageFormat = VK_FORMAT_B8G8R8A8_UNORM;
vkb::Swapchain vkbSwapchain = swapchainBuilder
//.use_default_format_selection()
.set_desired_format(VkSurfaceFormatKHR{ .format = _swapchainImageFormat, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR })
//use vsync present mode
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR)
.set_desired_extent(width, height)
.add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
.build()
.value();
_swapchainExtent = vkbSwapchain.extent;
//store swapchain and its related images
_swapchain = vkbSwapchain.swapchain;
_swapchainImages = vkbSwapchain.get_images().value();
_swapchainImageViews = vkbSwapchain.get_image_views().value();
}
void VulkanEngine::init_swapchain()
{
create_swapchain(_windowExtent.width, _windowExtent.height);
}
create_swapchain()
์์ ์ค์์ฒด์ธ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ ๋ค, init_swapchain()
์์ ํด๋น ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ ํ์ ๋ชจ๋(Present Mode)๋ก, VK_PRESENT_MODE_FIFO_KHR
์ ์ค์ ํ ๋ถ๋ถ์
๋๋ค. ์ด ์ค์ ์ ์๊ฒฉํ VSync๋ฅผ ์๋ฏธํ๋ฉฐ, ์ ์ฒด ์์ง์ FPS๋ฅผ ๋ชจ๋ํฐ ์ฃผ์ฌ์จ์ ๋ง์ถฐ ์ ํํ๊ฒ ๋ฉ๋๋ค.
๋ํ ์ค์์ฒด์ธ ์์ฑ ์ ์ฐฝ์ ํฌ๊ธฐ๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ค์์ฒด์ธ์ ์์ฑํ๋ฉด ๋์์ ํด๋น ํฌ๊ธฐ์ ๋ง๋ ์ด๋ฏธ์ง๋ค๋ ์์ฑ๋๋ฏ๋ก, ์ด๋ฏธ์ง ํฌ๊ธฐ๋ ๊ณ ์ ๋ฉ๋๋ค. ์ดํ ํํ ๋ฆฌ์ผ์์๋ ์ฐฝ ํฌ๊ธฐ ๋ณ๊ฒฝ์ ๋ฐ๋ผ ์ค์์ฒด์ธ์ ๋ค์ ์์ฑํด์ผ ํ๋ฏ๋ก, ์ด๊ธฐํ ํ๋ฆ๊ณผ ๋ถ๋ฆฌํด ๊ด๋ฆฌํ ์์ ์ ๋๋ค. ํ์ง๋ง ์ด๊ธฐํ ์์ ์์๋ ์ฐฝ์ ํฌ๊ธฐ๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
์ค์์ฒด์ธ์ด ์์ฑ๋๋ฉด, ๊ทธ์ ๊ด๋ จ๋ ๋ชจ๋ ์ ๋ณด๋ฅผ VulkanEngine
ํด๋์ค์ ๋ฉค๋ฒ ๋ณ์์ ์ ์ฅํฉ๋๋ค.
destroy_swapchain()
ํจ์๋ ์์ฑํด๋ด
์๋ค.
void VulkanEngine::destroy_swapchain()
{
vkDestroySwapchainKHR(_device, _swapchain, nullptr);
// destroy swapchain resources
for (int i = 0; i < _swapchainImageViews.size(); i++) {
vkDestroyImageView(_device, _swapchainImageViews[i], nullptr);
}
}
์ฐ์ ์ค์์ฒด์ธ ๊ฐ์ฒด๋ฅผ ์ญ์ ํ๋๋ฐ, ์ด ์์
์ ๋ด๋ถ์ ์ผ๋ก ํฌํจ๋ ์ด๋ฏธ์ง๋ค๋ ํจ๊ป ์ญ์ ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์, ์ด ์ด๋ฏธ์ง๋ค์ ํด๋นํ๋ ImageView
๋ค๋ ๋ฐ๋ก ์ ๊ฑฐํด์ฃผ์ด์ผ ํฉ๋๋ค.
์์ ์ ๋ฆฌํ๊ธฐ
์ ํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋ ๋ ์ฐ๋ฆฌ๊ฐ ์์ฑํ ๋ชจ๋ Vulkan ์์๋ค์ด ์ฌ๋ฐ๋ฅด๊ฒ ํด์ ๋๋๋ก ํด์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด VulkanEngine::cleanup()
ํจ์๋ก ์ด๋ํฉ์๋ค.
void VulkanEngine::cleanup()
{
if (_isInitialized) {
destroy_swapchain();
vkDestroySurfaceKHR(_instance, _surface, nullptr);
vkDestroyDevice(_device, nullptr);
vkb::destroy_debug_utils_messenger(_instance, _debug_messenger);
vkDestroyInstance(_instance, nullptr);
SDL_DestroyWindow(_window);
}
}
๊ฐ์ฒด๋ค ๊ฐ์๋ ์์กด์ฑ์ด ์๊ธฐ ๋๋ฌธ์, ์ฌ๋ฐ๋ฅธ ์์๋ก ์ญ์ ํด์ผ ํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์์ฑํ ์์์ ์ญ์์ผ๋ก ์ญ์ ํ๋ ๊ฒ์ด ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ค ๊ฒฝ์ฐ์๋, ๋ง์ฝ ๊ตฌ์กฐ๋ฅผ ์ ์ดํดํ๊ณ ์๋ค๋ฉด ์์๋ฅผ ์ฝ๊ฐ ๋ฐ๊พธ์ด๋ ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค.
VkPhysicalDevice
๋ Vulkan ์์ ๊ทธ ์์ฒด๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ญ์ ํ ์ ์์ต๋๋ค. ์ด๋ ์์คํ
๋ด GPU๋ฅผ ๊ฐ๋ฆฌํค๋ ํธ๋ค์ผ ๋ฟ์
๋๋ค.
์ฐ๋ฆฌ๋ Window โ Instance โ Surface โ Device โ Swapchain ์์๋ก ์ด๊ธฐํํ๊ธฐ ๋๋ฌธ์, ์ญ์ ๋ ์ ํํ ๊ทธ ๋ฐ๋ ์์๋ก ์ํ๋ฉ๋๋ค.
์ง๊ธ ํ๋ก๊ทธ๋จ์ ์คํํด๋ณด๋ฉด ์๋ฌด๊ฒ๋ ํ์ง ์์ ๊ฒ์ ๋๋ค. ํ์ง๋ง ๊ทธ โ์๋ฌด๊ฒ๋ ํ์ง ์์โ์๋ ์๋ฌ๋ ๋ฐ์ํ์ง ์๋๋ค๋ ์ ์ด ํฌํจ๋ฉ๋๋ค.
์ด๋ฒ ๊ฒฝ์ฐ์๋ VkImage
๋ค์ ๋ณ๋๋ก ์ญ์ ํ ํ์๋ ์์ต๋๋ค. ์๋ํ๋ฉด ์ด๋ฏธ์ง๋ค์ ์ค์์ฒด์ธ์ ์์ ๋์ด ์๊ณ , ์ค์์ฒด์ธ์ ์ญ์ ํ ๋ ํจ๊ป ์ญ์ ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ฒ์ฆ ๋ ์ด์ด ์๋ฌ
๊ฒ์ฆ ๋ ์ด์ด๊ฐ ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ๊ธฐ ์ํด, ์ด๋ฒ์๋ ์๋์ ์ผ๋ก ์๋ชป๋ ์์๋ก ํ๊ดด ํจ์๋ฅผ ํธ์ถํด๋ณด๊ฒ ์ต๋๋ค.
void VulkanEngine::cleanup()
{
if (_isInitialized) {
//ERROR - Instance destroyed before others
vkDestroyInstance(_instance, nullptr);
destroy_swapchain();
vkDestroyDevice(_device, nullptr);
vkDestroySurfaceKHR(_instance, _surface, nullptr);
vkb::destroy_debug_utils_messenger(_instance, _debug_messenger);
SDL_DestroyWindow(_window);
}
}
์ง๊ธ ์ฐ๋ฆฌ๋ VkInstance
๋ฅผ VkDeivce
์ VkInstance
๋ก๋ถํฐ ์์ฑ๋ VkSurfaceKHR
๋ณด๋ค ๋จผ์ ์ญ์ ํ๊ณ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๊ฒ์ฆ ๋ ์ด์ด๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ ๋ฉ์์ง๋ก ๊ฒฝ๊ณ ๋ฅผ ์ถ๋ ฅํ ๊ฒ์
๋๋ค.
[ERROR: Validation]
Validation Error: [ VUID-vkDestroyInstance-instance-00629 ] Object 0: handle = 0x24ff02340c0, type = VK_OBJECT_TYPE_INSTANCE; Object 1: handle = 0xf8ce070000000002, type = VK_OBJECT_TYPE_SURFACE_KHR; | MessageID = 0x8b3d8e18 | OBJ ERROR : For VkInstance 0x24ff02340c0[], VkSurfaceKHR 0xf8ce070000000002[] has not been destroyed. The Vulkan spec states: All child objects created using instance must have been destroyed prior to destroying instance (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyInstance-instance-00629)
Vulkan ์ด๊ธฐํ๊ฐ ์๋ฃ๋์๊ณ ๊ฒ์ฆ ๋ ์ด์ด๋ ์ ์์ ์ผ๋ก ์๋ํ๋ฏ๋ก, ์ด์ GPU๊ฐ ๋ฌด์ธ๊ฐ๋ฅผ ์ํํ ์ ์๋๋ก ๋ช ๋ น ๊ตฌ์กฐ์ฒด๋ฅผ ์ค๋นํ๊ฒ ์ต๋๋ค.
Next: Executing Vulkan Commands