Share via


Flip model, modifiziert rectangles, scrolled areas

DXGI 1.2 unterstützt eine neue Flip-Model-Swapchain, modifiziert Rechtecke und scrollte Bereiche. Wir erläutern die Vorteile der verwendung der neuen Flip-Model-Swapchain und der Optimierung der Darstellung durch Angabe modifiziert Rechtecke und scrollter Bereiche.

DXGI-Flipmodellpräsentation

DXGI 1.2 fügt Unterstützung für das Flip-Präsentationsmodell für Direct3D 10- und höher-APIs hinzu. In Windows 7 hat Direct3D 9EX zuerst eine Flip-Model-Präsentation eingeführt, um das unnötige Kopieren des Swap-Chain-Puffers zu vermeiden. Mithilfe des Flipmodells werden Rückpuffer zwischen der Laufzeit und dem Desktopfenster-Manager (DWM) umgedreht, sodass DWM immer direkt aus dem Backpuffer erstellt wird, anstatt den Inhalt des Backpuffers zu kopieren.

DXGI 1.2-APIs enthalten die überarbeitete DXGI-Swap-Chain-Schnittstelle IDXGISwapChain1. Sie können mehrere IDXGIFactory2-Schnittstellenmethoden verwenden, um das entsprechende IDXGISwapChain1-Objekt für die Verwendung mit einem HWND-Handle , einem CoreWindow-Objekt , DirectComposition oder dem Windows.UI.Xaml-Framework zu erstellen.

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 den 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 Darstellung des Flip-Präsentationsmodells und anderer neuer Funktionen wird empfohlen, das Flip-Präsentationsmodell für alle neuen Apps zu verwenden, die Sie mit Direct3D 10 und höher schreiben.

Verwenden modifiziert Rechtecke und des Bildlaufrechtecks in der Swap chain-Präsentation

Durch die Verwendung modifiziert Rechtecke und des Bildlaufrechtecks in der Swap chain-Präsentation sparen Sie die Nutzung der Speicherbandbreite und die damit verbundene Nutzung der Systemleistung, da die Menge an Pixeldaten, die das Betriebssystem zum Zeichnen des nächsten angezeigten Frames benötigt, reduziert wird, wenn das Betriebssystem nicht den gesamten Frame zeichnen muss. Bei Apps, die häufig über Remotedesktopverbindung und andere Technologien für den Remotezugriff angezeigt werden, sind die Einsparungen besonders in der Anzeigequalität spürbar, da diese Technologien modifiziert Rechtecke und Scrollmetadaten verwenden.

Sie können den Bildlauf nur mit DXGI-Swapchains verwenden, die im Flip-Präsentationsmodell ausgeführt werden. Sie können modifiziert Rechtecke mit DXGI-Swapchains verwenden, die sowohl im Flip-Modell als auch im Bitblt-Modell ausgeführt werden (mit DXGI_SWAP_EFFECT_SEQUENTIAL festgelegt).

In diesem Szenario und in der Abbildung zeigen wir die Funktionalität der Verwendung von modifiziert Rechtecke und Bildlauf. Hier enthält eine scrollbare App Text und animierende Videos. Die App verwendet modifiziert Rechtecke, um nur das animierende Video und die neue Zeile für das Fenster zu aktualisieren, anstatt das gesamte Fenster zu aktualisieren. Das Scrollrechteck ermöglicht es dem Betriebssystem, den zuvor gerenderten Inhalt im neuen Frame zu kopieren und zu übersetzen und nur die neue Zeile im neuen Frame zu rendern.

Die App führt eine Präsentation durch Aufrufen der IDXGISwapChain1::P resent1-Methode durch. In diesem Aufruf übergibt die App einen Zeiger an eine DXGI_PRESENT_PARAMETERS-Struktur, die modifiziert Rechtecke und die Anzahl der modifiziert Rechtecke, das Scrollrechteck und den zugeordneten Bildlaufoffset oder beides modifiziert Rechtecke und das Scrollrechteck enthält. Unsere App übergibt 2 modifiziert Rechtecke und das Scrollrechteck. 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 animierende Video und die neue Zeile als modifiziert Rechtecke an, und das Betriebssystem rendert sie im aktuellen Frame.

Abbildung von Bildlauf- und modifiziert Rechtecke, die sich überlappen

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 Scrollrechteck im aktuellen Frame an. Das Bildlaufrechteck wird durch das pScrollRect-Element von DXGI_PRESENT_PARAMETERS angegeben. Der Pfeil zeigt den Scrolloffset an. Der Bildlaufoffset wird durch das pScrollOffset-Element von DXGI_PRESENT_PARAMETERS angegeben. Gefüllte Rechtecke zeigen modifiziert Rechtecke an, die die App mit neuen Inhalten aktualisiert hat. Die gefüllten Rechtecke werden durch die Member DirtyRectsCount und pDirtyRects von DXGI_PRESENT_PARAMETERS angegeben.

Beispiel-2-Puffer-Flip-Model-Swapchain mit modifiziert Rechtecke und Scrollrechteck

Die nächste Abbildung und Sequenz zeigt ein Beispiel für einen DXGI-Flipmodellpräsentationsvorgang, der modifiziert Rechtecke und ein Scrollrechteck verwendet. In diesem Beispiel verwenden wir die mindeste Anzahl von Puffern für die Flip-Model-Präsentation, d. h. eine Pufferanzahl von zwei, einen Frontpuffer, der den App-Anzeigeinhalt enthält, und einen Backpuffer, der den aktuellen Frame enthält, den die App rendern möchte.

  1. Wie im vorderen Puffer am Anfang des Frames gezeigt, zeigt die scrollbare App zunächst einen Frame mit text und animierendem Video an.
  2. Um den nächsten Frame zu rendern, rendert die App die modifiziert Rechtecke, die das animierende Video und die neue Zeile für das Fenster aktualisieren, auf dem Hintergrundpuffer.
  3. Wenn die App IDXGISwapChain1::P resent1 aufruft, gibt sie die modifiziert Rechtecke sowie das Scrollrechteck und den Offset an. Die Runtime kopiert als Nächstes das Scrollrechteck aus dem vorherigen Frame abzüglich der aktualisierten modifiziert Rechtecke in den aktuellen Backpuffer.
  4. Die Runtime tauscht schließlich die Front- und Backpuffer aus.

Beispiel für Flip-Model-Swapchain mit Bildlauf und modifiziert Rechtecke

Nachverfolgen modifiziert Rechtecke und Bildlaufrechtecke über mehrere Frames hinweg

Wenn Sie modifiziert Rechtecke in Ihrer App verwenden, müssen Sie die modifiziert Rechtecke nachverfolgen, um inkrementelles Rendering zu unterstützen. Wenn Ihre App IDXGISwapChain1::P resent1 mit modifiziert Rechtecke aufruft, müssen Sie sicherstellen, dass jedes Pixel innerhalb der modifiziert Rechtecke auf dem neuesten Stand ist. Wenn Sie den gesamten Bereich des modifiziert Rechtecks nicht vollständig neu rendern oder wenn Sie bestimmte Bereiche nicht kennen können, die verschmutzt sind, müssen Sie einige Daten aus dem vorherigen vollständig kohärenten Rückpuffer in den aktuellen veralteten Rückpuffer 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 Puffer. Wenn sich diese Bereiche überschneiden, kopiert die Runtime nur den Unterschied zwischen ihnen. Wie Sie im folgenden Diagramm und der folgenden Sequenz sehen können, müssen Sie die Schnittmenge zwischen dem modifiziert Rechteck aus Frame 1 und dem modifiziert Rechteck aus Frame 2 in das modifiziert Rechteck von Frame 2 kopieren.

  1. Zeigen Sie modifiziert Rechteck in Frame 1 an.
  2. Kopieren Sie die Schnittmenge zwischen dem modifiziert Rechteck aus Frame 1 und dem modifiziert Rechteck aus Frame 2 in das modifiziert Rechteck von Frame 2.
  3. Zeigen Sie modifiziert Rechteck in Frame 2 an.

Nachverfolgen von Bildlauf und modifiziert Rechtecke über mehrere Frames hinweg

Für eine Swapchain mit N-Puffern lautet der Bereich, den die Laufzeit vom letzten Frame in den aktuellen Frame kopiert:

Formel zum Berechnen des Bereichs, der von der Laufzeit kopiert wird

wobei puffer den Pufferindex in einer Swapchain angibt, beginnend mit dem aktuellen Pufferindex bei 0.

Sie können alle Überschneidungen zwischen dem vorherigen Frame und den modifiziert Rechtecke des aktuellen Frames nachverfolgen, indem Sie eine Kopie der modifiziert Rechtecke des vorherigen Frames beibehalten oder die modifiziert 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 über mehr als 2 Backpuffer verfügt, sicherstellen, dass überlappende Bereiche zwischen den modifiziert Rechtecken des aktuellen Puffers und den modifiziert Rechtecken aller vorherigen Frames kopiert oder neu gerendert werden.

Nachverfolgen einer einzelnen Schnittmenge zwischen 2 modifiziert Rechtecken

Im einfachsten Fall, wenn Sie ein einzelnes modifiziert Rechteck pro Frame aktualisieren, überschneiden sich die modifiziert Rechtecke über zwei Frames. Um herauszufinden, ob sich das modifiziert Rechteck des vorherigen Frames und das modifiziert Rechteck des aktuellen Frames überschneiden, müssen Sie überprüfen, ob sich das modifiziert Rechteck des vorherigen Frames mit dem modifiziert Rechteck des aktuellen Frames überschneidet. Sie können die GDI IntersectRect-Funktion aufrufen, um zu bestimmen, ob sich zwei RECT-Strukturen, die die beiden modifiziert Rechtecke darstellen, überschneiden.

In diesem Codeausschnitt gibt ein Aufruf von IntersectRect die Schnittmenge von zwei modifiziert Rechtecke in einem anderen RECT namens dirtyRectCopy zurück. Nachdem der Codeausschnitt festgestellt hat, dass sich die beiden modifiziert Rechtecke überschneiden, ruft er die ID3D11DeviceContext1::CopySubresourceRegion1-Methode auf, um den Bereich der Schnittmenge 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 modifiziert-Rechteck zu aktualisieren.

Nachverfolgen von Überschneidungen zwischen N modifiziert Rechtecken

Wenn Sie mehrere modifiziert Rechtecke angeben, die ein modifiziert Rechteck für die neu angezeigte Bildlauflinie enthalten können, müssen Sie alle Überlappungen überprüfen und nachverfolgen, die zwischen allen modifiziert Rechtecken des vorherigen Frames und allen modifiziert Rechtecken des aktuellen Frames auftreten können. Um die Überschneidungen zwischen den modifiziert Rechtecke des vorherigen Frames und den modifiziert Rechtecke des aktuellen Frames zu berechnen, können Sie die modifiziert Rechtecke in Regionen gruppieren.

In diesem Codeausschnitt rufen wir die GDI SetRectRgn-Funktion auf, um jedes modifiziert Rechteck in einen rechteckigen Bereich zu konvertieren, und dann rufen wir die GDI CombineRgn-Funktion auf, um alle modifiziert rechteckigen Regionen 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 jetzt die GDI CombineRgn-Funktion verwenden, um die Schnittmenge zwischen der modifiziert Region des vorherigen Frames und der modifiziert Region des aktuellen Frames zu bestimmen. Nachdem Sie die sich überschneidende Region abgerufen haben, rufen Sie die GDI GetRegionData-Funktion auf, um jedes einzelne Rechteck aus der sich überschneidenden Region abzurufen, und rufen Sie dann die ID3D11DeviceContext1::CopySubresourceRegion1-Methode auf, um jedes sich überschneidende Rechteck in den aktuellen Rückpuffer zu kopieren. Der nächste Codeausschnitt zeigt die Verwendung dieser GDI- und Direct3D-Funktionen.

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 modifiziert Rechtecke

Sie können modifiziert Rechtecke mit DXGI-Swapchains verwenden, die im Bitblt-Modell (mit DXGI_SWAP_EFFECT_SEQUENTIAL) ausgeführt werden. Bitblt-Modell-Swapketten, die mehr als einen Puffer verwenden, müssen auch überlappende modifiziert Rechtecke über Frames hinweg auf die gleiche Weise nachverfolgen, wie unter Nachverfolgen modifiziert Rechtecke und Scrollrechtecke über mehrere Frames für Wechselketten des Flipmodells beschrieben. Bitblt-Modell-Swapketten mit nur einem Puffer müssen keine überlappenden modifiziert Rechtecke nachverfolgen, da der gesamte Puffer jeden Frame neu gezeichnet wird.

DXGI 1.2 Verbesserungen