Menyalin dan Mengakses Data Sumber Daya (Direct3D 10)

Tidak perlu lagi memikirkan sumber daya sebagai dibuat dalam memori video atau memori sistem. Atau apakah runtime harus mengelola memori atau tidak. Berkat arsitektur WDDM (Windows Display Driver Model) baru, aplikasi sekarang membuat sumber daya Direct3D 10 dengan bendera penggunaan yang berbeda untuk menunjukkan bagaimana aplikasi berniat menggunakan data sumber daya. Model driver baru memvirtualisasikan memori yang digunakan oleh sumber daya; kemudian menjadi tanggung jawab sistem operasi /driver/manajer memori untuk menempatkan sumber daya di area memori yang paling berkinerja mungkin mengingat penggunaan yang diharapkan.

Kasus default adalah agar sumber daya tersedia untuk GPU. Tentu saja, setelah mengatakan itu, ada kalanya data sumber daya perlu tersedia untuk CPU. Menyalin data sumber daya di sekitar sehingga prosesor yang sesuai dapat mengaksesnya tanpa memengaruhi performa memerlukan beberapa pengetahuan tentang cara kerja metode API.

Menyalin Data Sumber Daya

Sumber daya dibuat dalam memori saat Direct3D menjalankan panggilan Buat. Mereka dapat dibuat dalam memori video, memori sistem, atau jenis memori lainnya. Karena model driver WDDM memvirtualisasikan memori ini, aplikasi tidak perlu lagi melacak jenis sumber daya memori apa yang dibuat.

Idealnya, semua sumber daya akan terletak di memori video sehingga GPU dapat segera mengaksesnya. Namun, terkadang perlu bagi CPU untuk membaca data sumber daya atau agar GPU dapat mengakses data sumber daya yang telah ditulis CPU. Direct3D 10 menangani skenario yang berbeda ini dengan meminta aplikasi menentukan penggunaan, lalu menawarkan beberapa metode untuk menyalin data sumber daya bila perlu.

Bergantung pada bagaimana sumber daya dibuat, tidak selalu mungkin untuk langsung mengakses data yang mendasar. Ini mungkin berarti bahwa data sumber daya harus disalin dari sumber daya sumber ke sumber daya lain yang dapat diakses oleh prosesor yang sesuai. Dalam hal Direct3D 10, sumber daya default dapat diakses langsung oleh GPU, sumber daya dinamis dan penahapan dapat langsung diakses oleh CPU.

Setelah sumber daya dibuat, penggunaannya tidak dapat diubah. Sebagai gantinya, salin konten satu sumber daya ke sumber daya lain yang dibuat dengan penggunaan yang berbeda. Direct3D 10 menyediakan fungsionalitas ini dengan tiga metode yang berbeda. Dua metode pertama( ID3D10Device::CopyResource dan ID3D10Device::CopySubresourceRegion) dirancang untuk menyalin data sumber daya dari satu sumber daya ke sumber daya lainnya. Metode ketiga (ID3D10Device::UpdateSubresource) dirancang untuk menyalin data dari memori ke sumber daya.

Ada dua jenis sumber daya utama: dapat dipetakan dan tidak dapat dipetakan. Sumber daya yang dibuat dengan penggunaan dinamis atau penahapan dapat dipetakan, sementara sumber daya yang dibuat dengan penggunaan default atau tidak dapat diubah tidak dapat dipetakan.

Menyalin data di antara sumber daya yang tidak dapat dipetakan sangat cepat karena ini adalah kasus yang paling umum dan telah dioptimalkan untuk berperforma baik. Karena sumber daya ini tidak dapat diakses secara langsung oleh CPU, sumber daya tersebut dioptimalkan sehingga GPU dapat memanipulasinya dengan cepat.

Menyalin data di antara sumber daya yang dapat dipetakan lebih bermasalah karena performa akan bergantung pada penggunaan yang dibuat dengan sumber daya. Misalnya, GPU dapat membaca sumber daya dinamis dengan cukup cepat tetapi tidak dapat menulis kepada mereka, dan GPU tidak dapat membaca atau menulis ke sumber daya penahapan secara langsung.

Aplikasi yang ingin menyalin data dari sumber daya dengan penggunaan default ke sumber daya dengan penggunaan penahapan (untuk memungkinkan CPU membaca data -- yaitu masalah readback GPU) harus melakukannya dengan hati-hati. Lihat Mengakses Data Sumber Daya untuk detail selengkapnya tentang kasus terakhir ini.

Mengakses Data Sumber Daya

Mengakses sumber daya memerlukan pemetaan sumber daya; pemetaan pada dasarnya berarti aplikasi mencoba memberikan akses CPU ke memori. Proses pemetaan sumber daya sehingga CPU dapat mengakses memori yang mendasar dapat menyebabkan beberapa hambatan performa dan karena alasan ini, perawatan harus diambil tentang bagaimana dan kapan melakukan tugas ini.

Performa dapat dihentikan jika aplikasi mencoba memetakan sumber daya pada waktu yang salah. Jika aplikasi mencoba mengakses hasil operasi sebelum operasi tersebut selesai, stall alur akan terjadi.

Melakukan operasi peta pada waktu yang salah berpotensi menyebabkan penurunan performa yang parah dengan memaksa GPU dan CPU untuk disinkronkan satu sama lain. Sinkronisasi ini akan terjadi jika aplikasi ingin mengakses sumber daya sebelum GPU selesai menyalinnya ke sumber daya yang dapat dipetakan CPU.

CPU hanya dapat membaca dari sumber daya yang dibuat dengan bendera D3D10_USAGE_STAGING. Karena sumber daya yang dibuat dengan bendera ini tidak dapat ditetapkan sebagai output alur, jika CPU ingin membaca data dalam sumber daya yang dihasilkan oleh GPU, data harus disalin ke sumber daya yang dibuat dengan bendera penahapan. Aplikasi dapat melakukan ini dengan menggunakan metode ID3D10Device::CopyResource atau ID3D10Device::CopySubresourceRegion untuk menyalin konten satu sumber daya ke sumber daya lainnya. Aplikasi kemudian dapat memperoleh akses ke sumber daya ini dengan memanggil metode Peta yang sesuai. Ketika akses ke sumber daya tidak lagi diperlukan, aplikasi kemudian harus memanggil metode Unmap yang sesuai. Misalnya, ID3D10Texture2D::Map dan ID3D10Texture2D::Unmap. Metode Peta yang berbeda mengembalikan beberapa nilai tertentu tergantung pada bendera input. Lihat bagian Keterangan Peta untuk detailnya.

Catatan

Ketika aplikasi memanggil metode Peta, aplikasi menerima penunjuk ke data sumber daya untuk diakses. Runtime memastikan bahwa penunjuk memiliki perataan tertentu, tergantung pada tingkat fitur. Untuk D3D_FEATURE_LEVEL_10_0 dan yang lebih tinggi, penunjuk diselaraskan ke 16 byte. Untuk lebih rendah dari D3D_FEATURE_LEVEL_10_0, penunjuk diratakan ke 4 byte. Penyelarasan 16 byte memungkinkan aplikasi untuk melakukan operasi yang dioptimalkan SSE pada data secara asli, tanpa perataan nyata atau salinan.

 

Pertimbangan Performa

Yang terbaik adalah menganggap PC sebagai mesin yang berjalan sebagai arsitektur paralel dengan dua jenis prosesor utama: satu atau beberapa CPU dan satu atau beberapa GPU. Seperti dalam arsitektur paralel apa pun, performa terbaik dicapai ketika setiap prosesor dijadwalkan dengan tugas yang cukup untuk mencegahnya menganggur dan ketika pekerjaan satu prosesor tidak menunggu pekerjaan orang lain.

Skenario terburuk untuk paralelisme GPU/CPU adalah kebutuhan untuk memaksa satu prosesor menunggu hasil pekerjaan yang dilakukan oleh prosesor lain. Direct3D 10 mencoba menghapus biaya ini dengan membuat metode ID3D10Device::CopyResource dan ID3D10Device::CopySubresourceRegion tidak sinkron; salinan belum tentu dijalankan pada saat metode kembali. Manfaat dari ini adalah bahwa aplikasi tidak membayar biaya performa benar-benar menyalin data sampai CPU mengakses data, yaitu ketika Peta dipanggil. Jika metode Peta dipanggil setelah data benar-benar disalin, tidak ada kehilangan performa yang terjadi. Di sisi lain, jika metode Peta dipanggil sebelum data disalin, maka kios alur akan terjadi.

Panggilan asinkron di Direct3D 10 (yang merupakan sebagian besar metode, dan terutama panggilan penyajian) disimpan dalam apa yang disebut buffer perintah. Buffer ini internal untuk driver grafis dan digunakan untuk melakukan batch panggilan ke perangkat keras yang mendasar sehingga peralihan mahal dari mode pengguna ke mode kernel di Microsoft Windows terjadi jarang mungkin.

Buffer perintah dibersihkan, sehingga menyebabkan pengalihan mode pengguna/kernel, dalam salah satu dari empat situasi, yaitu sebagai berikut.

  1. Hadir dipanggil.
  2. ID3D10Device::Flush dipanggil.
  3. Buffer perintah penuh; ukurannya dinamis dan dikendalikan oleh Sistem Operasi dan driver grafis.
  4. CPU memerlukan akses ke hasil perintah yang menunggu untuk dijalankan di buffer perintah.

Dari empat situasi di atas, nomor empat adalah yang paling penting untuk performa. Jika aplikasi mengeluarkan panggilan ID3D10Device::CopyResource atau ID3D10Device::CopySubresourceRegion , panggilan ini diantrekan di buffer perintah. Jika aplikasi kemudian mencoba memetakan sumber daya penahapan yang merupakan target panggilan salin sebelum buffer perintah telah dibersihkan, stall alur akan terjadi karena tidak hanya panggilan metode Salin yang perlu dijalankan, tetapi semua perintah buffer lainnya di buffer perintah juga harus dijalankan. Ini akan menyebabkan GPU dan CPU disinkronkan karena CPU akan menunggu untuk mengakses sumber daya penahapan saat GPU mengosongkan buffer perintah dan akhirnya mengisi sumber daya yang dibutuhkan CPU. Setelah GPU menyelesaikan salinan, CPU akan mulai mengakses sumber daya penahapan, tetapi selama waktu ini, GPU akan duduk diam.

Melakukan ini sering pada runtime akan sangat menurunkan performa. Untuk alasan itu, pemetaan sumber daya yang dibuat dengan penggunaan default harus dilakukan dengan hati-hati. Aplikasi perlu menunggu cukup lama agar buffer perintah dikosongkan dan dengan demikian semua perintah tersebut selesai dijalankan sebelum mencoba memetakan sumber daya penahapan yang sesuai. Berapa lama aplikasi harus menunggu? Setidaknya dua bingkai karena ini akan memungkinkan paralelisme antara CPU dan GPU untuk dimanfaatkan secara maksimal. Cara kerja GPU adalah bahwa saat aplikasi memproses bingkai N dengan mengirimkan panggilan ke buffer perintah, GPU sibuk menjalankan panggilan dari bingkai sebelumnya, N-1.

Jadi, jika aplikasi ingin memetakan sumber daya yang berasal dari memori video dan memanggil ID3D10Device::CopyResource atau ID3D10Device::CopySubresourceRegion di frame N, panggilan ini sebenarnya akan mulai dijalankan pada bingkai N+1, ketika aplikasi mengirimkan panggilan untuk bingkai berikutnya. Salinan harus selesai ketika aplikasi memproses bingkai N+2.

Bingkai GPU/CPU Status
N
  • Masalah CPU merender panggilan untuk bingkai saat ini.
N+1
  • GPU menjalankan panggilan yang dikirim dari CPU selama bingkai N.
  • Masalah CPU merender panggilan untuk bingkai saat ini.
N+2
  • GPU selesai mengeksekusi panggilan yang dikirim dari CPU selama bingkai N. Hasil siap.
  • GPU menjalankan panggilan yang dikirim dari CPU selama bingkai N+1.
  • Masalah CPU merender panggilan untuk bingkai saat ini.
N+3
  • GPU selesai menjalankan panggilan yang dikirim dari CPU selama bingkai N+1. Hasil siap.
  • GPU menjalankan panggilan yang dikirim dari CPU selama bingkai N+2.
  • Masalah CPU merender panggilan untuk bingkai saat ini.
N+4 ...

 

Sumber daya (Direct3D 10)