Come usare UpdateSubresource e Map / Unmap?


8

Da quello che ho capito (dalla lettura di varie pagine) ci sono 2 modi per aggiornare un buffer:

  1. UpdateSubresource()(quando il buffer viene creato con l' DEFAULTutilizzo)
  2. Map(), copia i nuovi dati, Unmap()(quando il buffer viene creato con l' DYNAMICutilizzo)

Nel primo caso, chiamo solo questa funzione (niente di più)? Perché ho visto persone dire che mappano il buffer e quindi aggiornano subresource, o forse li ho fraintesi.

C'è anche un altro modo (ne dubito: P)? Capisco le cose correttamente?

Risposte:


11

C'è una buona presentazione a riguardo: non buttare via tutto: efficiente gestione del buffer di John McDonald presso NVIDIA. Copre vari argomenti, ma sull'argomento della tua domanda, il consiglio generale è quello di creare buffer con utilizzo dinamico e uso Map()con D3D11_MAP_WRITE_DISCARD, quando i dati devono essere aggiornati frequentemente (come ogni frame o più volte per frame). Questo sarebbe usato per buffer costanti, buffer di vertici per sistemi particellari e simili.

Secondo la presentazione, l'utilizzo predefinito / UpdateSubresource()comporta un sovraccarico della CPU rispetto all'utilizzo dinamico / Map(). Tuttavia, raccomanda l'uso predefinito / UpdateSubresource()per i dati che devono essere aggiornati solo una volta ogni tanto, come i dati trasmessi dal disco in un gioco open-world.

E sì, nel caso in cui lo usi UpdateSubresource(), lo useresti da solo, non in combinazione con Map().


2
Uncanny, entrambi avete risposto nello stesso minuto e pubblicato lo stesso link.
NPS,

In un altro thread hai scritto: "Non è necessario associare il buffer per aggiornarlo con UpdateSubresource. In effetti, non è necessario vincolarlo quando lo si aggiorna". Questo significa che dovrei sempre separare tutti i buffer prima di aggiornarli? In tal caso, come posso separare un buffer?
NPS,

1
@NPS Prima di tutto, sarà implicitamente illimitato se hai già legato qualcos'altro al suo posto. Altrimenti, è possibile associare esplicitamente NULL per separare un buffer. Ad esempio, puoi fare ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);per separare una trama dallo slot 0.
Nathan Reed,

Conoscevo quello implicito ma avevo bisogno di quello esplicito, grazie. Ma non hai risposto alla mia prima domanda: devo farlo sempre per tutti i buffer che ho intenzione di aggiornare?
NPS,

1
@NPS Idealmente, il buffer non dovrebbe essere utilizzato dalla GPU al momento dell'aggiornamento sulla CPU. Ma la GPU e la CPU funzionano in modo asincrono, quindi non è facile da garantire. Direi di non preoccuparti a meno che non trovi che si tratta di un vero problema di prestazioni.
Nathan Reed,

2

Potrebbero essersi riferiti all'atto effettivo di aggiornamento di una risorsa e non alla chiamata di funzione effettiva. In generale, UpdateSubResource dovrebbe essere utilizzato per risorse predefinite che non sono soggette ad aggiornamenti frequenti (ovvero: non tutti i frame. In questo caso, è più probabile che il buffer possa essere copiato in un buffer temporaneo accessibile dal buffer dei comandi ( a causa delle condizioni di gara, ad esempio). Ti consentirà anche di aggiornare le risorse secondarie (ad esempio nelle trame).

Map / Unmap dovrebbe essere usato quando una risorsa verrà aggiornata molto frequentemente (ad esempio ogni frame), come alcuni buffer costanti. Il caso più comune è quando si sovrascrive l'intero buffer con WriteDiscard. C'è una presentazione nVidia in cui raccomandano questa pratica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.