目录
- 先叨叨
- Git信息
- 关键代码
- TestPipeline::Initialize()
- 编译运行
先叨叨
到上篇为止已经创建了FrameBuffer和RenderPass。建立Pipeline的先决条件已经具备。本篇就来创建Pipeline。
Git信息
- repository: https://gitee.com/J8_series/easy-car-ui
- tag: 10-CreatePipeline
- url: https://gitee.com/J8_series/easy-car-ui/tree/10-CreatePipeline
关键代码
TestPipeline::Initialize()
本方法很长,对照【Vulkan入门】06-Pipeline介绍看会清晰一点。
- 通过shaderStages为Pipeline指定Shader程序
- VIEWPORT决定了Vulkan渲染图片的大小,SCISSOR决定了Vulkan渲染后对图片的裁剪。我们希望这两个值随窗口大小改变而改变,因此我们用dynamicStates告诉Vulkan这两个值在渲染时动态指定。
- 通过vertexInputInfo给Pipeline提供顶点信息,但目前我们还不需要任何顶点信息。
- 通过inputAssembly告诉Pipeline我们的顶点是想画什么,例子中我们需要Pipeline画三角形
- 通过rasterizer告诉Pipeline如何光栅化
- 通过multisampling告诉Pipeline如何采样
- 通过colorBlending告诉Pipeline如何叠加同一个像素的多个颜色
- 通过pipelineLayoutInfo告诉Pipeline全局变量,目前我们不需要任何全局变量
void TestPipeline::Initialize(
const std::string& vertexShaderFile,
const std::string& fragmentShaderFile,
const VkDevice& device,
uint32_t width,
uint32_t height,
uint32_t memroyTypeIndex)
{
m_vertexShaderFile = vertexShaderFile;
m_fragmentShaderFile = fragmentShaderFile;
m_device = device;
m_width = width;
m_height = height;
m_memroyTypeIndex = memroyTypeIndex;
CreateRenderPass();
CreateFramebuffers();
std::vector<char> vertShaderCode = ReadShader(m_vertexShaderFile);
std::vector<char> fragShaderCode = ReadShader(m_fragmentShaderFile);
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineShaderStageCreateInfo
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineDynamicStateCreateInfo
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineVertexInputStateCreateInfo
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineInputAssemblyStateCreateInfo
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineViewportStateCreateInfo
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineRasterizationStateCreateInfo
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineMultisampleStateCreateInfo
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineColorBlendAttachmentState
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineColorBlendStateCreateInfo
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
//https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkPipelineLayoutCreateInfo
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pushConstantRangeCount = 0;
if (vkCreatePipelineLayout(m_device, &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS)
{
throw std::runtime_error("To create pipeline layout is failed");
}
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.renderPass = m_renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if (vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicsPipeline) != VK_SUCCESS) {
throw std::runtime_error("To create graphics pipeline is failed!");
}
vkDestroyShaderModule(m_device, fragShaderModule, nullptr);
vkDestroyShaderModule(m_device, vertShaderModule, nullptr);
}
编译运行
没有出现错误就是最好的现象