Os compiladores de shader são extremamente agressivos quanto ao desenrolamento, pois o HW inicial muitas vezes não tinha controle de fluxo e o custo em HW mais recente pode variar. Se você tem uma referência em que está testando ativamente e uma variedade de hardware relevante, tente as coisas para ver o que acontece. Seu loop dinâmico é mais passível de intervenção do desenvolvedor do que um loop estático - mas deixá-lo para o compilador ainda é um bom conselho, a menos que você tenha um benchmark disponível. Com uma referência, a exploração vale a pena (e é divertida).
BTW, a maior perda com um loop dinâmico em uma GPU é que "threads" individuais em uma frente de onda / distorção terminam em momentos diferentes. Os threads que param mais tarde forçam todos os que terminam cedo a executar NOPs.
Os loops aninhados devem ser cuidadosamente pensados: Implementei um decodificador de entropia baseado em bloco que codifica execuções de zeros (para JPEG como compactação). A implementação natural era decodificar as execuções em um loop interno apertado - o que significava frequentemente que apenas um thread estava progredindo; achatando o loop e testando explicitamente em cada thread se atualmente estava decodificando uma execução ou não, mantive todos os threads ativos através do loop de comprimento fixo (os blocos decodificados tinham o mesmo tamanho). Se os threads fossem como threads de CPU, a mudança teria sido terrível, mas na GPU em que eu estava executando, obtive um aumento de 6 vezes no desempenho (o que ainda era terrível - não havia blocos suficientes para manter a GPU ocupada - mas foi uma prova de conceito).