Link

Iniciando um render pass

Quando um pipeline gráfico é criado, podemos usá-lo para renderizar ligando-o ao buffer de comando antes de gravar um comando de desenho. Pipelines gráficos só podem ser vinculados a buffers de comando dentro de render passes (após o início de um render pass ser gravado).

Para inicializarmos um render pass precisamos de algumas informações específicas, como o framebuffer, o objeto render pass, as dimensões da área de renderização, clear color, valores de estêncil e profundidade e assim por diante. Essas informações são especificadas usando a estrutura de controle VkRenderPassBeginInfo. Essa estrutura é usada posteriormente para definir a execução do render pass.

No começo de startNextFrame adicionamos:

VkRenderPassBeginInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = m_window->defaultRenderPass();
renderPassInfo.framebuffer = m_window->currentFramebuffer();

Os primeiros parâmetros são o próprio render pass e o framebuffer atual. Como discutido anteriormente, QVulkanWindow criou um render pass com um único subpass e um framebuffer para cada imagem do swap chain que foi definida como anexo de cor (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT).

renderPassInfo.renderArea.offset.x = 0;
renderPassInfo.renderArea.offset.y = 0;
const QSize swapChainImageSize = m_window->swapChainImageSize();
renderPassInfo.renderArea.extent.width = swapChainImageSize.width();
renderPassInfo.renderArea.extent.height = swapChainImageSize.height();

Os próximos parâmetros definem a área de todas as imagens que serão afetadas pelas operações que ocorrem nesse render pass. Eles especificam o canto superior esquerdo (através dos parâmetros x e y do membro offset) e largura e altura (através do membro extension) de uma área de renderização. É importante mencionar aqui que os framebuffers criados pela classe QVulkanWindow possuem as mesmas dimensões que as imagens do swap chain.

Quando especificamos uma área de renderização para o render pass, precisamos nos certificar de que as operações de renderização não modifiquem pixels fora dessa área. Esta é apenas uma dica para o driver otimizar seu comportamento. Se não restringirmos as operações à área fornecida usando um scissor test (teste de tesoura) adequado, os pixels fora dessa área poderão ficar indefinidos (não podemos confiar no conteúdo deles). Também não podemos especificar uma área de renderização maior que as dimensões de um framebuffer.

std::array<VkClearValue, 2> clearValues = {};
clearValues[0].color = {0.0f, 0.0f, 0.0f, 1.0f};
clearValues[1].depthStencil = {1.0f, 0};
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();

Os dois últimos parâmetros definem os clear values a serem usados para VK_ATTACHMENT_LOAD_OP_CLEAR, que o Qt usou como operação de carregamento para o anexo de cores. Nós definimos clear color para simplesmente ficar preta com 100% de opacidade. Também precisamos incluir o cabeçalho <array> em renderer.cpp.

Em seguida, iniciamos o render pass. Para isso, chamamos a função vkCmdBeginRenderPass. Todas as funções que gravam comandos podem ser reconhecidas pelo prefixo vkCmd. Todas elas retornam void, então não haverá tratamento de erros até terminarmos a gravação.

VkCommandBuffer commandBuffer = m_window->currentCommandBuffer();
m_deviceFunctions->vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

O primeiro parâmetro para cada comando é sempre o buffer de comando para gravar o comando. Nesse caso, utilizamos a função QVulkanWindow::currentCommandBuffer() que retorna o buffer de comando ativo para a imagem atual do swap chain. O segundo parâmetro especifica os detalhes do render pass que acabamos de fornecer. O parâmetro final controla como os comandos de desenho dentro do render pass serão fornecidos. Por enquanto, definiremos isso como VK_SUBPASS_CONTENTS_INLINE, o que indica que continuaremos adicionando comandos ao mesmo buffer de comando. Também é possível chamar outros buffers de comando. Nesse caso, definimos isso como VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS.


Anterior Próximo