Bagikan melalui


Menggunakan handel DDI Context-Local

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.

Setiap objek (misalnya, sumber daya, shader, dan sebagainya) memiliki handel DDI konteks-lokal.

Misalkan objek digunakan dengan tiga konteks yang ditangguhkan. Dalam situasi ini, empat handel merujuk ke objek yang sama (satu handel untuk setiap konteks yang ditangguhkan dan handel lain untuk konteks segera). Karena setiap konteks dapat dimanipulasi oleh utas secara bersamaan, handel konteks-lokal memastikan bahwa beberapa utas CPU tidak bersaing dengan memori serupa (baik secara sengaja atau tidak sengaja). Handel konteks-lokal juga intuitif karena driver mungkin harus memodifikasi banyak data ini yang secara logis terkait per konteks (misalnya, objek mungkin terikat oleh konteks, dan sebagainya).

Masih ada perbedaan dari handel konteks langsung versus handel konteks yang ditangguhkan. Secara khusus, handel konteks langsung dijamin menjadi handel pertama yang dialokasikan dan handel terakhir yang dihancurkan. Handel konteks langsung yang sesuai disediakan selama "pembukaan" dari setiap handel konteks yang ditangguhkan untuk menautkannya bersama-sama. Saat ini tidak ada konsep objek yang memiliki handel DDI per perangkat (yaitu, handel yang dibuat sebelumnya dan dihancurkan setelah handel konteks langsung, dan hanya akan dirujuk dalam urutan berdasarkan pembuatan handel konteks).

Beberapa handel memiliki hubungan dependensi dengan handel lain (misalnya, tampilan memiliki dependensi pada sumber daya yang sesuai). Jaminan pengurutan pembuatan dan penghancuran yang ada untuk konteks langsung diperluas ke handel konteks yang ditangguhkan juga (yaitu, runtime membuat handel sumber daya konteks-lokal sebelum runtime membuat handel tampilan konteks-lokal apa pun ke sumber daya tersebut, dan runtime menghancurkan handel sumber daya konteks-lokal setelah runtime menghancurkan semua handel tampilan konteks-lokal ke sumber daya tersebut). Saat runtime membuat handel konteks-lokal, runtime juga menyediakan handel dependensi konteks-lokal yang sesuai.

Organisasi Data Driver

Ada beberapa kekhawatiran tentang organisasi data driver yang perlu diperhatikan. Seperti Direct3D versi 10, lokalitas data yang tepat dapat mengurangi kesalahan cache antara API dan driver. Lokalitas data yang tepat juga dapat mencegah pembatasan cache, yang terjadi ketika beberapa bagian data yang sering diakses semuanya diselesaikan ke indeks cache yang sama dan menghabiskan cache secara asosiatif. DDI telah dirancang sejak Direct3D versi 10 untuk membantu menghindari masalah tersebut dari manifes oleh driver yang memberi tahu API berapa banyak memori yang diperlukan driver untuk memenuhi handel dan API yang menetapkan nilai handel. Namun, masalah terkait utas baru berdampak pada desain DDI dalam jangka waktu Direct3D versi 11.

Secara alami, handel konteks-lokal menyediakan cara untuk mengaitkan data objek per konteks, yang menghindari masalah pertikaian antar utas. Namun, karena data tersebut direplikasi untuk setiap konteks yang ditangguhkan, ukuran data tersebut menjadi perhatian utama. Hal ini memberikan rasionalisasi alami untuk berbagi data baca-saja antara handel konteks langsung dan handel konteks yang ditangguhkan. Selama pembuatan handel konteks yang ditangguhkan, handel konteks langsung disediakan untuk membangun koneksi antar handel. Namun, data apa pun yang terletak di luar handel konteks yang ditangguhkan mendapatkan manfaat lokalitas dengan data API, dan tingkat tidak langsung tambahan ke data baca-saja mencegah manfaat lokalitas meluas ke data baca-saja. Beberapa data baca-saja dapat direplikasi ke setiap wilayah handel konteks jika manfaat lokalitas membenarkan duplikasi data. Namun, memori yang mendukung setiap handel konteks yang ditangguhkan harus dipertimbangkan pada premium seperti itu sehingga mungkin ada baiknya untuk merelokasi data yang tidak berdekatan dari handel jika data tersebut relatif besar dan tidak diakses sesering data lain. Idealnya, jenis data yang terkait dengan setiap handel konteks yang ditangguhkan akan menjadi semua data frekuensi tinggi; oleh karena itu, data tidak akan cukup besar untuk mempertimbangkan relokasi yang diperlukan. Tentu saja, pengemudi harus menyeimbangkan motivasi yang bertentangan ini.

Untuk membuat desain data driver kompatibel secara efisien dengan Direct3D versi 10, namun tidak berbeda dalam implementasi, data baca-saja harus terletak berdekatan (tetapi masih dipisahkan dari dan sesudah) konteks langsung menangani data. Jika driver menggunakan desain ini, driver harus menyadari bahwa padding baris cache diperlukan antara data handel konteks langsung dan data baca-saja. Karena utas mungkin sering memanipulasi setiap konteks menangani data (jika tidak secara bersamaan), penalti berbagi palsu terjadi antara konteks langsung menangani data dan konteks yang ditangguhkan menangani data jika padding baris cache tidak digunakan. Desain driver harus kognizan dengan penalti berbagi palsu yang bermanifestasi jika pointer ditetapkan dan dilalui secara teratur antara konteks menangani wilayah memori.

Runtime Direct3D menggunakan DDI Direct3D 11 berikut untuk handel lokal konteks yang ditangguhkan:

Agar runtime Direct3D mengambil ukuran handel konteks yang ditangguhkan yang diperlukan oleh driver, fungsi DDI sebelumnya harus digunakan. Segera setelah pembuatan objek untuk konteks langsung, runtime memanggil CalcDeferredContextHandleSize untuk meminta driver untuk jumlah ruang penyimpanan yang diperlukan driver untuk memenuhi handel konteks yang ditangguhkan ke objek ini. Namun, API Direct3D harus menyempurnakan alokator memori CLS-nya dengan menentukan berapa banyak ukuran handel unik dan nilainya yang diakses; runtime memanggil fungsi CheckDeferredContextHandleSizes driver untuk mendapatkan informasi ini. Oleh karena itu, selama instansiasi perangkat, API meminta array ukuran handel konteks yang ditangguhkan dengan polling ganda. Polling pertama adalah meminta berapa banyak ukuran yang dikembalikan, sementara polling kedua lolos dalam array untuk mengambil nilai setiap ukuran. Driver harus menunjukkan berapa banyak memori yang diperlukan untuk memenuhi handel bersama dengan jenis handel mana. Driver dapat mengembalikan beberapa ukuran yang terkait dengan jenis handel tertentu. Namun, tidak terdefinisi bagi driver untuk pernah mengembalikan nilai dari CalcDeferredContextHandleSize yang tidak juga dikembalikan secara sesuai dalam array CheckDeferredContextHandleSizes .

Adapun untuk membuat handel DDI, metode buat pada konteks yang ditangguhkan digunakan. Misalnya, periksa fungsi CreateBlendState(D3D10_1) dan DestroyBlendState . HDEVICE secara alami menunjuk ke konteks yang ditangguhkan yang sesuai (versus konteks langsung); penunjuk struktur CONST lainnya adalah NULL (dengan asumsi objek tidak memiliki dependensi); dan, handel D3D10DDI_HRT* adalah handel D3D10DDI_H* ke objek konteks langsung yang sesuai.

Untuk objek yang memiliki dependensi (misalnya, tampilan memiliki hubungan dependensi pada sumber daya yang sesuai), penunjuk struktur yang menyediakan handel dependensi bukan NULL. Namun, satu-satunya anggota struktur yang valid adalah handel dependensi; sedangkan, anggota lainnya diisi dengan nol. Sebagai contoh, penunjuk D3D11DDIARG_CREATESHADERRESOURCEVIEW dalam panggilan ke fungsi CreateShaderResourceView (D3D11) driver tidak akan NULL ketika runtime memanggil fungsi ini pada konteks yang ditangguhkan. Dalam panggilan CreateShaderResourceView (D3D11) ini, runtime menetapkan handel konteks-lokal yang sesuai untuk sumber daya ke anggota D3D11DDIARG_CREATESHADERRESOURCEVIEW hDrvResource . Anggota D3D11DDIARG_CREATESHADERRESOURCEVIEW lainnya, diisi dengan nol.

Contoh kode berikut menunjukkan bagaimana runtime Direct3D menerjemahkan permintaan pembuatan aplikasi dan penggunaan pertama konteks yang ditangguhkan untuk memanggil driver tampilan mode pengguna untuk membuat konteks langsung versus ditangguhkan. Panggilan aplikasi ke ID3D11Device::CreateTexture2D memulai kode runtime di bagian "Resource Create" berikut. Panggilan aplikasi ke ID3D11Device::CopyResource memulai kode runtime di bagian "Penggunaan Sumber Daya Konteks Yang Ditangguhkan" berikut.

// Device Create
 IC::pfnCheckDeferredContextHandleSizes( hIC, &u, NULL );
pArray = malloc( u * ... );
IC::pfnCheckDeferredContextHandleSizes( hIC, &u, pArray );

// Resource Create
 s = IC::pfnCalcPrivateResourceSize( hIC, &Args );
pICRHandle = malloc( s );
 IC::pfnCreateResource( hIC, &Args, pICRHandle, hRTResource );
 s2 = IC::pfnCalcDeferredContextHandleSize( hIC, D3D10DDI_HT_RESOURCE, pICRHandle );

// Deferred Context Resource Usage
pDCRHandle = malloc( s2 );
 DC::pfnCreateResource( hDC, NULL, pDCRHandle, pICRHandle );

Masalah dengan pfnSetErrorCb

Tidak ada fungsi buat yang mengembalikan kode kesalahan, yang akan sangat ideal untuk model utas Direct3D versi 11. Semua fungsi buat menggunakan pfnSetErrorCb untuk mengambil kode kesalahan kembali dari driver. Untuk memaksimalkan kompatibilitas dengan model driver Direct3D versi 10, fungsi buat DDI baru yang mengembalikan kode kesalahan tidak diperkenalkan. Sebagai gantinya, driver harus terus menggunakan perangkat terpadu/konteks langsung D3D10DDI_HRTCORELAYER menangani dengan pfnSetErrorCb selama fungsi pembuatan. Ketika driver mendukung daftar perintah, driver harus menggunakan pfnSetErrorCb yang sesuai yang terkait dengan konteks yang sesuai. Artinya, kesalahan konteks yang ditangguhkan harus masuk ke panggilan konteks tertentu yang ditangguhkan ke pfnSetErrorCb dengan handel yang sesuai, dan sebagainya.

Konteks yang ditangguhkan dapat mengembalikan E_OUTOFMEMORY melalui panggilan ke pfnSetErrorCb dari fungsi DDI yang sebelumnya hanya mengizinkan D3DDDIERR_DEVICEREMOVED (seperti Draw, SetBlendState, dan sebagainya), karena tuntutan memori konteks yang ditangguhkan terus tumbuh dengan setiap panggilan ke fungsi DDI. API Direct3D memicu penghapusan konteks lokal, untuk membantu driver dengan kasus kegagalan seperti itu, yang secara efektif membuang daftar perintah yang dibuat sebagian. Aplikasi terus menentukan bahwa aplikasi merekam daftar perintah; namun, ketika aplikasi akhirnya memanggil fungsi FinishCommandList , FinishCommandList mengembalikan kode kegagalan E_OUTOFMEMORY.