[vk] Drawing triangle - Drawing - Framebuffers

2021. 8. 11. 15:01그래픽스/vk

1. Framebuffers

- swapchain image와 같은 포맷을 가지는 단일 framebuffer를 생각하며 render pass를 설정하였다.

- 하지만 실제로만들지는 않음.

 

- render pass 생성 동안에 명시된 attachments은 VkFramebuffer object로 래핑하여 바인딩됨.

- framebuffer object는 attachments로 표현된 모든 VkImageView 객체를 참조한다.

- 우리의 경우, 오직 하나의 color attachment만 가지고 있음.

- 하지만, attachment를 위해 사용하는 image는 swapchain이 표시할 이미지를 검색할 때  swapchain이 반환하는 image에 따라 다름

- 이것은 swapchain에있는 모든 images에 대해 framebuffer를 만들어야한다는것을 의미한다.

- 그리고, drawing time 때 하나의 image에 해당하는 framebuffer를 사용해야한다.

The attachments specified during render pass creation are bound by wrapping them into a VkFramebuffer object.

A framebuffer object references all of the 
VkImageView objects that represent the attachments.

In our case that will be only a single one: the color attachment.

However, the image that we have to use for the attachment depends on which image the swap chain returns when we retrieve one for presentation.

That means that we have to create a framebuffer for all of the images in the swap chain and use the one that corresponds to the retrieved image at drawing time.

- 이를 위해 framebuffers을 보유할 std::vector class member를 생성해야함.

std::vector<VkFramebuffer> swapChainFramebuffers;

- 그래픽 파이프라인을 생성한 직후 이 objects 배열을 초기화할 함수 createFramebuffers 를 만들어 보자

void initVulkan() {
    createInstance();
    setupDebugMessenger();
    createSurface();
    pickPhysicalDevice();
    createLogicalDevice();
    createSwapChain();
    createImageViews();
    createRenderPass();
    createGraphicsPipeline();
    createFramebuffers();
}

...

void createFramebuffers() {

}

 

2. createFramebuffers

 

- 일단 모든 framebuffer를 담을 수 있게 resize 해준다.

void createFramebuffers() {
    swapChainFramebuffers.resize(swapChainImageViews.size());
}

- 그다음에 반복문을 통해 image views마다 framebuffer를 생성함.

for (size_t i = 0; i < swapChainImageViews.size(); i++) {
    VkImageView attachments[] = {
        swapChainImageViews[i]
    };

    VkFramebufferCreateInfo framebufferInfo{};
    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.renderPass = renderPass;
    framebufferInfo.attachmentCount = 1;
    framebufferInfo.pAttachments = attachments;
    framebufferInfo.width = swapChainExtent.width;
    framebufferInfo.height = swapChainExtent.height;
    framebufferInfo.layers = 1;

    if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
        throw std::runtime_error("failed to create framebuffer!");
    }
}

- 먼저 framebuffer와 호환이 되는 renderPass  를 명시

- framebuffer는 호환 가능한 render pass만 사용할 수 있음

-  여기서의 호환은 대략 attachments의 수가 같고, attachments의 타입이 같아야함을 의미함.

 

attachmentCount , pAttachments

- render pass의 pAttachment 배열 각각의 attachment descriptions에 바인딩 되어야하는 

- VkImageView object 배열 을 명시

 

width height

- 자명함. swapchainExtent와 같게.

 

layers

- image arrays안에 있는 layers의 개수 (VkswapchainCreateInfoKHR::imageArrayLayers)

- 튜토리얼에서는 swapchain images은 single images 이므로

- 레이어수는 1

 

 

3. DestroyFramebuffer

- image view와 render pass를 기반으로 생성하였으니 먼저 삭제해줘야함

void cleanup() {
    for (auto framebuffer : swapChainFramebuffers) {
        vkDestroyFramebuffer(device, framebuffer, nullptr);
    }

    ...
}

 

다음장에선 실제 drawing commands을 다룸.

 

C++ code / Vertex shader / Fragment shader