Estou meio que lutando para entender a diferença conceitual entre buffers uniformes e constantes push. Pelo que consigo entender lendo as especificações, as principais diferenças são:
- Buffers uniformes podem ser muito maiores que constantes push.
- UBOs usam std140, PCs usam std430.
- Os UBOs podem ser atualizados a qualquer momento com vkCmdUpdateBuffer (ou mapeamento de host) e mantêm seus valores, caso contrário, os PCs precisam ser pressionados novamente para cada passagem de renderização. (O que me surpreendeu - com base no nome. Pensei em literalmente atualizar constantes no pipeline no local e fazer com que essas alterações persistissem)
No meu cenário, tenho cerca de ~ 200 bytes de dados que espero que sejam constantes . Ou seja, vou alterá-los com pouca frequência. Seria melhor (assumindo o tamanho permitido) usar constantes push, mesmo que eu tenha que reenviá-las em todos os buffers de comando? Ou seria melhor usar um UBO de 200 bytes e atualizá-lo apenas com frequência com vkCmdUpdatebuffer?
Além disso. e se eu tiver, por exemplo, um float random_seed
que atualizarei toda vez que o shader for executado? Supondo que eu já possua uma UBO, seria melhor agrupá-la com a UBO, mesmo que o restante da UBO seja constante, ou eu obteria um benefício ao usar constantes push para especificamente essa variável, para evitar evitar vkCmdUpdateBuffer antes de cada passagem de renderização?
Respostas:
Na especificação: "vkCmdUpdateBuffer é permitido apenas fora de um passe de renderização". Portanto, "a qualquer momento" não é o caso.
Mesmo que tenha sido permitido dentro de um passe de renderização, ainda é uma operação de transferência. O que significa que você precisa sincronizar a transferência de memória com os comandos que a utilizam. O que diminui o desempenho.
Para o geral Push Constant vs. Uniform, use seu julgamento. Por "julgamento", quero dizer, apenas observe como eles funcionam. As constantes push permitem que você altere seus dados a qualquer momento sem realizar processos pesados, como operações de memória, sincronização ou alteração do estado do descritor. Claramente, eles servem para alterar dados com frequência. Com que frequência é "frequentemente"? Bem, isso é um julgamento.
Caso contrário, analise a diferença de desempenho.
fonte
Se os dados não forem alterados com frequência, você poderá usar constantes de especialização . Eles são definidos quando o pipeline é criado, e um novo pipeline deve ser criado se você precisar alterar os valores. Para um evento não frequente, como o redimensionamento de uma janela, esse pode ser um custo aceitável.
Esse é um caso de uso perfeito para constantes de envio. Você pode manter todos os outros dados na UBO (ou nas constantes de especialização) e alterar esse valor com
VkCmdPushConstants
.fonte