2021. 8. 9. 05:12ㆍ그래픽스/vk
Render passes
1. Setup
- 파이프라인을 생성하기전에 Vulkan에게 렌더링 동안 사용될 framebuffer를 알려줘야함
(need to tell Vulkan about the framebuffer attachments)
- 얼마나 많은 색상 과 깊이 버퍼가 있는지,
- 각각에 대해 사용할 샘플 수 및 렌더링 작업 전체에서 내용을 처리하는 방법을 지정해야함.
- 이러한 모든정보들은 render pass object에 래핑됨
- createRenderPass 함수를 새로 만들어 initVulkan에 createGraphicsPipeline전에 호출할것임
void initVulkan() {
createInstance();
setupDebugMessenger();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
createRenderPass();
createGraphicsPipeline();
}
...
void createRenderPass() {
}
2. Attachment description
- 지금은 swap chain의 images 중 하나가 나타내는 단일 color buffer 만 설정함.
(따라서 color에 대한 구조체만 만듬)
void createRenderPass() {
VkAttachmentDescription colorAttachment{};
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
}
- format 은 swapchain image의 형식과 일치해야함 (format of image view)
- sample: 멀티 샘플링을 설정하지 않았으므로 1을 할당해준것 (the number of samples of the image.)
- 나머지 op가 붙은 멤버들은 수행할 작업을 결정함.
2.1 loadOp, storeOp
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: Existing contents are undefined; 무엇이든 상관없음
- 튜토리얼에선 새로운 프레임을 그리기 전에 clear 연산을 사용하여 framebuffer를 지울것임
- VK_ATTACHMENT_STORE_OP_STORE: 렌더링된 내용이 메모리에 보관되고 나중에 읽을 수 있음.
- VK_ATTACHMENT_STORE_OP_DONT_CARE: 렌더링 작업 후의 framebuffer의 내용이 정의되지않음
- 튜토리얼에선 삼각형을 screen에 띄우는게 목표이므로 store 연산을 STORE로 설정한것
- loadOp 와 storeOp는 색상과 depth data에 적용하는것.
2.2 stencilLoadOp/ stencilStoreOp
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- stencilLoadOp / stencilStoreOp 은 stencil data에 적용하는것
- 현재 stencil buffer를 사용하지 않으므로 무엇이든 상관이 없음.
2.3 layout
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- Vulkan의 Textures 그리고 framebuffers은 특정 pixel format과함께 VkImage 객체로 표현함.
- 하지만 이미지에서 수행하려고 하는 작업에 따라 메모리의 픽셀 레이아웃이 변경될 수 있음.
- 가장 일반적인 레이아웃은 아래와 같음
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : Images used as color attachment
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : Images to be presented in the swap chain
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : Images to be used as destination for a memory copy operation
- 이 토픽은 texturing 챕터에서 깊게 들어갈것임
- 중요한것은, 이미지를 다음 작업에 적합한 특정 레이아웃으로 전환해야한다는것임.
- initialLayout 은 renderpass 가 시작되기전에 이미지가 가질 레이아웃을 지정함.
- finalLayout은 렌더 패스가 완료 될 때 자동으로 전환 할 레이아웃을 지정함.
- initialLayout에 VK_IMAGE_LAYOUT_UNDEFINED 을 사용한다는것은 이전 이미지가 무엇이든 상관없다는것이다.
- undefined 주의사항(caveat) : 이미지 내용물을 보존한다는것을 보장하지못함. (이전의 내용)
- - - - 어쨋든 clear하기 때문에 중요하진 않음
- 렌더링 후 swapchain을 사용함으로써 이미지가 준비되기를 원하기 위해
- - - - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR 를 finalLayout으로 설정한것임.
3. Subpasses and attachment references
- single render pass는 multiple subpasses로 구성될 수 있음.
- subpasses 은 이전 passes의 framebuffers 내용에 의존하는 후속 렌더링 연산임.
(ex. 차례대로 처리되는 후처리효과 시퀀스)
- 이러한 렌더링 작업들을 하나의 render pass로 그룹화하면,
- Vulkan은 작업을 재정렬할 수 있고
- 더 나은 성능을 위해 메모리 대역폭을 절약할 수 있음.
- 그러나 첫번째 삼각형의 경우 단일 하위패스만 사용할것임
3.1 Attachment reference
모든 subpass는 이전 섹션에서 다룬 attachment 구조체를 하나 또는 그이상 참조함.
- 이러한 attachment에 대한 참조는 VkAttachmentReference 구조체에서 다룸
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- attachment : 참조할 VkRenderPassCreateInfo::pAttachments 의 인덱스
- - - - 또는 VK_ATTACHMENT_UNUSED로 사용하지 않음을 명시.
(renderpass의 attachment의 인덱스)
(const VkAttachmentDescription* pAttachments)
- 1개의 VkAttachmentDescription로 구성된 배열이므로 index는 0으로 설정
- layout 은 subpass가 attachment를 참조하는동안 사용할 레이아웃을 지정.
- Vulkan은 subpass가 시작되면, 자동적으로 attachment의 레이아웃을 이 값으로 전환한다.
- 지금은 attachment를 color buffer로 사용할것임.
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 레이아웃은 이름에서 알 수 있듯이 최상의 성능을 제공함.
3.2 SubpassDescription
- subpass는 VkSubpassDescription 구조체를 사용하여 기술함.
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- Vulkan은 미래에 compute subpasses를 지원할 수 있으므로 그래픽 서브패스라는 점에 대해 명시해야함.
- 다음으로, color attachment에 대해 명시해야함.
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
- pColorAttachments 의 배열은 layout(location = 0) out vec4 outColor 지시문을 사용한 fragment shader의 반환값에 직접 참조됨.
| Each element of the pColorAttachments array corresponds to an output location in the shader, i.e. if the shader declares an output variable decorated with a Location value of X, then it uses the attachment provided in pColorAttachments[X]. If the attachment member of any element of pColorAttachments is VK_ATTACHMENT_UNUSED, or if Color Write Enable has been disabled for the corresponding attachment index, then writes to the corresponding location by a fragment shader are discarded.
|
- 다른 타입의 Attachments 또한 subpass에 의해 참조될 수 있음
- pInputAttachments: Attachments that are read from a shader
- pResolveAttachments: Attachments used for multisampling color attachments
- pDepthStencilAttachment: Attachment for depth and stencil data
- pPreserveAttachments: Attachments that are not used by this subpass, but for which the data must be preserved
4. Render pass
- attachment와 이를 참조하는 basic subpass에 대해 기술했으므로
- render pass 그 자체를 만들 수 있다.
- 새로운 class member 변수인 VkRenderPass object를 만들자.
VkRenderPass renderPass;
VkPipelineLayout pipelineLayout;
- render pass object 를 생성하기 위해서는
- VkRenderPassCreateInfo 구조체에 attachment의 배열 그리고 subpass의 배열을 기술해야함.
(VkAttachmentReference 객체는 이 배열들의 인덱스를 사용하여 attachment를 참조하는것.)
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!");
}
- pipeline layout과 같이 render pass 는 program 전체에 걸쳐 참조될것임.
- 따라서 아래와 같이 destroy해줘야함을 잊지말자
void cleanup() {
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyRenderPass(device, renderPass, nullptr);
...
}
- 다음장에서 이제 grphics pipeline object를 만들것임!
void createRenderPass() {
VkAttachmentDescription colorAttachment{};
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
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!");
}
}
전체 코드
C++ code / Vertex shader / Fragment shader
https://vulkan-tutorial.com/en/Drawing_a_triangle/Graphics_pipeline_basics/Render_passes
'그래픽스 > vk' 카테고리의 다른 글
| [vk] Drawing triangle - Drawing - Framebuffers (0) | 2021.08.11 |
|---|---|
| [vk] Drawing triangle - graphics pipeline basics - Conclusion (0) | 2021.08.09 |
| [vk] Drawing triangle - graphics pipeline basics - Fixed functions (0) | 2021.08.09 |
| [vk] Drawing triangle - graphics pipeline basics - Shader modules (0) | 2021.08.09 |
| [vk] Drawing triangle - graphics pipeline basics - introduction (0) | 2021.08.09 |