O que o ddx (hlsl) realmente faz?

17

Estou um pouco confuso. A documentação oficial ( http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588(v=vs.85).aspx ) diz que ddx (entrada) é a derivada parcial da entrada com relação a para a "coordenada x do espaço na tela".

Meu cálculo é bom, mas como ele pode dizer de onde vem a entrada? Se eu aprovasse uma função, tudo bem, posso imaginar o que faria, mas a derivada de um número é sempre zero ...?

É apenas uma escala? Como, isso seria escalado para um décimo do seu tamanho a essa distância, então retorna um décimo? Mas então não precisa de uma entrada ...

Alguém pode dar uma explicação rápida do que realmente está acontecendo?

Richard Rast
fonte
2
ddxe ddyfaça mágica que você não pode fazer sozinho. Eles têm acesso a informações adicionais do pipeline de rasterização que você não pode adquirir de dentro de um pixel shader. Não tenho certeza exatamente qual fórmula eles usam; Fui levado a acreditar que eles usam uma técnica de estimativa, mas não sei ao certo.
Sean Middleditch
Isso é profundamente estranho, mas ainda assim. O que ddx (5) realmente representa? Se diz .1, como devo interpretar isso? Ou -6?
Richard Rast
1
ddx(5)é meio inútil. Use-o com um valor de entrada, e isso fornecerá a derivada desse valor em relação aos pixels vizinhos em um bloco. Novamente, eu não sei exatamente como ele calcula valores, mas solicitar a derivada de uma não entrada pode muito bem ser apenas um comportamento indefinido e produzir lixo. Veja fgiesen.wordpress.com/2011/07/10/… para obter mais informações do que eu posso fornecer.
Sean Middleditch
Não tenho certeza, mas pode ser que o compilador HLSL esteja realmente fazendo diferenciação simbólica completa da expressão que você passa para o ddx / ddy. blogs.msdn.com/b/chuckw/archive/2011/03/08/… research.microsoft.com/pubs/146019/…
Ziriax em
O que isso faz? A ÚNICA coisa ligeiramente razoável, obviamente.
MickLH

Respostas:

32

Internamente, as GPUs nunca executam uma instância de um pixel shader por vez. No nível mais fino de granularidade, eles estão sempre executando de 32 a 64 pixels ao mesmo tempo, usando uma arquitetura SIMD. Dentro disso, os pixels são ainda organizados em quads 2x2, de modo que cada grupo de 4 pixels consecutivos no vetor SIMD corresponde a um bloco 2x2 de pixels na tela.

As derivadas são calculadas tomando-se diferenças entre os pixels em um quad. Por exemplo, ddxsubtrai os valores nos pixels no lado esquerdo do quad dos valores no lado direito e ddysubtrai os pixels inferiores dos superiores. As diferenças podem então ser retornadas como derivada para todos os quatro pixels no quad.

Como o sombreador de pixels está sendo executado no SIMD, é garantido que o valor correspondente esteja no mesmo registro ao mesmo tempo para todos os pixels no quad. Portanto, seja qual for a expressão ou o valor que você colocar ddxou ddyserá avaliado nos quatro pixels do quadrilátero, os valores de pixels diferentes serão subtraídos conforme descrito acima.

Portanto, tirar a derivada de um valor constante dará zero (como seria de esperar do cálculo, certo?), Porque é o mesmo valor constante em todos os quatro pixels.

Observe também que existem derivadas "grossas" e "finas", ddx_coarse/ ddy_coarsee ddx_fine/ ddy_fine. Uma explicação da distinção é dada aqui . Simplesmente ddx/ ddysão aliases para as versões grosseiras.

BTW, o motivo dessa funcionalidade existir é que as GPUs internamente precisam obter derivadas das coordenadas de textura para fazer a seleção do mipmap e a filtragem anisotrópica. Como o hardware precisa da capacidade de qualquer maneira (você pode usar qualquer expressão arbitrária para coordenadas de textura em um sombreador), foi fácil o suficiente também expô-lo diretamente aos programadores de sombreador.

Nathan Reed
fonte
+1; Achei isso útil ao aplicar um efeito de perturbação a uma textura; os texcoords perturbados causavam alguma distorção de cor, mas o uso do tex2Dgrad com derivadas dos cabos tex tex originais (não perturbados) deu um resultado sem distorções.
Maximus Minimus
Tudo bem, depois de pensar um pouco, acho que descobri minha confusão. Na minha opinião, ddxfunciona como qualquer outra função em uma linguagem de programação tradicional; você avalia a entrada, transforma-a em um ponto flutuante ou o que for e, em seguida, executa a função externa ( ddx). Mas isso é diferente: pega a sequência de entrada , avalia-a em vários locais, calcula uma derivada e relata o resultado. Isso é certo?
Richard Rast 24/09
1
@RichardRast Right. Você pode pensar ddxcomo operando na expressão que passa para ela, e não no valor .
Nathan Reed
Mas veja, isso é estranho o suficiente para constar na documentação. Não consigo pensar em nenhum outro momento da minha vida de programação em que esse tenha sido o caso.
Richard Rast
Nathan Reed mencionou que as GPUs usam essas funções para a seleção do mipmap. Você também pode usá-los para forçar a GPU a selecionar um nível de mapa mip desejado ou para impedir que artefatos sejam selecionados incorretamente no nível mip. O processo está descrito nas páginas 163 e 164 do Shader X3.
precisa saber é o seguinte