buffer - name - meta title y meta descripcion
¿Por qué no se permite escribir en un búfer desde un sombreador de fragmentos en Metal? (2)
Como se indica en la Guía de idiomas de Metal Shading :
Las escrituras en un búfer o una textura no están permitidas en una función de fragmento.
Entiendo que este es el caso, pero tengo curiosidad por saber por qué. Ser capaz de escribir en un búfer desde un sombreador de fragmentos es increíblemente útil ; Entiendo que es probable que sea más complejo en el extremo del hardware el no saber de antemano la ubicación final de las escrituras de memoria para un subproceso en particular, lo que no siempre se sabe con las escrituras de búfer sin procesar, pero esta es una capacidad expuesta en Metal compute shaders, entonces ¿por qué no dentro de los shaders de fragmentos también?
Apéndice
Debería aclarar por qué creo que las escrituras de búfer de funciones de fragmentos son útiles. En el caso de uso más común de la tubería de rasterización, los triángulos se rasterizan y sombrean (según el sombreador de fragmentos) y se escriben en ubicaciones de memoria predefinidas, conocidas antes de cada invocación de sombreadores de fragmentos y determinadas por el mapeo predefinido a partir de las coordenadas normalizadas del dispositivo y el marco buffer. Esto se adapta a la mayoría de los casos de uso, ya que la mayoría de las veces solo desea renderizar triángulos directamente en un búfer o en la pantalla.
Hay otros casos en los que podría querer hacer una escritura perezosa dentro del sombreador de fragmentos, cuya ubicación final se basa en las propiedades del fragmento y no en la ubicación exacta del fragmento; Efectivamente, rasterización con efectos secundarios. Por ejemplo, la mayoría de la voxelización basada en GPU funciona al representar la escena con proyección ortográfica desde algún ángulo deseable, y luego escribir en una textura 3D, mapeando las coordenadas XY del fragmento y su valor de profundidad asociado a una ubicación en la textura 3D. Esto se describe here .
Otros usos incluyen algunas formas de transparencia independiente del pedido (la transparencia donde el orden de dibujo no es importante, permitiendo la superposición de objetos transparentes). Una solución es utilizar un búfer de cuadros de varias capas, y luego ordenar y combinar los fragmentos en función de sus valores de profundidad en un pase separado. Dado que no hay soporte de hardware para hacer esto (en la mayoría de las GPU, creo que Intel tiene aceleración de hardware para esto), debe mantener contadores atómicos y escrituras manuales de textura / búfer de cada píxel para coordinar las escrituras en el búfer de marco en capas.
Otro ejemplo podría ser la extracción de luces de puntos virtuales para GI a través de la rasterización (es decir, se escriben luces de puntos para fragmentos relevantes a medida que se rasterizan). En todos estos casos de uso, se requieren escrituras de búfer desde los sombreadores de fragmentos, porque los ROP solo almacenan un fragmento resultante para cada píxel. La única forma de lograr resultados equivalentes sin esta función es mediante algún tipo de pelado de profundidad, que es terriblemente lento para escenas de gran complejidad.
Ahora me doy cuenta de que los ejemplos que proporcioné no son realmente todo sobre escrituras de búferes en particular, sino más generalmente sobre la idea de escrituras de memoria dinámica desde fragmentos de sombreado, idealmente junto con soporte para atomicidad. La escritura de búfer simplemente parece un problema simple, y su inclusión ayudaría en gran medida a mejorar la situación.
Como no recibía ninguna respuesta aquí, terminé publicando la pregunta en los foros de desarrolladores de Apple . Recibí más comentarios allí, pero todavía no tengo una respuesta real. A menos que me esté faltando algo, parece que virtualmente todos los dispositivos OS X que son oficialmente compatibles con Metal tienen soporte de hardware para esta función. Y, según tengo entendido, esta característica comenzó a aparecer en las GPU alrededor del 2009. Es una característica común tanto en DirectX actual como en OpenGL (sin considerar DX12 o Vulkan), por lo que Metal sería la única API "vanguardista" que no tiene .
Me doy cuenta de que esta característica podría no ser compatible con el hardware PowerVR, pero Apple no tuvo problemas para diferenciar el Metal Shading Language por su conjunto de funciones. Por ejemplo, Metal en iOS permite la obtención de búferes de fotogramas "libres" dentro de los sombreadores de fragmentos, que son soportados directamente en el hardware por la arquitectura PowerVR de gran caché. Esta función se manifiesta directamente en el Metal Shading Language, ya que le permite declarar entradas de función de fragmento con el calificador de atributo [[color(m)]]
para sombreadores de iOS. Podría decirse que permitir la declaración de búferes con el calificador de espacio de almacenamiento del device
, o las texturas con access::write
, como entradas para los sombreadores de fragmentos, no sería un cambio semántico mayor en el lenguaje que lo que Apple ha hecho para optimizar iOS. Entonces, en lo que a mí respecta, la falta de soporte de PowerVR no explicaría la falta de la función que estoy buscando en OS X.
Ahora se admite la escritura en búferes desde sombreadores de fragmentos, como se menciona en Novedades en iOS 10, tvOS 10 y macOS 10.12
Función Buffer Read-Writes Disponible en: iOS_GPUFamily3_v2, OSX_GPUFamily1_v2
Las funciones de fragmentos ahora pueden escribir en buffers. Los buffers grabables deben declararse en el espacio de direcciones del dispositivo y no deben ser const. Utilice la indexación dinámica para escribir en un búfer.
Además, la línea que especifica la restricción (de la pregunta original) no se encuentra en Metal Shading Language Specification 2.0
Creo que no puede escribir píxeles o texels arbitrarios en una función de fragmento en OpenGL o DirectX. Una cosa es la API de representación y otra son las funciones de fragmentos o vértices.
Se pretende que una función de fragmento produzca como resultado una salida de píxel / texel, una por ejecución, incluso si cada una tiene varios canales. Por lo general, si desea escribir en un búfer o una textura, debe renderizar algo (un cuadrángulo, un triángulo o algo con su función de fragmentación sobre una superficie (búfer o textura). Como resultado, cada píxel / texel se procesará con su función de fragmentación Por ejemplo, las funciones de fragmento de trazado de rayos o de trazado de rayos usualmente utilizan este enfoque.
Hay una buena razón para no permitirle escribir píxeles / texels arbitrarios: paralelización. La función de fragmentación se ejecuta generalmente para muchos píxeles / texels diferentes a la vez en la mayoría de las GPU en un modo de paralelización muy alto, cada GPU tiene su propia manera de paralelizar (SMP, vectorial ...) pero todas tienen paralelización muy alta . Por lo tanto, puede escribir solo devolviendo una salida de los canales de un píxel o de un texel como el retorno de la función de fragmentos para evitar problemas comunes de paralelización como las razas. Esto se aplica a cada biblioteca gráfica que conozco.