Como a atualização de um buffer de profundidade funciona na GPU?


10

No momento, estou tentando implementar algum tipo de buffer de profundidade no software e tenho um grande problema ao escrever nele. Ter um mutex é um exagero absoluto. Então eu criei um número de mutexes igual ao número de threads. Estou bloqueando um mutex com base no pixel atual (pixel_index% mutexes_number) e isso funciona melhor, mas ainda é muito, muito lento. E eu me pergunto como é feito em uma GPU real? Existe um algoritmo inteligente ou hardware lida com isso?

Respostas:


9

Hardware altamente especializado lida com isso. Uma estratégia típica é uma GPU colocar lado a lado a rasterização e armazenar informações de profundidade em formatos compactados (por exemplo, a equação z quando um polígono cobre completamente um lado a lado). Isso permite testar um bloco inteiro de uma só vez; outros truques legais de HW incluem teste de profundidade antes da execução do sombreador de pixels (assumindo que as condições o permitam - o sombreador não pode gravar um valor de profundidade). Você pode considerar algo semelhante em software, como ter cada encadeamento "possuir" um subconjunto de blocos e percorrer cada primitivo independentemente ou imitar estratégias de várias gpu, como quadros alternativos ou linhas de varredura alternativas.


11

Em uma GPU real, em vez de ter vários núcleos tentando ler / gravar a mesma região do buffer de profundidade e tentar sincronizar entre eles, o buffer de profundidade é dividido em blocos (como 16 × 16 ou 32 × 32) e cada o bloco é atribuído a um único núcleo. Esse núcleo é responsável por toda a rasterização nesse bloco: quaisquer triângulos que tocam nesse bloco serão rasterizados (dentro desse bloco) pelo núcleo proprietário. Então não há interferência entre os núcleos e não é necessário que eles sejam sincronizados ao acessar sua parte do buffer de estrutura.

Isso implica que triângulos que tocam em vários blocos precisarão ser rasterizados por vários núcleos. Portanto, há uma etapa de redistribuição de trabalho entre o processamento de geometria (operações em vértices e triângulos) e o processamento de pixels.

No estágio de geometria, cada núcleo pode processar um pedaço de primitivas de entrada; depois, para cada primitiva, ele pode determinar rapidamente em quais blocos os toques primitivos (isso é chamado de "rasterização grossa") e adicionar o primitivo a uma fila para cada núcleo que possui um dos blocos afetados.

Em seguida, no estágio de pixel, cada núcleo pode ler a lista de primitivas em sua fila, calcular a cobertura de pixels para os blocos que o núcleo possui e prosseguir para testes de profundidade, sombreamento de pixels e atualização do buffer de estrutura, sem a necessidade de coordenação adicional. com outros núcleos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.