Bagaimana cara menggunakan UpdateSubresource dan Map / Unmap?

8

Dari apa yang saya mengerti (dari membaca berbagai halaman) ada 2 cara untuk memperbarui buffer:

  1. UpdateSubresource()(saat buffer dibuat dengan DEFAULTpenggunaan)
  2. Map(), salin data baru, Unmap()(saat buffer dibuat dengan DYNAMICpenggunaan)

Dalam kasus pertama, apakah saya hanya memanggil fungsi yang satu ini (tidak lebih)? Karena saya pernah melihat orang mengatakan mereka memetakan buffer dan kemudian memperbarui sub-sumber daya, atau mungkin saya salah paham.

Apakah ada cara lain (ragu: P)? Apakah saya mengerti banyak hal dengan benar?

NPS
sumber

Jawaban:

11

Ada presentasi yang bagus tentang ini: Jangan Membuang Semuanya: Manajemen Buffer yang Efisien oleh John McDonald di NVIDIA. Ini mencakup berbagai topik, tetapi pada subjek pertanyaan Anda, saran umum adalah membuat buffer dengan penggunaan dinamis dan digunakan Map()bersama D3D11_MAP_WRITE_DISCARD, ketika data perlu sering diperbarui (seperti setiap frame, atau beberapa kali per frame). Ini akan digunakan untuk buffer konstan, buffer vertex untuk sistem partikel, dan sejenisnya.

Menurut presentasi, penggunaan default / UpdateSubresource()mengeluarkan lebih banyak overhead CPU daripada penggunaan dinamis / Map(). Namun, ia merekomendasikan penggunaan default / UpdateSubresource()untuk data yang perlu diperbarui hanya sesekali, seperti data yang dialirkan dari disk dalam gim dunia terbuka.

Dan ya, dalam kasus di mana Anda menggunakan UpdateSubresource(), Anda akan menggunakannya dengan sendirinya, tidak dalam kombinasi dengan Map().

Nathan Reed
sumber
2
Luar biasa, Anda berdua merespons pada menit yang sama dan memposting tautan yang sama.
NPS
Di utas lain Anda menulis: "Anda tidak perlu mengikat buffer untuk memperbaruinya dengan UpdateSubresource. Bahkan, tidak boleh terikat ketika Anda memperbaruinya". Apakah ini berarti saya harus selalu melepaskan ikatan semua buffer sebelum memperbarui mereka? Jika demikian, bagaimana cara melepaskan ikatan buffer?
NPS
1
@NPS Pertama-tama, itu akan secara implisit tidak mengikat jika Anda sudah mengikat sesuatu yang lain di tempatnya. Jika tidak, Anda dapat secara eksplisit mengikat NULL untuk melepaskan ikatan buffer. Misalnya, Anda dapat melakukan ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);untuk melepaskan ikatan tekstur dari slot 0.
Nathan Reed
Saya tahu tentang yang implisit tetapi membutuhkan yang eksplisit, thx. Tetapi Anda tidak menjawab pertanyaan pertama saya - apakah saya harus selalu melakukan ini untuk semua buffer yang ingin saya perbarui?
NPS
1
@NPS Idealnya, buffer tidak boleh digunakan oleh GPU pada saat Anda memperbaruinya di CPU. Tetapi GPU dan CPU berjalan secara tidak sinkron, jadi ini tidak mudah untuk dipastikan. Saya akan mengatakan jangan khawatir tentang hal itu kecuali jika Anda menemukan itu masalah kinerja yang sebenarnya.
Nathan Reed
2

Mereka mungkin merujuk pada tindakan aktual memperbarui sumber daya dan bukan untuk panggilan fungsi yang sebenarnya. Secara umum, UpdateSubResource harus digunakan untuk sumber daya default yang tidak sering dimutakhirkan (yaitu: tidak setiap frame. Dalam hal ini, kemungkinan buffer akan disalin ke buffer sementara yang dapat diakses dari buffer perintah ( karena kondisi ras misalnya) .Ini juga akan memungkinkan Anda memperbarui sub sumber daya (dalam tekstur, misalnya).

Peta / Unmap harus digunakan ketika sumber daya akan sangat sering diperbarui (yaitu setiap frame), seperti beberapa buffer konstan. Kasus yang paling umum adalah ketika Anda menimpa seluruh buffer dengan WriteDiscard. Ada presentasi nVidia di mana mereka merekomendasikan praktik ini.

Petualang
sumber