¿Cómo funciona la actualización de un buffer de profundidad en la GPU?

10

En este momento estoy tratando de implementar algún tipo de búfer de profundidad en el software y tengo un gran problema cuando le escribo. Tener un mutex es una exageración absoluta. Entonces creé una cantidad de mutexes igual a la cantidad de hilos. Estoy bloqueando un mutex basado en el píxel actual (pixel_index% mutexes_number) y esto funciona mejor, pero sigue siendo muy lento. ¿Y me pregunto cómo se hace en una GPU real? ¿Existe algún algoritmo inteligente o hardware que lo maneje?

nikitablack
fuente

Respuestas:

9

El hardware altamente especializado lo maneja. Una estrategia típica es que una GPU mezcle la rasterización y almacene información de profundidad en formatos comprimidos (por ejemplo, la ecuación z cuando un polígono cubre completamente un mosaico). Esto permite realizar pruebas en todo un mosaico a la vez; Otros trucos geniales de HW incluyen pruebas de profundidad antes de ejecutar el sombreador de píxeles (suponiendo que las condiciones lo permitan, el sombreador no puede escribir un valor de profundidad). Puede considerar algo similar en el software, como hacer que cada subproceso "posea" un subconjunto de mosaicos y recorrer cada primitivo de forma independiente, o imitar estrategias de múltiples gpu como marcos alternativos o líneas de trama alternativas.

Daniel M Gessel
fuente
11

En una GPU real, en lugar de tener múltiples núcleos que intentan leer / escribir la misma región del búfer de profundidad e intentar sincronizar entre ellos, el búfer de profundidad se divide en mosaicos (como 16 × 16 o 32 × 32), y cada uno el mosaico se asigna a un solo núcleo. Ese núcleo es responsable de toda la rasterización en ese mosaico: cualquier triángulo que toque ese mosaico será rasterizado (dentro de ese mosaico) por el núcleo propietario. Entonces no hay interferencia entre los núcleos, y no es necesario que se sincronicen al acceder a su parte del framebuffer.

Esto implica que los triángulos que tocan múltiples mosaicos necesitarán ser rasterizados por múltiples núcleos. Entonces, hay un paso de redistribución de trabajo entre el procesamiento de geometría (operaciones en vértices y triángulos) y el procesamiento de píxeles.

En la etapa de geometría, cada núcleo puede procesar una porción de primitivas de entrada; luego, para cada primitivo, puede determinar rápidamente qué mosaicos toca el primitivo (esto se denomina "rasterización gruesa") y agregar el primitivo a una cola para cada núcleo que posee uno de los mosaicos afectados.

Luego, en la etapa de píxeles, cada núcleo puede leer la lista de primitivas en su cola, calcular la cobertura de píxeles para los mosaicos que posee el núcleo y proceder a las pruebas de profundidad, sombreado de píxeles y actualización del framebuffer, sin necesidad de ninguna coordinación adicional. con otros núcleos

Nathan Reed
fuente