Ajuda a declarar variáveis fora do seu escopo de função principal no GLSL? Essas variáveis são realmente reutilizadas e são mais eficientes?
Aqui está o código em questão:
varying vec2 vposition;
uniform float seed;
uniform float top;
uniform float bottom;
uniform float phi;
uniform float theta;
uniform float scaledPI;
uniform float yn;
uniform float ym;
uniform float rx;
uniform float ry;
uniform float radius;
const float PI = 3.141592653589793238462643383;
float left;
float right;
float mscaled;
float xn;
float xm;
void main() {
float t = vposition.y * yn + ym;
if(t <= 0.0 || t >= PI){
left = phi - PI;
right = phi + PI;
}else{
mscaled = scaledPI / (1 - abs(Math.cos(theta)));
mscaled = mscaled < PI ? mscaled : PI;
left = phi - mscaled;
right = phi + mscaled;
}
xn = (left - right) / ((-rx / 2.0) - (rx / 2.0));
xm = left - ((-rx/2.0) * xn);
float p = vposition.x * xn + xm;
vec3 coords = vec3( sin(p) * sin(t), cos(t), cos(p) * sin(t) );
float nv = surface( vec4( coords, seed ) );
gl_FragColor = vec4( vec3( nv, nv, nv ), 1.0 );
}
main()
função? Seus valores são realmente variáveis globais (uniformes ou atributos na linguagem GLSL) ou valores constantes?Respostas:
Acho que entendi o que você está tentando perguntar. Presumo que sua principal preocupação sejam as variáveis não uniformes definidas fora de
main()
:Vamos dar uma olhada em como a GPU e o GLSL funcionam. A GPU não possui uma pilha ou registros de ativação de chamada. Não há como simular escopo ou variáveis locais no GLSL, como um compilador C pode fazer na maioria das CPUs. Tudo o que existe são os registros, que são registros uniformes, entradas do estágio de sombreador, saídas e o arquivo de registro local exclusivo para essa chamada de sombreador.
Em outras palavras, como não existe uma função, a pilha ou a pilha, todas as variáveis declaradas em qualquer lugar ficam em um registro. Seja local para algum escopo no GLSL ou global para o arquivo inteiro, não faz diferença. Eles são apenas registros.
No entanto, o alocador de registro não faz parte do padrão GLSL. Diferentes implementações de OpenGL podem ter níveis variados de qualidade quando se trata de converter código GLSL de alto nível em código de máquina de baixo nível que a GPU entende. Uma das partes mais complicadas de um compilador (GLSL ou não) é a alocação de registros . Essa é a parte do compilador que determina quais registros uma determinada variável ocupa. C tem um pouco mais de dificuldade, pois geralmente tem que lidar com arquivos de registro muito pequenos (especialmente no x86) e tem que lidar com derramamento de registro (mover variáveis para a pilha) e alias (salvar variáveis de volta na RAM antes de chamar funções) e instruções ímpares que exigem a saída em um registro específico (x86
idiv
por exemplo). As GPUs têm um arquivo de registro grande por não terem pilha ou pilha, portanto, o alocador pode ser mais simples.No entanto, o arquivo de registro não é infinito. Se você tiver mais variáveis do que registros suportados pelo seu hardware, o compilador precisará ajustar todas as suas variáveis nos registros. Isso geralmente requer alguma forma de verificação do alcance da animação . Ou seja, se você usar uma variável
xn
para um cálculo e nunca mais usá-la novamente, o compilador poderá determinar isso e, em seguida, saber que o registro ocupado porxn
poderia ser usado por outra variável posteriormente, permitindo mais variáveis do que há registros (por muito tempo porque não há muitas variáveis dinâmicas ao mesmo tempo).O compilador pode não fazer isso, no entanto. Não tem. Ou pode fazê-lo apenas em alguns casos. Os escopos deram aos compiladores mais simples um problema muito mais fácil de resolver. Todos os registros alocados às variáveis de função local podem ser reutilizados após a saída dessa função, porque ela sabe que as variáveis estão mortas. Variáveis globais não têm essa garantia fácil. Portanto, alguns compiladores menos capazes podem não otimizar sua vida útil também, e as variáveis globais sempre consomem um registro. Isso não tornará nada mais lento, mas em alguns drivers poderá limitar o tamanho do sombreador que você pode escrever.
Em geral, eu recomendaria manter todas as variáveis localizadas. Mantenha a definição o mais próximo possível do uso da variável. Isso se aplica a todas as linguagens de programação, não apenas ao GLSL. Eu também recomendaria criar todas as constantes "variáveis" em todos os casos possíveis. Mais uma vez, pode ser uma dica para certos compiladores menos capazes de que certas otimizações são possíveis e, mais importante, torna seu código mais auto-documentado e fácil de manter.
E, claro, aqui está o seu obrigatório "apenas perfil para testar e descobrir com certeza" conselhos. Escreva seu shader com e sem os globais e faça o perfil. Todo e qualquer aconselhamento on-line sobre desempenho deve ser desconfiado e presumido estar imerso em suposição ou desatualizado.
fonte