Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
DXGI 1.2 admite una nueva cadena de intercambio de modelos invertidos, rectángulos sucios y áreas desplazadas. Explicamos las ventajas de usar la nueva cadena de intercambio de modelos invertidos y de optimizar la presentación especificando rectángulos sucios y áreas desplazadas.
Presentación dxgi flip-model
DXGI 1.2 agrega compatibilidad con el modelo de presentación flip para direct3D 10 y las API posteriores. En Windows 7, Direct3D 9EX adoptó por primera vez presentación de modelo volteo para evitar copiar innecesariamente el búfer de la cadena de intercambio. Mediante el modelo de volteo, los búferes de retroceso se voltean entre el entorno de ejecución y el Administrador de ventanas de escritorio (DWM), por lo que DWM siempre se compone directamente desde el búfer de reserva en lugar de copiar el contenido del búfer de reserva.
Las API de DXGI 1.2 incluyen una interfaz de cadena de intercambio DXGI revisada, IDXGISwapChain1. Puedes usar varios métodos de interfaz deIDXGIFactory2 depara crear el objeto IDXGISwapChain 1 adecuado para usarlo con un identificador de HWND, un objeto CoreWindow, DirectCompositiono el marco de Windows.UI.Xaml.
Para seleccionar el modelo de presentación invertida, especifique el valor de enumeración de DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL en el miembro SwapEffect de la estructura de DXGI_SWAP_CHAIN_DESC1 y estableciendo el miembro BufferCount de DXGI_SWAP_CHAIN_DESC1 en un mínimo de 2. Para obtener más información sobre cómo usar el modelo de volteo DXGI, consulta modelo de volteo DXGI. Debido a la presentación más fluida del modelo de presentación invertida y otras nuevas funcionalidades, se recomienda usar el modelo de presentación voltear para todas las aplicaciones nuevas que escriba con Direct3D 10 y las API posteriores.
Uso de rectángulos sucios y el rectángulo de desplazamiento en la presentación de la cadena de intercambio
Al usar rectángulos sucios y el rectángulo de desplazamiento en la presentación de la cadena de intercambio, se ahorra en el uso del ancho de banda de memoria y el uso relacionado de la potencia del sistema porque la cantidad de datos de píxeles que el sistema operativo necesita para dibujar el siguiente fotograma presentado se reduce si el sistema operativo no necesita dibujar todo el fotograma. En el caso de las aplicaciones que a menudo se muestran a través de conexión a Escritorio remoto y otras tecnologías de acceso remoto, el ahorro es especialmente notable en la calidad de la pantalla porque estas tecnologías usan rectángulos sucios y metadatos de desplazamiento.
Solo puede usar el desplazamiento con cadenas de intercambio DXGI que se ejecutan en el modelo de presentación invertida. Puede usar rectángulos sucios con cadenas de intercambio DXGI que se ejecutan tanto en el modelo flip como en el modelo bitblt (establecido con DXGI_SWAP_EFFECT_SEQUENTIAL).
En este escenario e ilustración se muestra la funcionalidad de usar rectángulos sucios y desplazarse. Aquí, una aplicación desplazable contiene texto y vídeo de animación. La aplicación usa rectángulos sucios para actualizar simplemente el vídeo animado y la nueva línea de la ventana, en lugar de actualizar toda la ventana. El rectángulo de desplazamiento permite al sistema operativo copiar y traducir el contenido representado anteriormente en el nuevo marco y representar solo la nueva línea en el nuevo marco.
La aplicación realiza una presentación llamando al método IDXGISwapChain1::P resent1. En esta llamada, la aplicación pasa un puntero a una estructura de DXGI_PRESENT_PARAMETERS que incluye rectángulos sucios y el número de rectángulos sucios, o el rectángulo de desplazamiento y el desplazamiento de desplazamiento asociado, o rectángulos sucios y el rectángulo de desplazamiento. Nuestra aplicación pasa 2 rectángulos sucios y el rectángulo de desplazamiento. El rectángulo de desplazamiento es el área del marco anterior que el sistema operativo necesita copiar en el marco actual antes de representar el marco actual. La aplicación especifica el vídeo de animación y la nueva línea como rectángulos sucios y el sistema operativo los representa en el fotograma actual.
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 }
El rectángulo discontinuo muestra el rectángulo de desplazamiento en el marco actual. El rectángulo de desplazamiento se especifica mediante el miembro pScrollRect de DXGI_PRESENT_PARAMETERS. La flecha muestra el desplazamiento de desplazamiento. El desplazamiento de desplazamiento se especifica mediante el miembro pScrollOffset de DXGI_PRESENT_PARAMETERS. Los rectángulos rellenos muestran rectángulos sucios que la aplicación actualizó con nuevo contenido. Los rectángulos rellenados se especifican mediante el DirtyRectsCount y pDirtyRects miembros de DXGI_PRESENT_PARAMETERS.
Cadena de intercambio de modelo volteo de 2 búferes de ejemplo con rectángulos sucios y rectángulo de desplazamiento
En la siguiente ilustración y secuencia se muestra un ejemplo de una operación de presentación de modelo volteo DXGI que usa rectángulos sucios y un rectángulo de desplazamiento. En este ejemplo se usa el número mínimo de búferes para la presentación del modelo invertida, que es un recuento de búferes de dos, un búfer frontal que contiene el contenido de visualización de la aplicación y un búfer de reserva que contiene el marco actual que la aplicación quiere representar.
- Como se muestra en el búfer frontal al principio del marco, la aplicación desplazable muestra inicialmente un marco con texto y vídeo animado.
- Para representar el siguiente fotograma, la aplicación se representa en el búfer de reserva de los rectángulos sucios que actualizan el vídeo animado y la nueva línea de la ventana.
- Cuando la aplicación llama a IDXGISwapChain1::P resent1, especifica los rectángulos sucios y el rectángulo de desplazamiento y el desplazamiento. El entorno de ejecución siguiente copia el rectángulo de desplazamiento del marco anterior menos los rectángulos desfasados actualizados en el búfer de retroceso actual.
- Por último, el tiempo de ejecución intercambia los búferes frontales y traseros.
Seguimiento de rectángulos sucios y rectángulos de desplazamiento en varios marcos
Al usar rectángulos sucios en la aplicación, debes realizar un seguimiento de los rectángulos sucios para admitir la representación incremental. Cuando la aplicación llama a IDXGISwapChain1::P resent1 con rectángulos sucios, debes asegurarte de que todos los píxeles de los rectángulos sucios estén actualizados. Si no vuelve a representar completamente el área completa del rectángulo sucio o si no puede conocer ciertas áreas que están sucias, debe copiar algunos datos del búfer de retroceso totalmente coherente anterior al búfer de retroceso obsoleto actual antes de empezar a representarse.
El tiempo de ejecución solo copia las diferencias entre las áreas actualizadas del marco anterior y las áreas actualizadas del marco actual en el búfer de reserva actual. Si estas áreas se intersecan, el tiempo de ejecución solo copia la diferencia entre ellas. Como puede ver en el siguiente diagrama y secuencia, debe copiar la intersección entre el rectángulo sucio del marco 1 y el rectángulo sucio del marco 2 en el rectángulo sucio del marco 2.
- Presente rectángulo sucio en el marco 1.
- Copie la intersección entre el rectángulo sucio del marco 1 y el rectángulo sucio del marco 2 en el rectángulo sucio del marco 2.
- Presente rectángulo sucio en el marco 2.
Para generalizar, para una cadena de intercambio con N búferes, el área que el tiempo de ejecución copia del último fotograma en el marco actual en el marco actual es:
donde el búfer indica el índice del búfer en una cadena de intercambio, empezando por el índice de búfer actual en cero.
Puede realizar un seguimiento de las intersecciones entre el marco anterior y los rectángulos desfasados del marco actual manteniendo una copia de los rectángulos sucios del marco anterior o volver a representar los rectángulos sucios del nuevo marco con el contenido adecuado del marco anterior.
Del mismo modo, en los casos en los que la cadena de intercambio tiene más de 2 búferes back, debe asegurarse de que las áreas superpuestas entre los rectángulos sucios del búfer actual y los rectángulos sucios de todos los fotogramas anteriores se copian o se vuelven a representar.
Seguimiento de una sola intersección entre 2 rectángulos sucios
En el caso más sencillo, al actualizar un único rectángulo sucio por fotograma, los rectángulos sucios en dos fotogramas podrían intersectarse. Para averiguar si el rectángulo sucio del marco anterior y el rectángulo sucio del marco actual se superponen, debe comprobar si el rectángulo sucio del marco anterior interseca con el rectángulo sucio del marco actual. Puede llamar a la funciónintersectRect de GDIpara determinar si dos RECT estructuras que representan los dos rectángulos sucios se intersecan.
En este fragmento de código, una llamada a IntersectRect devuelve la intersección de dos rectángulos sucios en otro RECT denominado dirtyRectCopy. Una vez que el fragmento de código determina que los dos rectángulos sucios se intersecan, llama al método ID3D11DeviceContext1::CopySubresourceRegion1 para copiar la región de intersección en el marco actual.
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.
Si usa este fragmento de código en la aplicación, la aplicación estará lista para llamar a IDXGISwapChain1::P resent1 para actualizar el marco actual con el rectángulo sucio actual.
Seguimiento de intersecciones entre N rectángulos sucios
Si especifica varios rectángulos sucios, que pueden incluir un rectángulo sucio para la línea de desplazamiento recién revelada, por fotograma, debe comprobar y realizar un seguimiento de las superposiciones que puedan producirse entre todos los rectángulos sucios del marco anterior y todos los rectángulos sucios del marco actual. Para calcular las intersecciones entre los rectángulos sucios del marco anterior y los rectángulos sucios del marco actual, puede agrupar los rectángulos sucios en regiones.
En este fragmento de código, llamamos a la funciónGDISetRectRgn para convertir cada rectángulo sucio en una región rectangular y, a continuación, llamamos a la función GDI CombineRgn para combinar todas las regiones rectangulares sucias en un grupo.
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.
}
Ahora puede usar la función CombineRgn de GDI para determinar la intersección entre la región desfasada del marco anterior y la región desfasada del marco actual. Después de obtener la región de intersección, llame a la funciónGDIGetRegionData para obtener cada rectángulo individual de la región de intersección y, a continuación, llame al método ID3D11DeviceContext1::CopySubresourceRegion1 para copiar cada rectángulo intersecnte en el búfer de reserva actual. El siguiente fragmento de código muestra cómo usar estas funciones GDI y Direct3D.
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;
}
}
Cadena de intercambio de modelos bitblt con rectángulos sucios
Puede usar rectángulos sucios con cadenas de intercambio DXGI que se ejecutan en el modelo bitblt (establecido con DXGI_SWAP_EFFECT_SEQUENTIAL). Las cadenas de intercambio de modelos bitblt que usan más de un búfer también deben realizar un seguimiento de los rectángulos sucios superpuestos entre fotogramas de la misma manera que se describe en Seguimiento de rectángulos sucios y rectángulos de desplazamiento entre varios marcos para las cadenas de intercambio de modelos flip. Las cadenas de intercambio de modelos bitblt con solo un búfer no necesitan realizar un seguimiento de los rectángulos sucios superpuestos porque todo el búfer se vuelve a dibujar cada fotograma.