DXGKDDI_BUILDPAGINGBUFFER Rückruffunktion (d3dkmddi.h)
Die DxgkDdiBuildPagingBuffer Funktion erstellt Pagingpuffer für Speichervorgänge.
Syntax
DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;
NTSTATUS DxgkddiBuildpagingbuffer(
[in] IN_CONST_HANDLE hAdapter,
[in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}
Parameter
[in] hAdapter
Ein Handle zu einem Kontextblock, der einem Anzeigeadapter zugeordnet ist. Der Display-Miniporttreiber, der zuvor dieses Handle für das Microsoft DirectX-Grafikkernsubsystem im MiniportDeviceContext Ausgabeparameter des DxgkDdiAddDevice--Funktion bereitgestellt hat.
[in/out] pBuildPagingBuffer
Ein Zeiger auf eine DXGKARG_BUILDPAGINGBUFFER Struktur, die Informationen zum Erstellen eines Pagingpuffers enthält.
Rückgabewert
DxgkDdiBuildPagingBuffer gibt einen der folgenden Werte zurück:
Rückgabecode | Beschreibung |
---|---|
STATUS_SUCCESS | DxgkDdiBuildPagingBuffersuccessful built a paging buffer. |
STATUS_GRAPHICS_ALLOCATION_BUSY | Die GPU verwendet derzeit die Zuordnung für den Pagingpuffer. |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | Mehr Platz ist im Pagingpuffer erforderlich (d. h. im pDmaBuffer-Element der DXGKARG_BUILDPAGINGBUFFER Struktur, auf die der pBuildPagingBuffer-Parameter verweist). |
Bemerkungen
Die DxgkDdiBuildPagingBuffer--Funktion wird aufgerufen, um spezielle DMA-Puffer (Direct Memory Access) zu erstellen, die als Pagingpufferbezeichnet werden. Ein Pagingpuffer enthält einen Vorgang, der den Inhalt von Teilen der Zuordnungen verschiebt:
- Innerhalb eines Segments einer Zuordnung.
- Zwischen Segmenten der Zuordnungen.
- Von einem Segment einer Zuordnung zum Systemspeicher.
- Vom Systemspeicher bis zu einem Segment einer Zuordnung.
Der Anzeige-Miniporttreiber muss die entsprechende GPU-Anweisung (Grafikverarbeitungseinheit) in den bereitgestellten Pagingpuffer (im pDmaBuffer Member von DXGKARG_BUILDPAGINGBUFFER) gemäß dem angeforderten Pagingvorgang schreiben; und dann muss der Treiber den Auslagerungspuffer wieder an den Videospeicher-Manager zurückgeben (der Teil von Dxgkrnl.sysist). Der GPU-Scheduler (der auch Teil von Dxgkrnl.sysist) ruft anschließend die DxgkDdiSubmitCommand-Funktion des Treibers auf, um anzufordern, dass der Treiber den Pagingpuffer als regulärer DMA-Puffer an die GPU sendet.
Wenn DxgkDdiBuildPagingBuffer bestimmt, dass ein Auslagerungsvorgang mehr als einen Pagingpuffer erfordert, kann der Treiber Informationen im MultipassOffset Member von DXGKARG_BUILDPAGINGBUFFER angeben und diese Informationen über mehrere Iterationen des Pagingvorgangs hinweg verwenden. Der Videospeicher-Manager initialisiert die Informationen in MultipassOffset auf Null vor der ersten Anforderung des Auslagerungsvorgangs und ändert die Informationen in MultipassOffset- zwischen Iterationen nicht. Daher kann der Treiber MultipassOffset- verwenden, um den Fortschritt zwischen Iterationen zu speichern. Beispielsweise kann der Treiber die Seitennummer speichern, die zuletzt für eine seitenbasierte Übertragung übertragen wurde.
Ein Auslagerungspuffer wird derzeit für die folgenden Arten von Vorgängen erstellt:
-
Übertragung
Der Übertragungsvorgang verschiebt den Inhalt einer Zuordnung von einem Ort in einen anderen. Dieser Vorgang ist der am häufigsten verwendete Speichervorgangstyp.
Eine Zuordnung wird immer vollständig von einem Standort an einen anderen übertragen. Aufgrund von Speichereinschränkungen kann die Übertragung einer Zuordnung jedoch in mehrere Unterübertragungen unterteilt werden (d. r. ein Teil der Zuordnung wird von Standort A nach B verschoben, und dann wird der folgende Teil verschoben usw., bis die gesamte Zuordnung übertragen wird). Die erste Teilübertragung einer Zuordnung wird mit der TransferStart- Bitfeldkennzeichnung im Flags Mitglied der Transfer DXGKARG_BUILDPAGINGBUFFER gekennzeichnet; die letzte Teilübertragung einer Zuordnung mit der TransferEnd Bitfeldflagge gekennzeichnet ist. Der Treiber erhält garantiert das Ende einer ausstehenden Übertragung (d. h. die letzte Unterübertragung), bevor der Fahrer den Beginn einer neuen Übertragung erhält.
Für jede Unterübertragung müssen möglicherweise mehrere Aufrufe an DxgkDdiBuildPagingBuffer abgeschlossen werden (z. B. kann der Treiber nicht mehr über den DMA-Pufferspeicher verfügen). Daher empfängt der Treiber möglicherweise das TransferStart- Flag in mehreren Aufrufen von DxgkDdiBuildPagingBuffer, bis der Treiber das flag TransferEnd in einem Aufruf von DxgkDdiBuildPagingBufferempfängt. Das Empfangen des TransferStart- Flags weist mehrmals nicht auf den Beginn mehrerer neuer Übertragungen hin; sie gibt an, dass die Unterübertragungen für die Zuordnung mehrere Iterationen erfordern (z. B. wenn der Treiber nicht mehr genügend DMA-Pufferspeicher hat). Der Treiber kann das MultipassOffset Mitglied von DXGKARG_BUILDPAGINGBUFFER verwenden, um den Fortschritt für eine bestimmte Unterübertragung über mehrere Iterationen von DxgkDdiBuildPagingBuffernachzuverfolgen.
In der Regel erfolgt eine Übertragung in einem einzigen Vorgang. In diesem Fall werden sowohl die TransferStart- als auch TransferEnd- Bitfeldkennzeichnungen festgelegt.
In einigen Szenarien ist der Treiber möglicherweise erforderlich, um Hardwareressourcen einzurichten, wenn bestimmte Zuordnungen in oder außerhalb des Arbeitsspeichers ausgelagert werden. Standardmäßig verwendet die GPU möglicherweise die Zuordnung, auf die während des Aufrufs von DxgkDdiBuildPagingBufferverwiesen wird. In diesen Szenarien muss der Treiber möglicherweise leer sein, bevor die erforderlichen Hardwareressourcen vom Treiber programmiert werden (d. a. die Programmierung der Hardwareressourcen kann nicht im bereitgestellten DMA-Puffer in die Warteschlange gestellt werden). In solchen Szenarien kann der Treiber den Aufruf von DxgkDdiBuildPagingBuffer mit STATUS_GRAPHICS_ALLOCATION_BUSY fehlschlagen.
Wenn der Treiber STATUS_GRAPHICS_ALLOCATION_BUSY zurückgibt, wartet der Videospeicher-Manager, bis die GPU mit einem Verweis auf die aktuelle Zuordnung abgeschlossen ist, und ruft dann die DxgkDdiBuildPagingBuffer Funktion erneut auf. Im zweiten Aufruf von DxgkDdiBuildPagingBufferlegt der Videospeicher-Manager die AllocationIsIdle- Bitfeldkennzeichnung im Flags Member des Transfer Member von DXGKARG_BUILDPAGINGBUFFER fest, um anzugeben, dass die zuordnung, auf die verwiesen wird, im Leerlauf ist. Wenn das Leerlaufflagge nicht festgelegt ist, sollte der Treiber immer feststellen, dass die Zuordnung aktuell ausgelastet ist oder bald ausgelastet wird. Wenn das Leerlaufflagge festgelegt ist, garantiert der Videospeicher-Manager, dass die zuordnung, auf die verwiesen wird, für die Dauer des Aufrufs an DxgkDdiBuildPagingBufferim Leerlauf bleibt.
Wenn das hAllocation- Mitglied von DXGKARG_BUILDPAGINGBUFFER NULL-ist, sollte der Treiber die Daten in der Quelle an das Ziel kopieren, ohne eine Schwarm- oder Tilung durchzuführen.
-
Füllen
Der Füllvorgang füllt eine Zuordnung mit einem angegebenen Muster aus. Der Füllvorgang wird verwendet, um den anfänglichen Inhalt einer Zuordnung einzurichten. Wenn der Inhalt der Zuordnung ausgefüllt wird, ist die Zuordnung garantiert im Leerlauf (d. a. nicht von der GPU verwendet). Der Füllvorgang kann nur für ein Speichersegment ausgeführt werden. Der Videospeicher-Manager fordert niemals an, dass der Display-Miniporttreiber ein Blendensegment füllt.
-
Inhalt verwerfen
Der Verwerfen-Inhaltsvorgang benachrichtigt den Treiber, dass eine Zuordnung vom aktuellen Speicherort der Zuordnung in einem Speichersegment verworfen wird. Das heißt, die Zuordnung wird räumt und nicht wieder in den Systemspeicher kopiert.
In einigen Szenarien ist der Treiber möglicherweise erforderlich, um Hardwareressourcen einzurichten, wenn bestimmte Zuordnungen in oder außerhalb des Arbeitsspeichers ausgelagert werden. Standardmäßig verwendet die GPU möglicherweise die Zuordnung, auf die während des Aufrufs von DxgkDdiBuildPagingBufferverwiesen wird. In diesen Szenarien muss der Treiber möglicherweise leer sein, bevor die erforderlichen Hardwareressourcen vom Treiber programmiert werden (d. a. die Programmierung der Hardwareressourcen kann nicht im bereitgestellten DMA-Puffer in die Warteschlange gestellt werden). In solchen Szenarien kann der Treiber den Aufruf von DxgkDdiBuildPagingBuffer mit STATUS_GRAPHICS_ALLOCATION_BUSY fehlschlagen.
Wenn der Treiber STATUS_GRAPHICS_ALLOCATION_BUSY zurückgibt, wartet der Videospeicher-Manager, bis die GPU mit einem Verweis auf die aktuelle Zuordnung abgeschlossen ist, und ruft dann die DxgkDdiBuildPagingBuffer Funktion erneut auf. Im zweiten Aufruf von DxgkDdiBuildPagingBufferlegt der Videospeicher-Manager das AllocationIsIdle- Bitfeld-Flag im Flags Member des DiscardContent Member der DXGKARG_BUILDPAGINGBUFFER Struktur fest, um anzugeben, dass die zuordnung, auf die verwiesen wird, im Leerlauf ist. Wenn das Leerlaufflagge nicht festgelegt ist, sollte der Treiber immer feststellen, dass die Zuordnung aktuell ausgelastet ist oder bald ausgelastet wird. Wenn das Leerlaufflagge festgelegt ist, garantiert der Videospeicher-Manager, dass die zuordnung, auf die verwiesen wird, für die Dauer des Aufrufs an DxgkDdiBuildPagingBufferim Leerlauf bleibt.
-
Physisches Lesen
Der read-physical-Vorgang liest aus einer angegebenen physischen Speicheradresse. Der Treiber wird aufgefordert, die GPU für den Vorgang zu programmieren. Die Größe des physischen Speichers für den Zugriff auf den Lesevorgang kann zwischen 1 Byte und 8 Bytes betragen. Da die gelesenen Daten irrelevant sind, ist DxgkDdiBuildPagingBuffer nicht erforderlich, um die Daten zurückzugeben. In Szenarien, in denen die CPU versucht, den AGP-Speicher zu lesen, nachdem die GPU in diesen AGP-Speicher geschrieben hat, ist der schreibgeschützte physische Vorgang wichtig, um die Speicherkohärenz sicherzustellen.
-
Physisches Schreiben
Der schreibgeschützte physische Vorgang schreibt in eine angegebene physische Adresse. Der Treiber wird aufgefordert, die GPU für den Vorgang zu programmieren. Die Größe des physischen Speichers für den Schreibvorgang kann zwischen 1 Byte und 8 Bytes betragen. Da die geschriebenen Daten irrelevant sind, können DxgkDdiBuildPagingBuffer- beliebige Daten in den Speicher schreiben. In Szenarien, in denen die CPU versucht, aus AGP-Speicher zu lesen, nachdem die GPU in diesen AGP-Speicher schreibt, ist der schreibgeschützte physische Vorgang jedoch wichtig, um die Speicherkohärenz sicherzustellen.
-
Karten-Blendensegment
Der Karten-Blendensegment-Vorgang ordnet eine angegebene Speicherdeskriptorliste (MDL) einem angegebenen Blendensegment bei einem angegebenen Segmentoffset für eine bestimmte Anzahl von Seiten zu. Wenn das CacheCoherent- Bitfeld-Flag im Flags Mitglied des MapApertureSegment Member der DXGKARG_BUILDPAGINGBUFFER-Struktur festgelegt ist, muss der Treiber sicherstellen, dass die Cachekohärenz auf den zugeordneten Seiten erzwungen wird; andernfalls ist die Cachekohärenz für die zugeordneten Seiten nicht erforderlich.
Hinweis Das CacheCoherent- Bitfeld-Flag wird nur festgelegt, wenn zwischengespeicherter Speicher in einem cache-kohärenten Blendensegment zugeordnet wird und niemals für ein nicht zwischengespeichertes Blendensegment oder für eine schreibgekoppelte Zuordnung festgelegt wird, die einem cache-kohärenten Segment zugeordnet ist. -
Blendensegment aufheben
Der Unmap-Blendensegment-Vorgang hebt einen zuvor zugeordneten Bereich eines angegebenen Blendensegments auf. Der Treiber muss den Bereich zuordnen, der der Dummyseite nicht zugeordnet ist, die vom DummyPage Mitglied des UnmapApertureSegment Member der DXGKARG_BUILDPAGINGBUFFER Struktur angegeben wird.
Hinweis Wenn der Treiber die Zuordnung zur Dummyseite aufhebt, muss der Treiber GPU-Zugriffe über den angegebenen Blendenbereich aktivieren, damit das DirectX-Grafik-Kernel-Subsystem Beschädigungsprobleme erkennen kann. Konformitätstests sind vorhanden, um diese Situation zu überprüfen.Der Treiber kann optional MMIO verwenden, um ein Blendensegment zu konfigurieren. Die GPU greift zur Konfigurationszeit nicht auf den Blendenbereich zu. Diese Blendenkonfiguration darf jedoch nicht die Ausführung der GPU beeinträchtigen. Die GPU ist nicht im Leerlauf, wenn DxgkDdiBuildPagingBuffer- mit dem DXGK_OPERATION_UNMAP_APERTURE_SEGMENT Vorgangstypsatz aufgerufen wird, und die GPU kann mit dem Zugriff auf andere Teile des Blendensegments beschäftigt sein, die neu konfiguriert werden.
-
Spezialsperrübertragung
Der spezielle Verriegelungsvorgang ähnelt dem regulären Übertragungsvorgang. Anstatt jedoch den Inhalt der Zuordnung aus oder in den regulären Sicherungsspeicher der Zuordnung zu übertragen, überträgt der spezielle Sperrübertragungsvorgang den Inhalt der Zuordnung von oder an die alternative virtuelle Adresse, die für die Zuordnung eingerichtet wurde, als die pfnLockCb--Funktion mit dem UseAlternateVA Bitfeldflagge aufgerufen wurde.
Der Spezielle Sperrübertragungsvorgang tritt nur in einem der folgenden Szenarien auf:
- Die Zuordnung ist derzeit cpu-zugänglich mit einer alternativen virtuellen Adresse und wird ausgeräumt.
- Eine zuordnung, die zuvor entfernt wurde, z. B. die Situation, die im vorherigen Aufzählungszeichen beschrieben wird, wird wieder eingeteilt.
In einigen Szenarien ist der Treiber möglicherweise erforderlich, um Hardwareressourcen einzurichten, wenn bestimmte Zuordnungen in oder außerhalb des Arbeitsspeichers ausgelagert werden. Standardmäßig verwendet die GPU möglicherweise die Zuordnung, auf die während des Aufrufs von DxgkDdiBuildPagingBufferverwiesen wird. In diesen Szenarien muss der Treiber möglicherweise leer sein, bevor die erforderlichen Hardwareressourcen vom Treiber programmiert werden (d. a. die Programmierung der Hardwareressourcen kann nicht im bereitgestellten DMA-Puffer in die Warteschlange gestellt werden). In solchen Szenarien kann der Treiber den Aufruf von DxgkDdiBuildPagingBuffer mit STATUS_GRAPHICS_ALLOCATION_BUSY fehlschlagen.
Wenn der Treiber STATUS_GRAPHICS_ALLOCATION_BUSY zurückgibt, wartet der Videospeicher-Manager, bis die GPU mit einem Verweis auf die aktuelle Zuordnung abgeschlossen ist, und ruft dann die DxgkDdiBuildPagingBuffer Funktion erneut auf. Im zweiten Aufruf von DxgkDdiBuildPagingBufferlegt der Videospeicher-Manager die AllocationIsIdle Bitfeldkennzeichnung im Flags Member des SpecialLockTransfer Member der DXGKARG_BUILDPAGINGBUFFER Struktur fest, um anzugeben, dass die zuordnung, auf die verwiesen wird, im Leerlauf ist. Wenn das Leerlaufflagge nicht festgelegt ist, sollte der Treiber immer feststellen, dass die Zuordnung aktuell ausgelastet ist oder bald ausgelastet wird. Wenn das Leerlaufflagge festgelegt ist, garantiert der Videospeicher-Manager, dass die zuordnung, auf die verwiesen wird, für die Dauer des Aufrufs an DxgkDdiBuildPagingBufferim Leerlauf bleibt.
Der Speicher-Manager des Systems stellt sicher, dass die Übertragung für die Anwendung unsichtbar ist. Da sich die Zuordnung jedoch im Systemspeicher befindet und die virtuelle Adresse der Zuordnung nicht mehr durch die Hardware blenden kann, muss der Treiber sicherstellen, dass die Byte-Sortierung in den Systemspeicher mit dem durch die Blende sichtbaren Wert übereinstimmt.
DxgkDdiBuildPagingBuffer sollte seitenfähig gemacht werden.
Beispiele
Das folgende Codebeispiel zeigt, wie DxgkDdiBuildPagingBufferverwendet wird.
NTSTATUS ntStatus;
DXGKARG_BUILDPAGINGBUFFER param;
// The driver receives the following paging operation to build:
//
param.Flags = 0;
param.pDmaBuffer= CurrentPagingBuffer;
param.DmaSize = CurrentPagingBufferSizeLeft;
param.pDmaBufferPrivateData = CurrentPagingBufferPrivateData;
param.DmaBufferPrivateDataSize = CurrentPagingBufferPrivateDataSizeLeft;
param.Operation = DXGK_OPERATION_TRANSFER;
param.Transfer.Flags = 0;
param.Transfer.TransferOffset = CurrentOffsetInAllocationBeingTransfered;
param.Transfer.hAllocation = DriverContextForAllocationBeingMoved;
param.Transfer.Source.SegmentId = 0; // Source is an MDL.
param.Transfer.Source.pMdl = MDLDescribingPagesForAllocationBeingMoved;
param.Transfer.Destination.SegmentId = 1; // Source to segment #1.
param.Transfer.Destination.SegmentAddress = 0; // Source to offset 0 of segment #1.
// The driver receives MultipassOffset when it is initialized to zero
// and uses it for multiple iterations of the paging operation.
//
param.MultipassOffset = 0;
do {
// Call the driver's BuildPagingBuffer function to build a paging buffer.
//
ntStatus = BuildPagingBuffer(hAdapter, ¶m);
// BuildPagingBuffer updates the size that is left in the
// paging buffer with the amount of bytes that were written.
//
if (NT_SUCCESS(ntStatus)) {
//
// If STATUS_SUCCESS, batch the paging buffer to the
// scheduler after multiple paging operations are batched.
}
else if (ntStatus == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER) {
//
// If STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, submit the current paging buffer to the scheduler to let
// the GPU start working on a partial transfer.
VidSchSubmitPagingBuffer(CurrentPagingBuffer, CurrentPagingBufferSizeLeft);
// Acquire a new paging buffer to complete the transfer.
//
VidMmAcquirePagingBuffer(&CurrentPagingBuffer, &CurrentPagingBufferSizeLeft);
}
else {
//
// A critical failure occurred, so bugcheck the system.
// This situation should never occur because the driver can
// fail the call only if it requires more DMA buffer space.
}
} while(!NT_SUCCESS(ntStatus))
Anforderungen
Anforderung | Wert |
---|---|
mindestens unterstützte Client- | Windows Vista |
Zielplattform- | Desktop |
Header- | d3dkmddi.h |
IRQL- | PASSIVE_LEVEL |