[vk] Drawing triangle - graphics pipeline basics - Conclusion

2021. 8. 9. 05:13그래픽스/vk

1. Conclusion

- 이전 챕터들에서 생성한 모든 구조체와 객체를 이제 결합하여 pipline 을 생성할 수 있게되었다.

- 아래는 이때까지 생성한 객체의 타입을 요약해서 보여주는것.

  • Shader stages: the shader modules that define the functionality of the programmable stages of the graphics pipeline
  • Fixed-function state: all of the structures that define the fixed-function stages of the pipeline, like input assembly, rasterizer, viewport and color blending
  • Pipeline layout: the uniform and push values referenced by the shader that can be updated at draw time
  • Render pass: the attachments referenced by the pipeline stages and their usage

- 이들을 모두 결합하여 graphics pipeline의 기능을 완전히 정의할 수 있음.

- 그래서 이제 VkGraphicsPipelineCreateInfo 구조체를 채워넣을 데이터가 전부 모인것

- createGraphicsPipeline 함수 뒷부분에 이 구조체를 생성할 것임.

    (vkDestroyShaderModule 호출전, 파이프라인을 생성할때 shadermodule은 여전히 필요하므로)

 

 

 

2 CreateInfo

2.1 shaderStage

VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};

VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;

- VkPipelineShaderStageCreateInfo 구조체를 참조하는것부터 시작 (pStages)

 

 

 

2.2 Fixed-function state

pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = nullptr; // Optional
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = nullptr; // Optional

- 그 다음 fixed-function stage를 기술해야함.

 

 

2.3 Pipeline layout

pipelineInfo.layout = pipelineLayout;

- 그리고 Vulkan의 핸들(class member)인 pipelineLayout을 참조.

 

 

 

2.4 Render Pass

pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;

- 그리고 마지막으로 핸들인 render pass와

- graphics pipeline에서 사용될 subpass의 인덱스 

- 또 다른 render passes 를 이 pipeline에서 사용할 수 있지만.

- renderPass 와 호환 가능해야함. -> here,에 설명되어있음. (하지만 튜토리얼에선 이 feature를 사용하지 않음)

Two render passes are compatible if their corresponding color, input, resolve, and depth/stencil attachment references are compatible and if they are otherwise identical except for:
  • Initial and final image layout in attachment descriptions
  • Load and store operations in attachment descriptions
  • Image layout in attachment references

    As an additional special case, if two render passes have a single subpass, the resolve attachment reference compatibility requirements are ignored.

 

 

 

 

2.5 Base-pipeline

pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional

- 사실 pipelineinfo에는 두가지 파라미터가 더있음

- Vulkan은 기존의 pipeline에서 파생해서 새로운 graphics pipeline을 만들 수 있음.

- basePipelineHandle :  기존의 파이프라인의 핸들을 지정

- basePipelineIndex: 인덱스로 만들려는 다른 파이프라인을 참조할 수 있음.

- 지금은 single pipeline이므로, 간단하게 null handle 그리고 invalid index 로 명시하면됨

- 이러한 값들은 오직 VK_PIPELINE_CREATE_DERIVATIVE_BIT  플래그가 flags 필드에 지정된 경우에만 사용

  (VkGraphicsPipelineCreateInfo 의 flags)

pipeline derivatives(그래픽 파이프라인 파생물) 에 대한 아이디어
- 파이프라인을 설정하는 데 드는 비용이 저렴하고 
- 기존 파이프 라인과 공통된 기능을많이 갖추고
- 동일한 부모의 파이프라인 간 전환도 더 빨리 수행 될 수 있다는것.

 

 

3. VkPipeline 

VkPipeline graphicsPipeline;

- 이제 VkPipeline 객체를 class member로 생성하자.

if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
    throw std::runtime_error("failed to create graphics pipeline!");
}

- 마침내 vkCreateGraphicsPipelines 함수를 사용하여 파이프라인을 생성하였다.

- 다른 객체의 create 함수들 보다 파라미터 수가 더 많은것을 볼 수 있다.

- 이것은 여러개의 VkGraphicsPipelineCreateInfo구조체들을 가져와서

- 한번에 여러개의 VkPipeline를 한번에 생성하도록 설계되었기 때문이다.

 

- 파라미터 2 : 선택적  VkPipelineCache 객체를 참조할 수 있음

- A pipeline cache : vkCreateGraphicsPipelines 에 대한 여러 호출에서 파이프 라인 생성과 관련된 데이터를 저장하고

- - - - 재사용하는데 사용할 수 있음, 캐시가 파일에 저장되는 경우, 프로그램 실행 전체에서 사용할 수 있음

- - - - 나중에 파이프 라인 생성 속도 또한 크게 높일 수 있음

- - - - pipeline cache 챕터에서 다룰 예정임.

 

 

3.1 Destroy

void cleanup() {
    vkDestroyPipeline(device, graphicsPipeline, nullptr);
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
    ...
}

- graphics pipeline 은 모든 drawing operations에 필요하기 때문에 program 마지막에 destroy해야한다.

- 다음 장에선 swapchain images로 부터 framebuffers을 설정하고 drawing commands을 준비할것임. 

 

C++ code / Vertex shader / Fragment shader

 

https://vulkan-tutorial.com/en/Drawing_a_triangle/Graphics_pipeline_basics/Conclusion