Perubahan dari Direct3D 10

Bagian ini hanya berlaku untuk Windows 7 dan yang lebih baru, dan Windows Server 2008 R2 dan versi yang lebih baru dari sistem operasi Windows.

Bagian berikut menjelaskan bagaimana Direct3D 11 telah berubah dari Direct3D 10.

Fungsi Panggilan Balik Driver ke Layanan Kernel-Mode

Fungsi panggilan balik khusus perangkat yang disediakan runtime Direct3D versi 11 dalam struktur D3DDDI_DEVICECALLBACKS saat runtime memanggil fungsi CreateDevice (D3D10) driver tampilan pengguna mengisolasi driver dari handel kernel dan tanda tangan fungsi kernel. Runtime Direct3D versi 11 mengubah semantik panggilan balik dan, oleh karena itu, implementasi fungsi panggilan balik untuk mendukung mode operasi utas bebas, sedangkan runtime versi Direct3D sebelumnya tidak mendukung mode operasi alur bebas. Aturan untuk operasi mode alur bebas berlaku setelah driver menunjukkan bahwa ia mendukung mode utas bebas (D3D11DDICAPS_FREETHREADED); jika tidak, aturan yang sangat dibatasi sebelumnya berlaku. Untuk informasi tentang bagaimana driver menunjukkan dukungan untuk mode alur bebas, lihat Threading dan Daftar Perintah. Pembatasan berikut masih ada untuk Direct3D versi 11:

  • Hanya satu utas yang dapat bekerja melawan HCONTEXT pada satu waktu. Fungsi panggilan balik yang ada yang saat ini menggunakan HCONTEXT adalah pfnPresentCb, pfnRenderCb, pfnEscapeCb, pfnDestroyContextCb, pfnWaitForSynchronizationObjectCb, dan pfnSignalSynchronizationObjectCb. Oleh karena itu, jika lebih dari satu utas memanggil fungsi panggilan balik ini dan menggunakan HCONTEXT yang sama, driver harus menyinkronkan panggilan ke fungsi panggilan balik. Memenuhi persyaratan ini cukup alami karena fungsi panggilan balik ini kemungkinan hanya dipanggil dari utas yang memanipulasi konteks langsung.

  • Driver harus memanggil fungsi panggilan balik berikut hanya selama panggilan ke fungsi driver berikut dengan menggunakan utas yang sama yang disebut fungsi driver tersebut:

  • Fungsi panggilan balik pfnDeallocateCb layak disebutkan khusus karena driver tidak diperlukan untuk memanggil pfnDeallocateCb sebelum driver kembali dari fungsi DestroyResource (D3D10) untuk sebagian besar jenis sumber daya. Karena DestroyResource(D3D10) adalah fungsi free-threaded, driver harus menunda penghancuran objek sampai driver dapat secara efisien memastikan bahwa tidak ada referensi konteks langsung yang ada tetap ada (yaitu, driver harus memanggil pfnRenderCb sebelum pfnDeallocateCb). Pembatasan ini berlaku bahkan untuk sumber daya bersama atau ke fungsi panggilan balik lainnya yang menggunakan HRESOURCE untuk melengkapi penggunaan HRESOURCE dengan pfnAllocateCb. Namun, pembatasan ini tidak berlaku untuk utama. Untuk informasi selengkapnya tentang pengecualian utama, lihat Pengecualian Utama. Karena beberapa aplikasi mungkin memerlukan munculnya penghancuran sinkron, driver harus memastikan bahwa ia memanggil pfnDeallocateCb untuk sumber daya bersama yang sebelumnya dihancurkan selama panggilan ke fungsi Flush (D3D10). Driver juga harus membersihkan objek yang sebelumnya hancur (hanya yang tidak akan menyimpan alur) selama panggilan ke fungsi Flush (D3D10) -nya; driver harus melakukannya untuk memastikan bahwa runtime memanggil Flush (D3D10) sebagai mekanisme resmi untuk membersihkan objek yang ditangguhkan yang dihancurkan untuk beberapa aplikasi yang mungkin memerlukan mekanisme seperti itu. Untuk informasi selengkapnya tentang mekanisme ini, lihat Deferred Destruction and Flush(D3D10). Driver juga harus memastikan bahwa objek apa pun yang penghancurannya ditangguhkan sepenuhnya dihancurkan sebelum fungsi DestroyDevice (D3D10) driver kembali selama pembersihan.

Menghentikan Kemampuan untuk Memungkinkan Modifikasi DDI Free-Threaded

Untuk Direct3D versi 11, konsep tingkat API dari perangkat tampilan dan konteks langsung masih dibundel bersama di tingkat DDI dengan konsep warisan perangkat tampilan. Bundel perangkat tampilan dan konteks langsung ini memaksimalkan kompatibilitas dengan DDI versi sebelumnya (seperti, DDI Direct3D versi 10) dan mengurangi churn driver saat mendukung beberapa versi API melalui beberapa versi DDI. Namun, bundling perangkat tampilan dan konteks langsung ini menghasilkan DDI yang lebih membingungkan karena domain utas tidak terlalu eksplisit. Sebagai gantinya, untuk memahami persyaratan utas beberapa antarmuka dan fungsi dalam antarmuka tersebut, pengembang driver harus merujuk ke dokumentasi.

Fitur utama API Direct3D versi 11 adalah memungkinkan beberapa utas untuk memasukkan fungsi buat dan hancurkan secara bersamaan. Fitur seperti itu tidak kompatibel dengan memungkinkan driver menukar pointer tabel fungsi untuk membuat dan menghancurkan, karena semantik DDI Direct3D versi 10 untuk fungsi yang ditentukan dalam D3D10DDI_DEVICEFUNCS dan D3D10_1DDI_DEVICEFUNCS diizinkan. Oleh karena itu, setelah driver meneruskan kembali pointer fungsi untuk membuat (CreateDevice(D3D10)), driver tidak boleh mencoba mengubah perilaku dengan memodifikasi pointer fungsi tertentu ini ketika driver berjalan di bawah DDI Direct3D versi 11 dan sementara driver mendukung threading DDI. Pembatasan ini berlaku untuk semua fungsi perangkat yang dimulai dengan pfnCreate, pfnOpen, pfnDestroy, pfnCalcPrivate, dan pfnCheck. Semua fungsi perangkat lainnya sangat terkait dengan konteks langsung. Karena satu utas memanipulasi konteks langsung pada satu waktu, didefinisikan dengan baik untuk terus memungkinkan driver untuk melakukan hot-swap entri tabel fungsi konteks langsung.

pfnRenderCb Versus pfnPerformAmortizedProcessingCb

Fungsi API Direct3D versi 10 menghubungkan fungsi panggilan balik kernel pfnRenderCb runtime Direct3D untuk melakukan pemrosesan yang diamortisasi (yaitu, alih-alih menjalankan operasi tertentu untuk setiap panggilan fungsi API, driver melakukan operasi yang diamortisasi untuk setiap begitu banyak panggilan fungsi API). API biasanya menggunakan kesempatan ini untuk memangkas marka air tinggi dan membersihkan antrean penghancuran objek yang ditangguhkan, antara lain.

Untuk memungkinkan fungsi panggilan balik kernel sebebas mungkin untuk driver, API Direct3D tidak lagi menggunakan pfnRenderCb ketika driver mendukung DDI Direct3D versi 11. Oleh karena itu, driver yang mendukung DDI Direct3D versi 11 harus memanggil fungsi panggilan balik kernel pfnPerformAmortizedProcessingCb secara manual dari utas yang sama yang memasuki fungsi DDI driver setelah driver mengirimkan buffer perintah pada konteks langsung (atau frekuensi serupa). Karena operasi harus memangkas marka air tinggi, akan menguntungkan untuk melakukannya sebelum driver menghasilkan buffer perintah yang dapat dimulakan saat memanfaatkan fungsi panggilan balik DDI refresh status.

Selain itu, driver harus mengetahui masalah amortisasi API, dan mencoba menyeimbangkan seberapa sering ia menggunakan fungsi panggilan balik kernel pfnPerformAmortizedProcessingCb . Pada satu ekstrem, driver dapat menyebabkan pemrosesan berlebihan. Misalnya, jika driver selalu memanggil pfnPerformAmortizedProcessingCb dua kali (back-to-back), mungkin karena penggunaan beberapa mesin, akan lebih efisien bagi driver untuk memanggil pfnPerformAmortizedProcessingCb hanya sekali. Pada ekstrem lainnya, driver mungkin tidak mengizinkan API Direct3D untuk melakukan pekerjaan apa pun untuk seluruh bingkai jika driver tidak pernah memanggil pfnPerformAmortizedProcessingCb, mungkin karena desain penyajian bingkai alternatif. Driver tidak diperlukan untuk memanggil pfnPerformAmortizedProcessingCb lebih sering daripada biasanya, seperti yang berlebihan (misalnya, jika driver tidak memanggil pfnPerformAmortizedProcessingCb dalam jangka waktu 1 milidetik, harus saatnya untuk memompa API). Driver diperlukan untuk hanya menentukan mana dari panggilan pfnRenderCb yang ada yang harus disertai dengan pfnPerformAmortizedProcessingCb dan, secara alami, sesuai dengan semantik threading operasi.

Untuk driver yang mendukung daftar perintah, driver tersebut juga harus memanggil pfnPerformAmortizedProcessingCb dari konteks yang ditangguhkan setiap kali driver tersebut kehabisan ruang (frekuensi serupa seperti setiap flush konteks langsung). Runtime Direct3D versi 11 mengharapkan untuk, setidaknya, memangkas marka air tingginya selama operasi tersebut. Karena semantik utas yang terkait dengan pfnRenderCb telah dilonggarkan untuk Direct3D versi 11, masalah konkurensi harus diselesaikan untuk memungkinkan Direct3D versi 11 terus mengaitkan pfnRenderCb, tanpa batasan.

Kode Kesalahan DDI Baru

Kode kesalahan D3DDDIERR_APPLICATIONERROR dibuat untuk memungkinkan driver berpartisipasi dalam validasi di mana API Direct3D versi 11 tidak. Sebelumnya, jika driver mengembalikan kode kesalahan E_INVALIDARG, itu akan menyebabkan API menaikkan pengecualian. Kehadiran lapisan debug akan menyebabkan output penelusuran kesalahan dan menunjukkan bahwa driver telah mengembalikan kesalahan internal. Output penelusuran kesalahan akan menyarankan kepada pengembang bahwa driver memiliki bug. Jika driver mengembalikan D3DDDIERR_APPLICATIONERROR, lapisan debug menentukan bahwa aplikasi salah, sebagai gantinya.

Membutuhkan DDI Free-Threaded CalcPrivate secara retroaktif

Direct3D versi 11 secara retroaktif memerlukan fungsi driver yang dimulai dengan pfnCalcPrivate pada fungsi DDI Direct3D versi 10 untuk menjadi utas gratis. Persyaratan retroaktif ini cocok dengan perilaku DDI Direct3D versi 11 untuk selalu memerlukan fungsi pfnCalcPrivate* dan pfnCalcDeferredContextHandleSize untuk menjadi utas gratis meskipun driver menunjukkan tidak mendukung threading DDI. Untuk informasi selengkapnya tentang persyaratan retroaktif ini, lihat Mengharuskan DDI Free-Threaded CalcPrivate secara surut.

Penghancuran yang Ditangguhkan dan Siram D3D10

Karena semua fungsi penghancuran sekarang berulir bebas, runtime Direct3D tidak dapat membersihkan buffer perintah selama penghancuran. Oleh karena itu, fungsi penghancuran harus menunda penghancuran objek yang sebenarnya sampai driver dapat memastikan bahwa utas yang memanipulasi konteks langsung tidak lagi tergantung pada objek tersebut untuk bertahan hidup. Setiap metode konteks langsung diskrit tidak dapat secara efisien menggunakan sinkronisasi untuk menyelesaikan masalah penghancuran ini; oleh karena itu, driver harus menggunakan sinkronisasi hanya ketika menghapus buffer perintah. Runtime Direct3D juga menggunakan desain yang sama ini ketika harus berurusan dengan masalah serupa.

Karena ratifikasi penghancuran yang ditangguhkan, runtime Direct3D menganjurkan bahwa aplikasi yang tidak dapat mentolerir solusi penghancuran yang ditangguhkan sebagai gantinya menggunakan mekanisme eksplisit. Oleh karena itu, driver harus memproses antrean penghancuran yang ditangguhkan selama panggilan ke fungsi Flush (D3D10) (bahkan jika buffer perintah kosong) untuk memastikan bahwa mekanisme ini benar-benar berfungsi.

Aplikasi yang memerlukan bentuk penghancuran sinkron harus menggunakan salah satu pola berikut, tergantung pada seberapa berat penghancuran yang mereka butuhkan:

  • Setelah aplikasi memastikan bahwa semua dependensi pada objek tersebut dirilis (yaitu, daftar perintah, tampilan, middle ware, dan sebagainya), aplikasi menggunakan pola berikut:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush(); // Destroy all objects as quickly as possible.
    
  • Pola berikut adalah penghancuran yang lebih berat:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush();
    ImmediateContext::End( EventQuery );
    while( S_FALSE == ImmediateContext::GetData( EventQuery ) ) ;
    ImmediateContext::Flush(); // Destroy all objects, completely.
    

Pengecualian Utama

Utama adalah sumber daya yang dibuat runtime dalam panggilan ke fungsi CreateResource (D3D11) driver. Runtime membuat primer dengan mengatur anggota pPrimaryDesc dari struktur D3D11DDIARG_CREATERESOURCE ke penunjuk yang valid ke struktur DXGI_DDI_PRIMARY_DESC . Utama memiliki pengecualian penting berikut sehubungan dengan perubahan sebelumnya dari Direct3D 10 ke Direct3D 11:

  • Baik fungsi CreateResource (D3D11) dan DestroyResource (D3D10) driver untuk utamanya tidak berutas bebas, dan mereka berbagi domain utas konteks langsung. Konkurensi masih dapat ada dengan fungsi yang dimulai dengan pfnCreate dan pfnDestroy, yang mencakup CreateResource(D3D11) dan DestroyResource(D3D10). Namun, konkurensi tidak dapat ada dengan CreateResource(D3D11) dan DestroyResource(D3D10) untuk yang utama. Misalnya, driver dapat mendeteksi bahwa panggilan ke fungsi CreateResource (D3D11) atau DestroyResource (D3D10) adalah untuk primer, dan dengan demikian menentukan bahwa ia dapat dengan aman menggunakan atau menyentuh memori konteks langsung selama durasi panggilan fungsi.

  • Penghancuran utama tidak dapat ditangguhkan oleh runtime Direct3D, dan driver harus memanggil fungsi pfnDeallocateCb dengan tepat dalam panggilan ke fungsi DestroyResource (D3D10) driver.