Link

Criação do pipeline gráfico

Agora que temos todos os recursos necessários para criar o pipeline gráfico, podemos começar a preencher a estrutura VkGraphicsPipelineCreateInfo no final da função initPipeline(), mas antes das chamadas para vkDestroyShaderModule porque os módulos de shader ainda devem ser usados durante a criação.

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

Começamos referenciando o array de estruturas VkPipelineShaderStageCreateInfo.

pipelineInfo.pDynamicState = &dynamicInfo;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssemblyInfo;
pipelineInfo.pRasterizationState = &rasterizationInfo;
pipelineInfo.pColorBlendState = &colorBlending;

Em seguida, referenciamos todas as estruturas que descrevem o estágio de função fixa.

pipelineInfo.layout = m_pipelineLayout;

Depois disso, vem o layout do pipeline, que é um identificador do Vulkan em vez de um ponteiro para uma estrutura.

pipelineInfo.renderPass = m_window->defaultRenderPass();
pipelineInfo.subpass = 0;

Por último, temos a referência para o render pass (que já foi criado automaticamente pela classe QVulkanWindow) o e o índice do subpass onde este pipeline gráfico será usado8. O render pass criado pela classe QVulkanWindow possuí apenas um subpass, portando, definimos o valor do campo subpass como 0.

8 Também podemos usar o mesmo pipeline com outros render passes se eles forem compatíveis com o especificado, mas não usaremos esse recurso neste projeto.

Agora nos preparemos para a etapa final criando um membro de classe para manter o objeto VkPipeline:

VkPipeline m_graphicsPipeline = nullptr;

E finalmente criamos o pipeline gráfico chamando a função vkCreateGraphicsPipelines:

result = m_deviceFunctions->vkCreateGraphicsPipelines(
		device,
		VK_NULL_HANDLE,
		1,
		&pipelineInfo,
		nullptr,
		&m_graphicsPipeline
	);

if (result != VK_SUCCESS)
	qFatal("Failed to graphics pipeline: %d", result);

Essa função na verdade tem mais parâmetros que as funções comuns de criação de objetos no Vulkan. Ela é projetada para receber vários objetos VkGraphicsPipelineCreateInfo e criar vários objetos VkPipeline em uma única chamada. O segundo parâmetro, para o qual passamos o argumento VK_NULL_HANDLE, faz referência a um objeto VkPipelineCache opcional.

O pipeline gráfico é necessário para todas as operações comuns de desenho, portanto, ele também deve ser destruído apenas no final do programa:

void Renderer::releaseResources()
{
    VkDevice device = m_window->device();

    m_deviceFunctions->vkDestroyPipeline(device, m_graphicsPipeline, nullptr);
    m_deviceFunctions->vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
}

Agora, podemos executar nosso programa para confirmar que todo esse trabalho resultou em uma criação de pipeline bem-sucedida. Já estamos chegando perto de ver algo aparecer na tela. Na próxima seção, vamos iniciar o render pass.


Anterior Próximo