Link

Instância, janela e renderizador Vulkan

Antes de continuarmos com o desenvolvimento do nosso aplicativo usando Vulkan, vamos entender as classes do Qt que precisaremos usar nele.


QVulkanInstance

Como já mencionamos anteriormente, a interação com o Vulkan começa com o objeto de instância do tipo VkInstance. Um aplicativo geralmente cria um único objeto de instância que contém o estado do aplicativo inteiro. Todos os demais objetos Vulkan só podem ser criados a partir desse objeto. No Qt, a classe correspondente é QVulkanInstance. Essa classe representa uma instância nativa do Vulkan, permitindo a renderização do Vulkan em um objeto do tipo QSurface1.

1 A classe QSurface é uma abstração de superfícies renderizáveis no Qt.

QVulkanInstance também fornece uma maneira conveniente de configurar o Vulkan e, em seguida, inicializá-lo com a configuração fornecida. Também podemos usar suas funções supportedExtensions() e supportedLayers() para consultar recursos suportados antes de usá-los. Após a configuração ser feita, devemos chamar a função create() que realmente inicia o carregamento da biblioteca Vulkan e a criação de um objeto VkInstance. Se essa função retornar true, o objeto de instância do Vulkan estará pronto para ser usado. Essa forma de inicialização do objeto de instância permite usar QVulkanInstance como uma variável membro simples, mantendo o controle sobre quando executar a inicialização.


QVulkanWindow

O próximo passo é criar uma janela capaz de renderizar imagens usando Vulkan. Isso é feito definindo uma classe como subclasse de QVulkanWindow. Essa classe é uma subclasse de QWindow2 capaz de acessar a API Vulkan que gerencia os seguintes recursos:

  • um dispositivo Vulkan do tipo VkDevice;
  • uma fila de gráficos;
  • um pool e um buffer de comandos;
  • uma imagem de depth-stencil;
  • um swapchain FIFO com buffer duplo;
  • um framebuffer para cada imagem do swap chain.

QVulkanWindow também cria um render pass com um subpass responsável por garantir que as imagens do swap chain e de depth-stencil sejam transferidas para um layout apropriado para apresentar essas imagens ao swap chain e um layout otimizado para uso do anexo de depth-stencil. Enquanto cuida do comportamento correto quando se trata de eventos como redimensionar o tamanho da janela, situações especiais como não ter uma fila de dispositivos que suporte gráficos e apresentações ao mesmo tempo, cenários de perda de dispositivos e funcionalidades adicionais, como ler o conteúdo renderizado de volta.

2 QVulkanWindow nem sempre elimina a necessidade de implementar uma subclasse QWindow totalmente customizada, pois ela não será necessariamente suficiente em casos de uso avançados. Mas para nosso caso vai funcionar bem.

Também podemos usar funções virtuais herdadas de QWindow para manipular quaisquer eventos despachados pelo sistema de eventos do Qt. Conceitualmente, é a contraparte do QOpenGLWindow no mundo Vulkan.

Um objeto do tipo QVulkanWindow deve sempre ser associado a um objeto do tipo QVulkanInstance e, portanto, devemos executar a criação da instância antes da janela e usar a função setVulkanInstance() para configurá-la no objeto QVulkanWindow. No entanto, as subclasses de QVulkanWindow não devem executar nenhuma renderização real. Esta tarefa é delegada à classe QVulkanWindowRenderer. A função virtual QVulkanWindow::createRenderer() será chamada uma vez depois que a janela é mostrada pela primeira vez, e devemos reimplementar esta função para retornar seu objeto renderizador.


QVulkanWindowRenderer

Agora, sobre o próprio renderizador: QVulkanWindowRenderer é uma classe simples contendo nada mais que um conjunto de funções virtuais. Ela permite implementar o gerenciamento de recursos do Vulkan e o buffer de comando que compõem a renderização da aplicação (QT, 2018c). Podemos criar nosso próprio renderizador definindo uma classe como subclasse de QVulkanWindowRenderer e reimplementar a única função virtual pura chamada startNextFrame(). Esta função será chamada quando a imagem do próximo quadro for solicitado. Podemos executar todas as operações de renderização necessárias nesta função e finalizá-la com uma chamada para QVulkanWindow::frameReady() para indicar que a imagem está completa. Também podemos reimplementar outras funções virtuais do renderizador. As mais úteis são initResources() e releaseResources(), que permitem iniciar os recursos gráficos do renderizador e depois liberá-los quando necessário.

Agora que aprendemos um pouco sobre as classes principais do Qt que precisamos usar em um aplicativo Vulkan, veremos como colocá-las em prática.


Anterior Próximo