Estou lendo um tutorial incrível sobre o OpenGL . É realmente ótimo, confie em mim. O tópico em que estou atualmente é Z-buffer. Além de explicar o que é, o autor menciona que podemos realizar testes de profundidade personalizados, como GL_LESS, GL_ALWAYS etc. Ele também explica que o significado real dos valores de profundidade (que é superior e que não é) também pode ser personalizado. Eu entendo até agora. E então o autor diz algo inacreditável:
O intervalo zNear pode ser maior que o intervalo zFar; se for, os valores do espaço da janela serão revertidos, em termos do que constitui o mais próximo ou o mais distante do visualizador.
Anteriormente, foi dito que o valor de Z no espaço da janela de 0 é o mais próximo e 1 é o mais distante. No entanto, se nossos valores Z do espaço do clipe forem negados, a profundidade de 1 estará mais próxima da vista e a profundidade de 0 será a mais distante. No entanto, se mudarmos a direção do teste de profundidade (GL_LESS para GL_GREATER, etc), obteremos exatamente o mesmo resultado. Portanto, é realmente apenas uma convenção. De fato, inverter o sinal de Z e o teste de profundidade já foi uma otimização de desempenho vital para muitos jogos.
Se eu entendi corretamente, em termos de desempenho, inverter o sinal de Z e o teste de profundidade não passa de uma <
comparação para outra >
. Então, se eu entendi direito e o autor não está mentindo ou inventando as coisas, mudar <
para >
costumava ser uma otimização vital para muitos jogos.
O autor está inventando as coisas, estou entendendo mal alguma coisa, ou é realmente o caso que já <
foi mais lento ( vitalmente , como o autor diz) do que >
?
Obrigado por esclarecer este assunto bastante curioso!
Isenção de responsabilidade: Estou ciente de que a complexidade do algoritmo é a principal fonte de otimizações. Além disso, suspeito que hoje em dia definitivamente não faria diferença e não estou pedindo para otimizar nada. Sou extremamente, dolorosamente, talvez proibitivamente curioso.
Respostas:
Não expliquei isso muito bem, porque não era importante. Eu apenas senti que era um pouco interessante de acrescentar. Eu não pretendia revisar o algoritmo especificamente.
No entanto, o contexto é fundamental. Eu nunca disse que uma comparação <era mais rápida que uma>. Lembre-se: estamos falando de testes de profundidade de hardware gráfico, não de sua CPU. Não
operator<
.O que eu estava me referindo era uma otimização antiga específica em que um quadro você usaria
GL_LESS
com um intervalo de [0, 0,5]. No próximo quadro, você renderiza comGL_GREATER
um intervalo de [1.0, 0.5]. Você vai e volta, literalmente "lançando o sinal de Z e o teste de profundidade" a cada quadro.Isso perde um pouco de precisão de profundidade, mas você não precisava limpar o buffer de profundidade, que era uma vez uma operação bastante lenta. Como a limpeza em profundidade não é apenas gratuita atualmente, mas na verdade é mais rápida que essa técnica, as pessoas não fazem mais isso.
fonte
A resposta é quase certamente que, para qualquer encarnação de chip + driver usada, o Hierarchical Z só funcionava na mesma direção - esse era um problema bastante comum na época. Montagem / ramificação de baixo nível não tem nada a ver com isso - o buffer Z é feito em hardware de função fixa e é canalizado - não há especulações e, portanto, nenhuma previsão de ramificação.
fonte
Uma otimização como essa prejudicará o desempenho de muitas soluções gráficas incorporadas, pois tornará a resolução do buffer de quadros menos eficiente. A limpeza de um buffer é um sinal claro para o driver de que ele não precisa armazenar e restaurar o buffer ao fazer o bin.
Pouca informação de fundo: um rasterizador de ladrilhos / ladrilhos processa a tela em número de ladrilhos muito pequenos que cabem na memória do chip. Isso reduz gravações e leituras na memória externa, o que reduz o tráfego no barramento de memória. Quando um quadro é concluído (a troca é chamada ou os FIFOs são liberados porque estão cheios, as ligações do buffer de quadros são alteradas etc.), o buffer de quadros deve ser resolvido; isso significa que cada compartimento é processado por sua vez.
O driver deve assumir que o conteúdo anterior deve ser preservado. A preservação significa que a bandeja deve ser gravada na memória externa e posteriormente restaurada da memória externa quando a bandeja for processada novamente. A operação de limpeza informa ao motorista que o conteúdo da bandeja está bem definido: a cor limpa. Esta é uma situação que é trivial para otimizar. Também existem extensões para "descartar" o conteúdo do buffer.
fonte
Tem a ver com bits de flag em montagem altamente ajustada.
O x86 possui instruções jl e jg, mas a maioria dos processadores RISC possui apenas jl e jz (sem jg).
fonte
for
loops com uma ramificação incondicional para trás e uma ramificação condicional raramente levada adiante para sair do loop? Parece estranho.