Como usar o UpdateSubresource e Map / Unmap?

8

Pelo que entendi (da leitura de várias páginas), existem 2 maneiras de atualizar um buffer:

  1. UpdateSubresource()(quando o buffer é criado com o DEFAULTuso)
  2. Map(), copie os novos dados Unmap()(quando o buffer for criado com o DYNAMICuso)

No primeiro caso, chamo apenas essa função (nada mais)? Porque eu vi pessoas dizerem que mapeiam o buffer e atualizam o sub-recurso, ou talvez eu as tenha entendido mal.

Também existe outra maneira (duvide: P)? Eu entendo as coisas corretamente?

NPS
fonte

Respostas:

11

Há uma boa apresentação sobre isso: Não jogue tudo fora: gerenciamento eficiente de buffer de John McDonald na NVIDIA. Abrange vários temas, mas sobre o tema da sua pergunta, o conselho geral é criar buffers com o uso dinâmico e uso Map()com D3D11_MAP_WRITE_DISCARD, quando os dados precisa ser atualizado com freqüência (como todos os quadros, ou várias vezes por quadro). Isso seria usado para buffers constantes, buffers de vértices para sistemas de partículas e similares.

De acordo com a apresentação, o uso padrão / UpdateSubresource()incorre em mais sobrecarga da CPU do que o uso dinâmico / Map(). No entanto, ele recomenda o uso padrão / UpdateSubresource()para dados que precisam ser atualizados apenas de vez em quando, como dados transmitidos do disco em um jogo de mundo aberto.

E sim, no caso em que você usa UpdateSubresource(), você o usa por si só, não em combinação com Map().

Nathan Reed
fonte
2
Estranho, vocês dois responderam no mesmo minuto e postaram o mesmo link.
NPS
Em outro segmento, você escreveu: "Você não precisa vincular o buffer para atualizá-lo com o UpdateSubresource. Na verdade, ele não deve ser vinculado ao atualizá-lo". Isso significa que eu sempre devo desvincular todos os buffers antes de atualizá-los? Em caso afirmativo, como desvincular um buffer?
NPS
11
@ NPS Antes de tudo, será implicitamente ilimitado se você já tiver vinculado outra coisa em seu lugar. Caso contrário, você pode ligar explicitamente NULL para desvincular um buffer. Por exemplo, você pode fazer ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);a uma textura unbind de slot 0.
Nathan Reed
Eu sabia sobre o implícito, mas precisava do explícito, thx. Mas você não respondeu à minha primeira pergunta - tenho que fazer isso sempre para todos os buffers que pretendi atualizar?
NPS
11
@NPS Idealmente, o buffer não deve estar em uso pela GPU no momento em que você o atualiza na CPU. Mas a GPU e a CPU funcionam de forma assíncrona, portanto, isso não é fácil de garantir. Eu diria que não se preocupe, a menos que você encontre um problema de desempenho real.
Nathan Reed
2

Eles podem estar se referindo ao ato real de atualizar um recurso e não à chamada de função real. Em geral, UpdateSubResource deve ser usado para recursos padrão que não estão sujeitos a atualizações frequentes (ou seja, nem todos os quadros. Nesse caso, é mais provável que o buffer possa ser copiado para um buffer temporário acessível a partir do buffer de comando ( devido a condições de corrida, por exemplo), além de permitir a atualização de sub- recursos (em texturas, por exemplo).

Mapear / Desmapear deve ser usado quando um recurso for atualizado com muita frequência (ou seja, todos os quadros), como alguns buffers constantes. O caso mais comum é quando você está substituindo o buffer inteiro pelo WriteDiscard. Há uma apresentação da nVidia em que eles recomendam essa prática.

O andarilho
fonte