¿Cómo usar UpdateSubresource y Map / Unmap?

8

Por lo que entendí (al leer varias páginas) hay 2 formas de actualizar un búfer:

  1. UpdateSubresource()(cuando el búfer se crea con el DEFAULTuso)
  2. Map(), copie los datos nuevos Unmap()(cuando se crea el búfer con el DYNAMICuso)

En el primer caso, ¿solo llamo a esta función (nada más)? Debido a que he visto a personas decir que mapean el búfer y luego actualizan los recursos secundarios, o tal vez los entendí mal.

Además, ¿hay alguna otra manera (lo dudo: P)? ¿Entiendo las cosas correctamente?

NPS
fuente

Respuestas:

11

Hay una buena presentación sobre esto: no lo deseche todo: gestión eficiente del búfer por John McDonald en NVIDIA. Cubre varios temas, pero sobre el tema de su pregunta, el consejo general es crear buffers con uso dinámico y uso Map()con D3D11_MAP_WRITE_DISCARD, cuando los datos deben actualizarse con frecuencia (como cada cuadro, o varias veces por cuadro). Esto se usaría para memorias intermedias constantes, memorias intermedias de vértices para sistemas de partículas, y similares.

Según la presentación, uso predeterminado / UpdateSubresource() incurre más sobrecarga de la CPU que el uso dinámico / Map(). Sin embargo, recomienda el uso predeterminado / UpdateSubresource()para los datos que deben actualizarse solo de vez en cuando, como los datos que se transmiten desde el disco en un juego de mundo abierto.

Y sí, en el caso de que lo use UpdateSubresource(), lo usaría solo, no en combinación con Map().

Nathan Reed
fuente
2
Extraño, ambos respondieron en el mismo minuto y publicaron el mismo enlace.
NPS
En otro hilo escribió: "No necesita vincular el búfer para actualizarlo con UpdateSubresource. De hecho, no debería estar vinculado cuando lo actualiza". ¿Significa esto que siempre debería desvincular todos los buffers antes de actualizarlos? Si es así, ¿cómo puedo desvincular un búfer?
NPS
1
@NPS En primer lugar, quedará implícitamente desvinculado si ya ha vinculado algo más en su lugar. De lo contrario, puede vincular explícitamente NULL para desvincular un búfer. Por ejemplo, puedes ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);deshacer una textura de la ranura 0.
Nathan Reed
Sabía sobre el implícito pero necesitaba el explícito, thx. Pero no respondió a mi primera pregunta: ¿tengo que hacer esto siempre para todos los buffers que he actualizado?
NPS
1
@NPS Idealmente, el búfer no debería estar en uso por la GPU en el momento en que lo actualiza en la CPU. Pero la GPU y la CPU se ejecutan de forma asíncrona, por lo que no es fácil garantizarlo. Yo diría que no se preocupe por eso a menos que encuentre que es un problema de rendimiento real.
Nathan Reed
2

Es posible que se hayan referido al acto real de actualizar un recurso y no a la llamada a la función real. En general, UpdateSubResource debe usarse para recursos predeterminados que no están sujetos a actualizaciones frecuentes (es decir: no todos los cuadros. En este caso, es más probable que el búfer se pueda copiar en un búfer temporal accesible desde el búfer de comandos ( debido a condiciones de carrera, por ejemplo). También te permitirá la actualización sub recursos (en texturas, por ejemplo).

Map / Unmap debe usarse cuando un recurso se va a actualizar con mucha frecuencia (es decir, cada cuadro), como algunos buffers constantes. El caso más común es cuando está sobrescribiendo todo el búfer con WriteDiscard. Hay una presentación de nVidia donde recomiendan esta práctica.

El vagabundo
fuente