Flip-Modell, schmutzige Rechtecke, Bildlaufbereiche
DXGI 1.2 unterstützt eine neue Flip-Modell-Swapchain, schmutzige Rechtecke und Bildlaufbereiche. Wir erläutern die Vorteile der Verwendung der neuen Flip-Modell-Swapchain und der Optimierung der Präsentation durch Angabe von schmutzigen Rechtecken und Bildlaufbereichen.
DXGI-Flip-Modellpräsentation
DXGI 1.2 bietet Unterstützung für das Flip-Präsentationsmodell für Direct3D 10 und höhere APIs. In Windows 7 hat Direct3D 9EX zunächst Flipmodellpräsentation eingeführt, um unnötiges Kopieren des Swapchainpuffers zu vermeiden. Mithilfe des Flipmodells werden Hintergrundpuffer zwischen der Laufzeit und dem DesktopFenster-Manager (DWM) gedreht, sodass DWM immer direkt aus dem Hintergrundpuffer verfasst wird, anstatt den Hintergrundpufferinhalt zu kopieren.
DXGI 1.2-APIs enthalten eine überarbeitete DXGI-Swapchainschnittstelle, IDXGISwapChain1. Sie können mehrere IDXGIFactory2- Schnittstellenmethoden verwenden, um das entsprechende IDXGISwapChain1--Objekt zu erstellen, das mit einem HWND- Handle, einem CoreWindow--Objekt, DirectComposition-oder dem Windows.UI.Xaml Framework verwendet wird.
Sie wählen das Flip-Präsentationsmodell aus, indem Sie den DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL Enumerationswert im SwapEffect- Member der DXGI_SWAP_CHAIN_DESC1 Struktur angeben und das BufferCount Member von DXGI_SWAP_CHAIN_DESC1 auf mindestens 2 festlegen. Weitere Informationen zur Verwendung des DXGI-Flipmodells finden Sie unter DXGI Flip-Modell. Aufgrund der reibungsloseren Präsentation des Flip-Präsentationsmodells und anderer neuer Funktionen empfehlen wir, das Flip-Präsentationsmodell für alle neuen Apps zu verwenden, die Sie mit Direct3D 10 und höher schreiben.
Verwenden von schmutzigen Rechtecke und dem Bildlaufrechteck in der Swapchainpräsentation
Wenn Sie schmutzige Rechtecke und das Bildlaufrechteck in der Swapchainpräsentation verwenden, sparen Sie die Speicherbandbreite und die damit verbundene Nutzung der Systemleistung, da die Menge der Pixeldaten, die das Betriebssystem zum Zeichnen des nächsten dargestellten Frames benötigt, reduziert wird, wenn das Betriebssystem nicht den gesamten Frame zeichnen muss. Für Apps, die häufig über Remotedesktopverbindung und andere Technologien für den Remotezugriff angezeigt werden, sind die Einsparungen in der Anzeigequalität besonders spürbar, da diese Technologien schmutzige Rechtecke und Bildlaufmetadaten verwenden.
Sie können scrollen nur mit DXGI-Swapchains verwenden, die im Flip-Präsentationsmodell ausgeführt werden. Sie können schmutzige Rechtecke mit DXGI-Swapchains verwenden, die sowohl im Flip-Modell als auch im Bitblt-Modell ausgeführt werden (mit DXGI_SWAP_EFFECT_SEQUENTIALfestgelegt).
In diesem Szenario und in der Abbildung zeigen wir die Funktionalität der Verwendung von schmutzigen Rechtecke und Bildlauf. Hier enthält eine bildlauffähige App Text und Animieren von Videos. Die App verwendet schmutzige Rechtecke, um einfach das animierende Video und die neue Zeile für das Fenster zu aktualisieren, anstatt das gesamte Fenster zu aktualisieren. Mit dem Bildlaufrechteck kann das Betriebssystem den zuvor gerenderten Inhalt im neuen Frame kopieren und übersetzen und nur die neue Zeile im neuen Frame rendern.
Die App führt eine Präsentation durch Aufrufen der IDXGISwapChain1::P resent1-Methode aus. In diesem Aufruf übergibt die App einen Zeiger an eine DXGI_PRESENT_PARAMETERS Struktur, die schmutzige Rechtecke und die Anzahl der schmutzigen Rechtecke oder das Bildlaufrechteck und den zugeordneten Bildlaufoffset oder sowohl schmutzige Rechtecke als auch das Bildlaufrechteck enthält. Unsere App übergibt zwei schmutzige Rechtecke und das Bildlaufrechteck. Das Bildlaufrechteck ist der Bereich des vorherigen Frames, den das Betriebssystem in den aktuellen Frame kopieren muss, bevor er den aktuellen Frame rendert. Die App gibt das Animieren von Videos und neue Linien als schmutzige Rechtecke an, und das Betriebssystem rendert sie im aktuellen Frame.
DirtyRectsCount = 2
pDirtyRects[ 0 ] = { 10, 30, 40, 50 } // Video
pDirtyRects[ 1 ] = { 0, 70, 50, 80 } // New line
*pScrollRect = { 0, 0, 50, 70 }
*pScrollOffset = { 0, -10 }
Das gestrichelte Rechteck zeigt das Bildlaufrechteck im aktuellen Frame an. Das Bildlaufrechteck wird durch das pScrollRect- Element von DXGI_PRESENT_PARAMETERSangegeben. Der Pfeil zeigt den Bildlaufoffset an. Der Bildlaufoffset wird durch das pScrollOffset Element von DXGI_PRESENT_PARAMETERSangegeben. Gefüllte Rechtecke zeigen schmutzige Rechtecke an, die die App mit neuem Inhalt aktualisiert hat. Die gefüllten Rechtecke werden durch die DirtyRectsCount und pDirtyRects Member von DXGI_PRESENT_PARAMETERSangegeben.
2-Puffer-Flip-Modell-Swapchain mit schmutzigen Rechtecks und Bildlaufrechteck
Die nächste Abbildung und Sequenz zeigt ein Beispiel für einen DXGI-Flip-Modellpräsentationsvorgang, der schmutzige Rechtecke und ein Bildlaufrechteck verwendet. In diesem Beispiel wird die Mindestanzahl von Puffern für die Flipmodellpräsentation verwendet. Dabei handelt es sich um eine Pufferanzahl von zwei Puffern, einen Frontpuffer, der den Inhalt der App-Anzeige enthält, und einen Hintergrundpuffer, der den aktuellen Frame enthält, den die App rendern möchte.
- Wie im Frontpuffer am Anfang des Frames gezeigt, zeigt die bildlauffähige App zunächst einen Frame mit text und animierendes Video an.
- Um den nächsten Frame zu rendern, rendert die App im Hintergrundpuffer die schmutzigen Rechtecke, die das Animieren des Videos und die neue Zeile für das Fenster aktualisieren.
- Wenn die App IDXGISwapChain1::P resent1aufruft, gibt sie die schmutzigen Rechtecke und das Bildlaufrechteck und den Offset an. Die Laufzeit kopiert das Bildlaufrechteck aus dem vorherigen Frame abzüglich der aktualisierten geänderten Rechtecke in den aktuellen Hintergrundpuffer.
- Die Laufzeit tauscht schließlich die Front- und Backpuffer aus.
Nachverfolgen schmutziger Rechtecke und Bildlaufrechtecke über mehrere Frames
Wenn Sie schmutzige Rechtecke in Ihrer App verwenden, müssen Sie die schmutzigen Rechtecke nachverfolgen, um das inkrementelle Rendering zu unterstützen. Wenn Ihre App IDXGISwapChain1::P resent1 mit schmutzigen Rechtecke aufruft, müssen Sie sicherstellen, dass jedes Pixel innerhalb der schmutzigen Rechtecke auf dem neuesten Stand ist. Wenn Sie den gesamten Bereich des schmutzigen Rechtecks nicht vollständig neu rendern oder für bestimmte Bereiche, die schmutzig sind, nicht wissen können, müssen Sie einige Daten aus dem vorherigen vollständig kohärenten Hintergrundpuffer in den aktuellen, veralteten Hintergrundpuffer kopieren, bevor Sie mit dem Rendern beginnen.
Die Laufzeit kopiert nur die Unterschiede zwischen aktualisierten Bereichen des vorherigen Frames und aktualisierten Bereichen des aktuellen Frames in den aktuellen Hintergrundpuffer. Wenn sich diese Bereiche schneiden, kopiert die Laufzeit nur den Unterschied zwischen diesen Bereichen. Wie Sie im folgenden Diagramm und in der folgenden Reihenfolge sehen können, müssen Sie die Schnittmenge zwischen dem schmutzigen Rechteck aus Frame 1 und dem schmutzigen Rechteck aus Frame 2 in das schmutzige Rechteck von Frame 2 in das schmutzige Rechteck von Frame 2 kopieren.
- Darstellen eines schmutzigen Rechtecks in Frame 1.
- Kopieren Sie die Schnittmenge zwischen dem schmutzigen Rechteck aus Frame 1 und dem schmutzigen Rechteck aus Frame 2 in das schmutzige Rechteck von Frame 2.
- Darstellen eines schmutzigen Rechtecks in Frame 2.
Um eine Swapchain mit N-Puffern zu generalisieren, lautet der Bereich, den die Laufzeit vom letzten Frame in den aktuellen Frame des aktuellen Frames kopiert:
wobei puffer den Pufferindex in einer Swapchain angibt, beginnend mit dem aktuellen Pufferindex bei Null.
Sie können alle Schnittmengen zwischen dem vorherigen Frame und den schmutzigen Rechtecke des aktuellen Frames nachverfolgen, indem Sie eine Kopie der schmutzigen Rechtecke des vorherigen Frames beibehalten oder die schmutzigen Rechtecke des neuen Frames mit dem entsprechenden Inhalt aus dem vorherigen Frame neu rendern.
Ebenso müssen Sie in den Fällen, in denen die Swapchain mehr als 2 Hintergrundpuffer enthält, sicherstellen, dass überlappende Bereiche zwischen den schmutzigen Rechtecke des aktuellen Puffers und den schmutzigen Rechtecke aller vorherigen Frames kopiert oder neu gerendert werden.
Nachverfolgen einer einzelnen Schnittmenge zwischen zwei schmutzigen Rechtecke
Wenn Sie ein einzelnes schmutziges Rechteck pro Frame aktualisieren, schneiden sich die schmutzigen Rechtecke in zwei Frames möglicherweise. Um herauszufinden, ob sich das schmutzige Rechteck des vorherigen Frames und das schmutzige Rechteck des aktuellen Frames überlappen, müssen Sie überprüfen, ob sich das schmutzige Rechteck des vorherigen Frames mit dem schmutzigen Rechteck des aktuellen Frames überschneidet. Sie können die GDI-IntersectRect--Funktion aufrufen, um zu bestimmen, ob zwei RECT--Strukturen, die die beiden schmutzigen Rechtecke darstellen, überschneiden.
In diesem Codeausschnitt gibt ein Aufruf von IntersectRect die Schnittmenge von zwei schmutzigen Rechtecke in einem anderen RECT- "dirtyRectCopy" zurück. Nachdem der Codeausschnitt ermittelt hat, dass sich die beiden schmutzigen Rechtecke schneiden, wird die ID3D11DeviceContext1::CopySubresourceRegion1 Methode aufgerufen, um den Schnittpunktbereich in den aktuellen Frame zu kopieren.
RECT dirtyRectPrev, dirtyRectCurrent, dirtyRectCopy;
if (IntersectRect( &dirtyRectCopy, &dirtyRectPrev, &dirtyRectCurrent ))
{
D3D11_BOX intersectBox;
intersectBox.left = dirtyRectCopy.left;
intersectBox.top = dirtyRectCopy.top;
intersectBox.front = 0;
intersectBox.right = dirtyRectCopy.right;
intersectBox.bottom = dirtyRectCopy.bottom;
intersectBox.back = 1;
d3dContext->CopySubresourceRegion1(pBackbuffer,
0,
0,
0,
0,
pPrevBackbuffer,
0,
&intersectBox,
0
);
}
// Render additional content to the current pBackbuffer and call Present1.
Wenn Sie diesen Codeausschnitt in Ihrer Anwendung verwenden, kann die App IDXGISwapChain1::P resent1 aufrufen, um den aktuellen Frame mit dem aktuellen geänderten Rechteck zu aktualisieren.
Nachverfolgen von Schnittmengen zwischen N dirty rectangles
Wenn Sie mehrere geänderte Rechtecke angeben, die ein schmutziges Rechteck für die neu angezeigte Bildlauflinie enthalten können, müssen Sie alle Überlappungen überprüfen und nachverfolgen, die zwischen allen schmutzigen Rechtecke des vorherigen Frames und allen schmutzigen Rechtecke des aktuellen Frames auftreten können. Um die Schnittmengen zwischen den schmutzigen Rechtecke des vorherigen Frames und den schmutzigen Rechtecke des aktuellen Frames zu berechnen, können Sie die schmutzigen Rechtecke in Regionen gruppieren.
In diesem Codeausschnitt rufen wir die GDI-SetRectRgn--Funktion auf, um jedes schmutzige Rechteck in einen rechteckigen Bereich zu konvertieren, und dann rufen wir die GDI-CombineRgn--Funktion auf, um alle schmutzigen rechteckigen Bereiche in einer Gruppe zu kombinieren.
HRGN hDirtyRgnPrev, hDirtyRgnCurrent, hRectRgn; // Handles to regions
// Save all the dirty rectangles from the previous frame.
RECT dirtyRect[N]; // N is the number of dirty rectangles in current frame, which includes newly scrolled area.
int iReturn;
SetRectRgn(hDirtyRgnCurrent,
dirtyRect[0].left,
dirtyRect[0].top,
dirtyRect[0].right,
dirtyRect[0].bottom
);
for (int i = 1; i<N; i++)
{
SetRectRgn(hRectRgn,
dirtyRect[0].left,
dirtyRect[0].top,
dirtyRect[0].right,
dirtyRect[0].bottom
);
iReturn = CombineRgn(hDirtyRgnCurrent,
hDirtyRgnCurrent,
hRectRgn,
RGN_OR
);
// Handle the error that CombineRgn returns for iReturn.
}
Sie können nun die GDI-CombineRgn--Funktion verwenden, um die Schnittmenge zwischen dem schmutzigen Bereich des vorherigen Frames und dem schmutzigen Bereich des aktuellen Frames zu bestimmen. Rufen Sie nach dem Abrufen der überschneidenden Region die GDI-GetRegionData--Funktion auf, um jedes einzelne Rechteck aus dem sich schneidenden Bereich abzurufen, und rufen Sie dann die ID3D11DeviceContext1::CopySubresourceRegion1 Methode auf, um jedes sich überschneidende Rechteck in den aktuellen Hintergrundpuffer zu kopieren. Der nächste Codeausschnitt zeigt, wie diese GDI- und Direct3D-Funktionen verwendet werden.
HRGN hIntersectRgn;
bool bRegionsIntersect;
iReturn = CombineRgn(hIntersectRgn, hDirtyRgnCurrent, hDirtyRgnPrev, RGN_AND);
if (iReturn == ERROR)
{
// Handle error.
}
else if(iReturn == NULLREGION)
{
bRegionsIntersect = false;
}
else
{
bRegionsIntersect = true;
}
if (bRegionsIntersect)
{
int rgnDataSize = GetRegionData(hIntersectRgn, 0, NULL);
if (rgnDataSize)
{
char pMem[] = new char[size];
RGNDATA* pRgnData = reinterpret_cast<RGNDATA*>(pMem);
iReturn = GetRegionData(hIntersectRgn, rgnDataSize, pRgnData);
// Handle iReturn failure.
for (int rectcount = 0; rectcount < pRgnData->rdh.nCount; ++r)
{
const RECT* pIntersectRect = reinterpret_cast<RECT*>(pRgnData->Buffer) +
rectcount;
D3D11_BOX intersectBox;
intersectBox.left = pIntersectRect->left;
intersectBox.top = pIntersectRect->top;
intersectBox.front = 0;
intersectBox.right = pIntersectRect->right;
intersectBox.bottom = pIntersectRect->bottom;
intersectBox.back = 1;
d3dContext->CopySubresourceRegion1(pBackbuffer,
0,
0,
0,
0,
pPrevBackbuffer,
0,
&intersectBox,
0
);
}
delete [] pMem;
}
}
Bitblt-Modell-Swapchain mit schmutzigen Rechtecke
Sie können schmutzige Rechtecke mit DXGI-Swapchains verwenden, die im Bitblt-Modell ausgeführt werden (mit DXGI_SWAP_EFFECT_SEQUENTIALfestgelegt). Bitblt-Modell-Swapchains, die mehr als einen Puffer verwenden, müssen auch überlappende Rechtecke auf die gleiche Weise nachverfolgen wie in Nachverfolgen schmutziger Rechtecke und Bildlaufrechtecke über mehrere Frames für Flipmodell-Swapchains beschrieben. Bitblt-Modell-Swapchains mit nur einem Puffer müssen keine überlappenden schmutzigen Rechtecke nachverfolgen, da der gesamte Puffer jedes Frame neu gezeichnet wird.