์์ง์ด ์ ์ ์ปค์ง๋ฉด์ ์ฌ๋ผ์ด๋, ๋ฒํผ์ ์ถ๊ฐํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ํ ์ ์๋ ์ํธ์์ฉ ๊ฐ๋ฅํ ์ธํฐํ์ด์ค๊ฐ ํ์ํด์ก์ต๋๋ค.
์ด๋ฅผ ์ํด ํ๋ก์ ํธ์ dear ImGui ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ ๊ฒ์ ๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ui ์ค์ ์ด๋ ๋ณต์กํ ์์คํ ์ ๋ค๋ฃจ์ง ์๊ณ ๋ ์ฌ๋ผ์ด๋๋ ๋ฒํผ, ๊ธฐํ ํธ์ง๊ฐ๋ฅํ ํ ์คํธ์ ๊ฐ์ ์ํธ์์ฉ ์์์ ์ฐฝ์ ๋งค์ฐ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
Immediate GPU ๋ช ๋ น
๋ณด๋ฅ : ํด๋น ์น์ ์ ๋์ค์ ๋ค๋ฅธ ์์น๋ก ์ด๋ํ ์์ ์ ๋๋ค. ์ต์ ๋ฒ์ ์ ImGui์์๋ ์ ๋ก๋๋ฅผ ์ํด immediate ๋ช ๋ น์ด ํ์ํ์ง ์์ง๋ง, ์์ง์ ์ถํ ํํ ๋ฆฌ์ผ์์ immediate ๋ช ๋ น์ด ํ์ํฉ๋๋ค.
ImGui
๋ ์ผ๋ฐ์ ์ธ ๊ทธ๋ฆฌ๊ธฐ ๋ฃจํ ์ธ๋ถ์์ ๋ช ๊ฐ์ง ๋ช
๋ น์ ์คํํด์ผ ํฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ์์ง์์ ๋ค์ํ ์ฉ๋๋ก ์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ์ด๋ฅผ ์ํด immediate_submit
ํจ์๋ฅผ ๊ตฌํํ ๊ฒ์ด๋ฉฐ, ์ด ํจ์๋ ๊ทธ๋ฆฌ๊ธฐ์ ์ฌ์ฉํ๋ ์ปค๋งจ๋ ๋ฒํผ์๋ ๋ค๋ฅธ ๋ฒํผ์ ํ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ค์์ฒด์ธ์ด๋ ๋ ๋๋ง ๋ก์ง๊ณผ ๋๊ธฐํํ์ง ์๊ณ GPU์ ๋ช
๋ น์ ์ ์กํฉ๋๋ค.
VulkanEngine
ํด๋์ค์ ์ด๋ฌํ ๊ตฌ์กฐ์ฒด๋ฅผ ์ถ๊ฐํฉ์๋ค.
class VulkanEngine{
public:
// immediate submit structures
VkFence _immFence;
VkCommandBuffer _immCommandBuffer;
VkCommandPool _immCommandPool;
void immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function);
private:
void init_imgui();
}
์ฐ๋ฆฌ๋ ํ์ค์ ์ปค๋งจ๋ ๋ฒํผ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. immediate_submit
ํจ์๋ ๋๋ค์ ํจ๊ป ์ฌ์ฉํ ์ ์๋๋ก std::function
์ ์ฝ๋ฐฑ์ผ๋ก ๋ฐ์ต๋๋ค. init_imgui() ํจ์๋ ์ถ๊ฐํ๊ณ , init() ํจ์ ํธ์ถ ๋ง์ง๋ง์ ํธ์ถ๋๋๋ก ํฉ๋๋ค. ์ง๊ธ์ ๋น์๋ก๋๋ค.
immediate submit์ ์ํด ์ด๋ฌํ ๋๊ธฐํ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ฏ๋ก, init_commands()
ํจ์์ ๋ช
๋ น ๋ถ๋ถ์ ์ฐ๊ฒฐํฉ์๋ค.
void VulkanEngine::init_commands()
{
VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_immCommandPool));
// allocate the command buffer for immediate submits
VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_immCommandPool, 1);
VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_immCommandBuffer));
_mainDeletionQueue.push_function([=]() {
vkDestroyCommandPool(_device, _immCommandPool, nullptr);
});
}
์ด๋ ํ๋ ์๋ณ ๋ช ๋ น์ ์์ฑํ ๋์ ๊ฐ์ง๋ง, ์ด๋ฒ์๋ ์ ๋ฆฌ๋ฅผ ์ํด ์ญ์ ํ์ ์ง์ ์ถ๊ฐํ๊ณ ์์ต๋๋ค.
์ด์ ํ์ค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์ด๋ init_sync_structures()
์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
void VulkanEngine::init_sync_structures()
{
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &_immFence));
_mainDeletionQueue.push_function([=]() { vkDestroyFence(_device, _immFence, nullptr); });
}
ํ๋ ์๋ณ ํ์ค์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ fenceCreateInfo
๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ์ปค๋งจ๋ ๋ฒํผ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด๋ฅผ ์ญ์ ํ์ ์ง์ ๋ฃ์ด์ฃผ๊ฒ ์ต๋๋ค.
์ด์ immediate_submit
ํจ์๋ฅผ ๊ตฌํํ๊ฒ ์ต๋๋ค.
void VulkanEngine::immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function)
{
VK_CHECK(vkResetFences(_device, 1, &_immFence));
VK_CHECK(vkResetCommandBuffer(_immCommandBuffer, 0));
VkCommandBuffer cmd = _immCommandBuffer;
VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
function(cmd);
VK_CHECK(vkEndCommandBuffer(cmd));
VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd);
VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo, nullptr, nullptr);
// submit command buffer to the queue and execute it.
// _renderFence will now block until the graphic commands finish execution
VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, _immFence));
VK_CHECK(vkWaitForFences(_device, 1, &_immFence, true, 9999999999));
}
์ด ํจ์๊ฐ GPU์์ ๋ช ๋ น์ ์คํํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฑฐ์ ๋์ผํ๋ค๋ ์ ์ ์ฃผ๋ชฉํ์ธ์.
๊ฑฐ์ ๋์ผํ์ง๋ง ์ ์ถํ ๋ ์ค์์ฒด์ธ๊ณผ ๋๊ธฐํ๋ ์ํํ์ง ์๊ณ ์์ต๋๋ค.
๋ฐ์ดํฐ ์ ๋ก๋์ ๋ ๋๋ง ๋ฃจํ ์ธ๋ถ์์ ๊ธฐํ โ์ฆ๊ฐ์ ์ธโ ์์ ์ ์ด ํจ์๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ ์ค ํ๋๋ ๊ทธ๋ํฝ์ค ํ์๋ ๋ค๋ฅธ ํ์์ ์คํํ์ฌ ํจ์์ ์คํ์ ๋ฉ์ธ ๋ ๋๋ง ๋ฃจํ์ ๊ฒน์ณ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
ImGui ์ค์
์ด์ ImGui๋ฅผ ์ด๊ธฐํํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ ๋ช๊ฐ์ง ํค๋๋ฅผ vk_engine.cpp
์ ํฌํจํ๊ฒ ์ต๋๋ค.
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_vulkan.h"
์ด๋ ์ฃผ์ imgui ํค๋์, SDL 2 ๋ฐ Vulkan ๋ฐฑ์๋ ๊ตฌํ ํค๋์ ๋๋ค.
์ด์ ์ด๊ธฐํ ํจ์๋ฅผ ์์ฑํด๋ด ์๋ค.
void VulkanEngine::init_imgui()
{
// 1: create descriptor pool for IMGUI
// the size of the pool is very oversize, but it's copied from imgui demo
// itself.
VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } };
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
pool_info.maxSets = 1000;
pool_info.poolSizeCount = (uint32_t)std::size(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
VkDescriptorPool imguiPool;
VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool));
// 2: initialize imgui library
// this initializes the core structures of imgui
ImGui::CreateContext();
// this initializes imgui for SDL
ImGui_ImplSDL2_InitForVulkan(_window);
// this initializes imgui for Vulkan
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = _instance;
init_info.PhysicalDevice = _chosenGPU;
init_info.Device = _device;
init_info.Queue = _graphicsQueue;
init_info.DescriptorPool = imguiPool;
init_info.MinImageCount = 3;
init_info.ImageCount = 3;
init_info.UseDynamicRendering = true;
//dynamic rendering parameters for imgui to use
init_info.PipelineRenderingCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
init_info.PipelineRenderingCreateInfo.colorAttachmentCount = 1;
init_info.PipelineRenderingCreateInfo.pColorAttachmentFormats = &_swapchainImageFormat;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
ImGui_ImplVulkan_Init(&init_info);
ImGui_ImplVulkan_CreateFontsTexture();
// add the destroy the imgui created structures
_mainDeletionQueue.push_function([=]() {
ImGui_ImplVulkan_Shutdown();
vkDestroyDescriptorPool(_device, imguiPool, nullptr);
});
}
์ด ํจ์๋ฅผ init_pipelines();
์ดํ์ VulkanEngine::init()
์ ๋ง์ง๋ง์ ํธ์ถํฉ๋๋ค. ์ด ์ฝ๋๋ ImGui ๋ฐ๋ชจ์์ ๊ฐ์ ธ์จ ์์ ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋์์ต๋๋ค. ๋จผ์ ImGui์์ ์๊ตฌํ๋ ๊ตฌ์กฐ์ฒด, ์๋ฅผ ๋ค์ด ImGui ์ ์ฉ ๋์คํฌ๋ฆฝํฐ ํ ๋ฑ์ ์์ฑํด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์์ ๋์คํฌ๋ฆฝํฐ ํ์ 1000๊ฐ์ ๋ค์ํ ํ์
์ ๋์คํฌ๋ฆฝํฐ๋ฅผ ๋ด๋๋ฐ, ์ด๋ ์ฝ๊ฐ ๊ณผํ์ง๋ง, ๊ณต๊ฐ ํ์ฉ ๋ฉด์์ ์ฝ๊ฐ ๋นํจ์จ์ ์ผ ๋ฟ ๋ฌธ์ ๋ ๋ฐ์ํ์ง ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ CreateContext()
, Imgui_ImplSDL2_InitForVulkan
๊ณผ ImGUI_ImplVulkan_Init
์ ํธ์ถํฉ๋๋ค. ์ด ํจ์๋ค์ ์ฐ๋ฆฌ๊ฐ ํ์ํ ImGui์ ์ฌ๋ฌ ๊ตฌ์ฑ์์๋ฅผ ์ด๊ธฐํํ ๊ฒ์
๋๋ค. Vulkan์์๋ ๋๋ฐ์ด์ค, ์ธ์คํด์ค, ํ์ ๊ฐ์ ๊ฒ๋ค์ ์ฐ๊ฒฐํด์ผ ํฉ๋๋ค.
ํ ๊ฐ์ง ์ค์ํ ์ ์ UseDynamicRendering
์ true
๋ก ์ค์ ํ๊ณ , ColorAttachmentFormat
์ ์ค์์ฒด์ธ ํฌ๋งท์ผ๋ก ์ค์ ํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ์๋ํ๋ฉด Vulkan ๋ ๋ ํจ์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋์ ๋ ๋๋ง์ ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ปดํจํธ ์
ฐ์ด๋์๋ ๋ฌ๋ฆฌ dear imgui๋ ์ค์์ฒด์ธ์ ์ง์ ๋ ๋๋ง๋ ๊ฒ์
๋๋ค.
ImGui_ImplVulkan_Init
์ ํธ์ถํ ํ, ํฐํธ ํ
์ค์ณ๋ฅผ ์
๋ก๋ ํ๊ธฐ ์ํด immediate submit์ ํด์ผํฉ๋๋ค. ์ด ์์
์ด ์คํ ๋๋ฉด DestroyFontUploadObjects๋ฅผ ํธ์ถํ์ฌ ImGui๊ฐ ์์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ๋ฆฌํ๋๋ก ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ ๋ฆฌํ๋ ์ฝ๋๋ฅผ ์ญ์ ํ์ ์ถ๊ฐํฉ๋๋ค.
Imgui ๋ ๋๋ง ๋ฃจํ
Imgui๊ฐ ์ด๊ธฐํ๋์์ง๋ง ์ด๋ฅผ ๋ ๋๋ง ๋ฃจํ์ ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํฉ๋๋ค.
๋จผ์ ImGui ์ฝ๋๋ฅผ run()
ํจ์์ ์ถ๊ฐํฉ๋๋ค.
//Handle events on queue
while (SDL_PollEvent(&e) != 0) {
//close the window when user alt-f4s or clicks the X button
if (e.type == SDL_QUIT) bQuit = true;
if (e.type == SDL_WINDOWEVENT) {
if (e.window.event == SDL_WINDOWEVENT_MINIMIZED) {
stop_rendering = true;
}
if (e.window.event == SDL_WINDOWEVENT_RESTORED) {
stop_rendering = false;
}
}
//send SDL event to imgui for handling
ImGui_ImplSDL2_ProcessEvent(&e);
}
//do not draw if we are minimized
if (stop_rendering) {
//throttle the speed to avoid the endless spinning
std::this_thread::sleep_for(std::chrono::milliseconds(100));
continue;
}
// imgui new frame
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
//some imgui UI to test
ImGui::ShowDemoWindow();
//make imgui calculate internal draw structures
ImGui::Render();
//our draw function
draw();
pollEvent
๋ฃจํ์์ ๋ฐ์ํ SDL ์ด๋ฒคํธ๋ฅผ ImGui๋ก ์ ๋ฌํ์ฌ ์ฒ๋ฆฌํ๊ฒ ํด์ผ ํฉ๋๋ค. ๊ทธ ๋ค์, ImGui์ ์๋ก์ด ํ๋ ์์ ์์ํ๊ธฐ ์ํด ์ธ ๊ฐ์ง ํจ์๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค. ์ด ์์
์ด ์ํ๋๋ฉด UI ๋ช
๋ น์ ์คํํ ์ ์์ต๋๋ค. ์ง๊ธ์ ๋ฐ๋ชจ ์ฐฝ๋ง์ ํ์ํด๋ณด๊ฒ ์ต๋๋ค. ImGui::Render()
๋ฅผ ํธ์ถํ ๋, ImGui๊ฐ ํ๋ ์์ ๊ทธ๋ฆฌ๊ธฐ์ ํ์ํ ์ ์ /๋๋ก์ฐ์ฝ ๋ฑ์ ๊ณ์ฐํ์ง๋ง, ์ค์ ๋ก ํ๋ฉด์ ๊ทธ๋ฆฌ์ง๋ ์์ต๋๋ค. ์ค์ ๋ ๋๋ง์ draw()
ํจ์ ๋ด๋ถ์์ ๊ณ์ํ๊ฒ ์ต๋๋ค.
๋์ ๋ ๋๋ง
ImGui๋ ๋ฉ์์ ์
ฐ์ด๋๋ฅผ ํฌํจํ๋ ์ค์ GPU ๋๋ก์ฐ์ฝ์ ์ฌ์ฉํด ๊ทธ๋ฆฝ๋๋ค. ํ์ฌ ์ฐ๋ฆฌ๊ฐ ์งํ์ค์ธ ์ปดํจํธ ์
ฐ์ด๋ ๋ฐฉ์์ ๋๋ก์ฐ๋ ์๋๋๋ค. ๋ํ์ ๋ ๋๋งํ๊ธฐ ์ํด ๋ ๋ ํจ์ค๋ฅผ ์ค์ ํด์ผ ํ์ง๋ง, Vulkan 1.3๊ธฐ๋ฅ์ธ ๋์ ๋ ๋๋ง์ ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ ๋ ํจ์ค๋ฅผ ์ฌ์ฉํ์ง ์์ ๊ฒ์
๋๋ค. VkRenderPass
๊ฐ์ฒด๋ฅผ ์ ๋ฌํด VkCmdBeginRenderPass
๋ฅผ ํธ์ถํ๋ ๊ฒ ๋์ ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋ฆด ๋ ํ์ํ ์ ๋ณด๋ฅผ ๋ด๋ VkRenderingInfo
์ ํจ๊ป VkBeginRendering
์ ํธ์ถํ ๊ฒ์
๋๋ค.
VkRenderingInfo
๋ ์ฐ๋ฆฌ์ ๊ทธ๋ฆด ์ด๋ฏธ์ง์ธ ์ฌ๋ฌ VkRenderingAttachmentInfo
๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ์ด๋ฅผ intializers
์ ์์ฑํด๋ด
์๋ค.
VkRenderingAttachmentInfo vkinit::attachment_info(
VkImageView view, VkClearValue* clear ,VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/)
{
VkRenderingAttachmentInfo colorAttachment {};
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorAttachment.pNext = nullptr;
colorAttachment.imageView = view;
colorAttachment.imageLayout = layout;
colorAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (clear) {
colorAttachment.clearValue = *clear;
}
return colorAttachment;
}
attachment info๋ฅผ ์ํด ์ ํ์ ์ธ ํฌ์ธํฐ๋ก clear value๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ด๊ธฐํํ๊ฑฐ๋, ํน์ ์๋ตํ๊ณ ๊ธฐ์กด ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.
์ด๋ฏธ์ง ๋ทฐ์ ๋ ์ด์์์ ํ์์ฒ๋ผ ๋ชจ๋ ๋ ๋๋ง ๋ช
๋ น๊ณผ ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํฉ๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ ๋ถ๋ถ์ loadOP
์ storeOP
์
๋๋ค. ์ด๋ ํด๋น ์ดํ์น๋จผํธ๊ฐ ๋ ๋ํจ์ค(๋์ ๋ ๋๋ง๊ณผ ์ผ๋ฐ ๋ ๋ํจ์ค ๋ชจ๋)์์ ์ฌ์ฉ๋ ๋ ๋ ๋ ํ๊ฒ์ ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง๋ฅผ ์ ์ดํฉ๋๋ค. load ์ ํ์ง์์๋ LOAD๋ฅผ ์ค์ ํ์ต๋๋ค. ์ด๋ ๊ธฐ์กด ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ์ ์งํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. Clear๋ ์์ ์ ์ค์ ๋ clear value๋ก ์ด๊ธฐํํ๋ฉฐ, ๋ชจ๋ ํฝ์
์ ๊ต์ฒดํ ๋์๋ dont-care๋ก ์ค์ ํด GPU๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ ์ฝ์ง ์๊ฒ ํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
์ฐ๋ฆฌ์ store op๋ ๊ทธ๋ฆฌ๊ธฐ ๋ช ๋ น์ ์ ์ฅํ๊ธฐ ์ํด store๋ก ํ๋์ฝ๋ฉํ ๊ฒ์ ๋๋ค.
attachment info๊ฐ ์์ฑ๋์์ผ๋ฏ๋ก VkRenderingInfo
๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ImGui๋ฅผ ๋ ๋๋งํ๋ ๋ ๋ํจ์ค๋ฅผ ์คํํ๊ธฐ ์ํด ์๋ก์ด ํจ์ draw_imgui()
๋ฅผ VulkanEngine
ํด๋์ค์ ์ถ๊ฐํฉ๋๋ค.
void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView)
{
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr);
vkCmdBeginRendering(cmd, &renderInfo);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
vkCmdEndRendering(cmd);
}
๊ทธ๋ฆด ์ฌ๊ฐํ์ ์์ญ์ ์ค์ ํ๊ธฐ ์ํด render extent๋ฅผ ๋ฐ์์ผ ํ๋ฉฐ, ์์ ์ดํ์น๋จผํธ์ ๊น์ด ์ดํ์น๋จผํธ๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ๊น์ด ์ดํ์น๋จผํธ๋ ๋น์ฅ์ ํ์ ์์ง๋ง ์ดํ์ ๋ค๋ฃฐ ๊ฒ์ ๋๋ค.
์ดํ์๋ draw()
ํจ์์์ ํธ์ถํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
// execute a copy from the draw image into the swapchain
vkutil::copy_image_to_image(cmd, _drawImage.image, _swapchainImages[swapchainImageIndex], _drawExtent, _swapchainExtent);
// set swapchain image layout to Attachment Optimal so we can draw it
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
//draw imgui into the swapchain image
draw_imgui(cmd, _swapchainImageViews[swapchainImageIndex]);
// set swapchain image layout to Present so we can draw it
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
//finalize the command buffer (we can no longer add commands, but it can now be executed)
VK_CHECK(vkEndCommandBuffer(cmd));
copy_image
๋ช
๋ น์ ์ด์ ๊ณผ ๊ฐ์ต๋๋ค. ์ดํ์ ๋ช
๋ น๋ค์ VkEndCommandBuffer
ํธ์ถ๊น์ง์ ๊ตฌ๊ฐ์ผ๋ก ๋์ฒดํฉ๋๋ค.
์ด์ ์๋ ์ค์์ฒด์ธ์ ์ด๋ฏธ์ง๋ฅผ ์ ์ก ๋ ์ด์์์์ ํ์ ๋ ์ด์์์ผ๋ก ์ ํํ์ง๋ง, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
๋ก ๋์ ๋ฐ๊ฟ ๊ฒ์
๋๋ค. ์ด๋ ์ฌ๊ธฐ์ฒ๋ผ ๋ ๋๋ง ๋ช
๋ น์ ํธ์ถํ ๋ ์ฌ์ฉํ๋ ๋ ์ด์์์
๋๋ค.
๊ทธ ๋ค์, VkRenderingInfo
๋ฅผ ๊ตฌ์ฑํ๊ณ ๋จ์ผ ์์ ์ดํ์น๋จผํธ๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ด ์์ ์ดํ์น๋จผํธ๋ ์ฐ๋ฆฌ๊ฐ ํ๊ฒํ
ํ ์ค์์ฒด์ธ ์ด๋ฏธ์ง๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
์ด์ VkRenderInfo
๋ฅผ ์ค๋นํ์ผ๋ฏ๋ก vkCmdBeginRendering
์ ํธ์ถํ ์ ์์ต๋๋ค. ์ด๋ ๋ ๋ ํจ์ค๋ฅผ ์์ํ๋ฉฐ ์ด์ ๊ทธ๋ฆฌ๊ธฐ ๋ช
๋ น์ ์คํํ ์ ์์ต๋๋ค. ImGui Vulkan ๋ฐฑ์๋์์ ์ฐ๋ฆฌ์ ์ปค๋งจ๋ ๋ฒํผ๋ฅผ ์ ๋ฌํ๋ฉด, ImGui๊ฐ ์์ ์ ๊ทธ๋ฆฌ๊ธฐ ๋ช
๋ น์ ํด๋น ๋ฒํผ์ ๊ธฐ๋กํฉ๋๋ค. ์ด๊ฒ์ด ์๋ฃ๋๋ฉด vkCmdEndRendering
์ ํธ์ถํด ๋ ๋ ํจ์ค๋ฅผ ๋๋ผ ์ ์์ต๋๋ค.
์ดํ, ์ค์์ฒด์ธ ์ด๋ฏธ์ง๋ฅผ ์ดํ์น๋จผํธ ์ต์ ์์ ํ์ ๋ชจ๋๋ก ์ ํํ๊ณ ์ปค๋งจ๋ ๋ฒํผ๋ฅผ๋๋ ๋๋ค.
์ด ์์ ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํด๋ณธ๋ค๋ฉด ImGui ๋ฐ๋ชจ์ฐฝ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ ๋๋ฒ๊น UI๋ฅผ ์ ฐ์ด๋์ ์ฐ๊ฒฐํด๋ณด๊ฒ ์ต๋๋ค.
Next: Push Constants and new shaders