본문 바로가기

Vulkan

Graphics Pipeline basics - Render passes

이전 글 - Graphics pipeline basics - Fixed function

다음 글 - Graphics pipeline basics - Conclusion



Render passes

렌더링 패스


Setup


파이프 라인 생성을 완료하기 전에 Vulkan에 렌더링하는 동안 사용될 프레임 버퍼를 알려 줘야 합니다. 얼마나 많은 색상 및 깊이 버퍼가 있는지, 각각에 대해 사용할 샘플 수 및 렌더링 작업 전체에서 내용을 처리하는 방법을 지정해야 합니다. 이 모든 정보는 렌더 패스 객체에 래핑됩니다.이 객체에 대해서는 새 createRenderPass 함수를 만듭니다. createVraphicsPipeline 전에 initVulkan에서 이 함수를 호출하십시오.


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

...

void createRenderPass() {

}



Attachment description


이번 경우에는 스왑 체인의 이미지 중 하나가 나타내는 단일 컬러 버퍼 만 있습니다.


void createRenderPass() {
   VkAttachmentDescription colorAttachment = {};
   colorAttachment.format = swapChainImageFormat;
   colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
}



format 은  스왑 체인 이미지의 형식과 일치해야 하며 멀티 샘플링에서는 아무 것도하지 않으므로 1 을 유지할 것 입니다.


colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;


loadOp 및 storeOp는 렌더링 전과 렌더링 후에 첨부된 데이터로 수행 할 작업을 결정합니다. loadOp에는 다음과 같은 선택 항목이 있습니다.


  • VK_ATTACHMENT_LOAD_OP_LOAD : 첨부된 기존 내용을 보존합니다.

  • VK_ATTACHMENT_LOAD_OP_CLEAR : 시작시 값을 상수로 지 웁니다.

  • VK_ATTACHMENT_LOAD_OP_DONT_CARE : 기존 내용이 정의되지 않았습니다. 즉 뭐가 됬든 관심이 없다는 것 입니다.


이번 경우에는 새로운 프레임을 그리기 전에 클리어 연산을 사용하여 프레임 버퍼를 검정색으로 지웁니다. storeOp에는 두 가지 가능성이 있습니다.


  • VK_ATTACHMENT_STORE_OP_STORE : 렌더링 된 내용이 메모리에 보관되고 나중에 읽을 수 있습니다.

  • VK_ATTACHMENT_STORE_OP_DONT_CARE : 렌더링 작업 후에 프레임 버퍼의 내용이 정의되지 않습니다.


우리는 렌더링 된 삼각형을 화면에 표시하는 것에 관심이 있습니다. 그래서 여기에 보관 작업을 진행할 것입니다.


colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;


loadOp 및 storeOp는 색상 및 심도 데이터에 적용되고 stencilLoadOp / stencilStoreOp는 스텐실 데이터에 적용됩니다. 우리의 응용 프로그램은 스텐실 버퍼를 사용하지 않으므로 로드 및 보관 결과는 관련이 없습니다.



colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;


Vulkan의 텍스처 및 프레임 버퍼는 특정 픽셀 형식의 VkImage 객체로 표시되지만 이미지에서 수행하려고 하는 작업에 따라 메모리의 픽셀 레이아웃이 변경 될 수 있습니다.


가장 일반적인 레이아웃은 다음과 같습니다.


  • VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : 컬러 첨부로 사용 된 이미지

  • VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : 스왑 체인에 표시 할 이미지

  • VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : 메모리 복사 작업의 대상으로 사용할 이미지


이 주제에 관해서는 텍스처링 장에서 좀 더 자세하게 다룰 것 입니다. 그러나 지금 알아 두어야 할 중요한 점은 이미지를 다음 작업에 적합한 특정 레이아웃으로 전환해야 한다는 것입니다.


initialLayout은 렌더 패스가 시작되기 전에 이미지가 가질 레이아웃을 지정합니다. finalLayout는 렌더 패스가 완료 될 때 자동으로 전환 할 레이아웃을 지정합니다. initialLayout에 VK_IMAGE_LAYOUT_UNDEFINED를 사용한다는 것은 이미지의 이전 레이아웃이 마음에 들지 않는다는 것을 의미합니다.이 특별한 값의 주의 사항은 이미지의 내용을 보존 할 수는 없지만 계속 진행 되므로 중요하지 않습니다만 어쨌든 그것을 클리어 합니다. 렌더링 후에 스왑 체인을 사용하여 이미지를 표시 할 준비가 되기를 바랍니다. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR을 finalLayout으로 사용하는 이유입니다.


Subpasses and attachment references

하위 패스 및 첨부 레퍼런스


단일 렌더링 패스는 여러 개의 하위 패스로 구성 될 수 있습니다. 서브 패스는 이전 패스에서 프레임 버퍼의 내용에 의존하는 후속 렌더링 작업 입니다 (예 : 후속 처리되는 일련의 후 처리 효과). 이러한 렌더링 작업을 하나의 렌더링 패스로 그룹화하면 Vulkan은 작업을 재정렬하고 더 나은 성능을 위해 메모리 대역폭을 절약 할 수 있습니다. 그러나 첫 번째 삼각형의 경우 단일 하위 패스 만 사용 해야 합니다.


모든 하위 패스는 이전 섹션의 구조를 사용하여 설명한 하나 이상의 첨부을 참조합니다. 이러한 참조 자체는 다음과 같은 VkAttachmentReference 구조체입니다.


VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;


attachment 매개 변수는 첨부 설명 배열의 해당 인덱스로 참조 할 첨부 파일을 지정합니다. 우리의 배열은 하나의 VkAttachmentDescription 으로 구성되어 있으므로 색인은 0입니다. 레이아웃은 이 참조를 사용하는 하위 패스 중에 첨부 에 포함시킬 레이아웃을 지정합니다. Subpass가 시작되면 Vulkan은 자동으로 첨부 들을 이 레이아웃으로 전환합니다. 첨부를 사용하여 색상 버퍼로 사용하고 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 레이아웃은 이름에서 알 수 있듯이 최상의 성능을 제공합니다.


서브 패스는 VkSubpassDescription 구조체를 사용하여 기술 됩니다.

VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;


또한 Vulkan은 미래에 계산 서브 패스를 지원할 수 있으므로 그래픽 서브 패스라는 점에 대해 명시 해야합니다. 다음으로 색상 첨부에 대한 참조를 지정합니다.


subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;


이 배열에 있는 첨부의 인덱스는 vec4 outColor 지시문에서 레이아웃 (위치 = 0)을 사용하여 프래그먼트 셰이더에서 직접 참조됩니다!


다음과 같은 다른 유형의 첨부를 서브 패스에서 참조 할 수 있습니다.


  • pInputAttachments : 셰이더에서 읽은 첨부

  • pResolveAttachments : 멀티 샘플링 컬러 첨부 에 사용되는 첨부

  • pDepthStencilAttachment : 깊이 및 스텐실 데이터 첨부

  • pPreserveAttachments :이 하위 패스에서 사용하지 않지만 데이터를 보존해야하는 첨부





Render pass

렌더패스


이제 첨부 들과 이를 참조하는 기본 서브 패스에 대해 설명 했으므로 렌더 패스 자체를 만들 수 있습니다. pipelineLayout 변수 바로 위에있는 VkRenderPass 객체를 유지할 새 클래스 멤버 변수를 만듭니다.


VkRenderPass renderPass;
VkPipelineLayout pipelineLayout;


그런 다음 VkRenderPassCreateInfo 구조체에 첨부 파일과 하위 패스의 배열을 채워 렌더 패스 객체를 만들 수 있습니다. VkAttachmentReference 개체는이 배열의 인덱스를 사용하여 첨부를 참조합니다.



VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;

if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
   throw std::runtime_error("failed to create render pass!");
}


파이프 라인 레이아웃과 마찬가지로 렌더 패스는 프로그램 전체에서 참조되므로 끝에서만 정리하면 됩니다.


void cleanup() {
   vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
   vkDestroyRenderPass(device, renderPass, nullptr);
   ...
}



그동안  많은 작업을 했지만, 다음 장에서는 모두 함께 모여 그래픽 파이프 라인 객체를 만들것 입니다.


C++ code / Vertex shader / Fragment shader


이전 글 - Graphics pipeline basics - Fixed function

다음 글 - Graphics pipeline basics - Conclusion




'Vulkan' 카테고리의 다른 글

Drawing - Framebuffers  (1) 2018.01.24
Graphics pipeline basics- Conclusion  (0) 2018.01.24
Graphics Pipeline basics - Fixed function  (0) 2018.01.24
Graphics Pipeline basics - Shader modules  (0) 2018.01.24
Graphics Pipeline basics - introduction  (0) 2018.01.23