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.
Hay varios tipos de consultas diseñadas para consultar el estado de los recursos. El estado de un recurso determinado incluye el estado de la unidad de procesamiento de gráficos (GPU), el estado del controlador o el estado del entorno de ejecución. Para comprender la diferencia entre los distintos tipos de consulta, debe comprender los estados de consulta. En el diagrama de transición de estado siguiente se explica cada uno de los estados de consulta.
diagrama de 
El diagrama muestra tres estados, cada uno definido por círculos. Cada una de las líneas sólidas son eventos controlados por la aplicación que provocan una transición de estado. La línea discontinua es un evento controlado por recursos que cambia una consulta del estado emitido al estado señalado. Cada uno de estos estados tiene un propósito diferente:
- El estado señalado es como un estado inactivo. El objeto de consulta se ha generado y espera a que la aplicación emita la consulta. Una vez que una consulta se ha completado y vuelto al estado señalado, se puede recuperar la respuesta a la consulta.
- El estado de creación es como un área de ensayo para una consulta. Desde el estado de creación, se ha emitido una consulta (llamando a D3DISSUE_BEGIN), pero aún no ha pasado al estado emitido. Cuando una aplicación emite un extremo de consulta (llamando a D3DISSUE_END), la consulta pasa al estado emitido.
- El estado emitido significa que el recurso que se consulta tiene el control de la consulta. Una vez que el recurso finaliza su trabajo, el recurso pasa la máquina de estado al estado señalado. Durante el estado emitido, la aplicación debe sondear para detectar la transición al estado señalado. Una vez que se produce la transición al estado señalado, GetData devuelve el resultado de la consulta (a través de un argumento) a la aplicación.
En la tabla siguiente se enumeran los tipos de consulta disponibles.
| Tipo de consulta | Evento issue | Búfer GetData | Ejecución | Inicio implícito de la consulta |
|---|---|---|---|---|
| ANCHO DE BANDATIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9BANDWIDTHTIMINGS | Retail/Debug | N/A |
| CACHEUTILIZATION | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9CACHEUTILIZATION | Retail/Debug | N/A |
| EVENTO | D3DISSUE_END | BOOL | Retail/Debug | CreateDevice |
| INTERFACETIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9INTERFACETIMINGS | Retail/Debug | N/A |
| OCLUSIÓN | D3DISSUE_BEGIN, D3DISSUE_END | DWORD | Retail/Debug | N/A |
| PIPELINETIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9PIPELINETIMINGS | Retail/Debug | N/A |
| RESOURCEMANAGER | D3DISSUE_END | D3DDEVINFO_ResourceManager | Depurar solo | presentes |
| TIMESTAMP | D3DISSUE_END | UINT64 | Retail/Debug | N/A |
| TIMESTAMPDISJOINT | D3DISSUE_BEGIN, D3DISSUE_END | BOOL | Retail/Debug | N/A |
| TIMESTAMPFREQ | D3DISSUE_END | UINT64 | Retail/Debug | N/A |
| VCACHE | D3DISSUE_END | D3DDEVINFO_VCACHE | Retail/Debug | CreateDevice |
| VERTEXSTATS | D3DISSUE_END | D3DDEVINFO_D3DVERTEXSTATS | Depurar solo | presentes |
| VERTEXTIMINGS | D3DISSUE_BEGIN, D3DISSUE_END | D3DDEVINFO_D3D9STAGETIMINGS | Retail/Debug | N/A |
Algunas de las consultas requieren un evento de inicio y finalización, mientras que otros solo requieren un evento de finalización. Las consultas que solo requieren un evento final comienzan cuando se produce otro evento implícito (que aparece en la tabla). Todas las consultas devuelven una respuesta, excepto la consulta de eventos cuya respuesta es siempre TRUE. Una aplicación usa el estado de la consulta o el código devuelto de GetData.
Crear una consulta
Antes de crear una consulta, puede comprobar si el tiempo de ejecución admite consultas mediante una llamada a CreateQuery con un puntero NULL como este:
IDirect3DQuery9* pEventQuery;
// Create a device pointer m_pd3dDevice
// Create a query object
HRESULT hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, NULL);
Este método devuelve un código correcto si se puede crear una consulta; de lo contrario, devuelve un código de error. Una vez que CreateQuery se realiza correctamente, puede crear un objeto de consulta como este:
IDirect3DQuery9* pEventQuery;
m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
Si esta llamada se realiza correctamente, se crea un objeto de consulta. La consulta está esencialmente inactiva en el estado señalado (con una respuesta sin inicializar) a la espera de emitirse. Cuando haya terminado con la consulta, suéltelo como cualquier otra interfaz.
Emitir una consulta
Una aplicación cambia un estado de consulta mediante la emisión de una consulta. Este es un ejemplo de emisión de una consulta:
IDirect3DQuery9* pEventQuery;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
// Issue a Begin event
pEventQuery->Issue(D3DISSUE_BEGIN);
or
// Issue an End event
pEventQuery->Issue(D3DISSUE_END);
Una consulta en el estado señalado pasará de la siguiente manera cuando se emita:
| Tipo de problema | Realiza transiciones de consulta a . . . |
|---|---|
| D3DISSUE_BEGIN | Estado de creación. |
| D3DISSUE_END | Estado emitido. |
Una consulta en el estado de creación pasará de la siguiente manera cuando se emita:
| Tipo de problema | Realiza transiciones de consulta a . . . |
|---|---|
| D3DISSUE_BEGIN | (Sin transición, permanece en el estado de construcción. Reinicia el corchete de consulta). |
| D3DISSUE_END | Estado emitido. |
Una consulta en el estado emitido pasará de la siguiente manera cuando se emita:
| Tipo de problema | Realiza transiciones de consulta a . . . |
|---|---|
| D3DISSUE_BEGIN | El estado de creación y reinicia el corchete de consulta. |
| D3DISSUE_END | Estado emitido después de abandonar la consulta existente. |
Compruebe el estado de la consulta y obtenga la respuesta a la consulta.
GetData hace dos cosas:
- Devuelve el estado de consulta en el código devuelto.
- Devuelve la respuesta a la consulta en pData.
A partir de cada uno de los tres estados de consulta, estos son los códigos de retorno de GetData:
| Estado de consulta | Código de retorno getData |
|---|---|
| Señalado | S_OK |
| Edificio | Código de error |
| Emitido | S_FALSE |
Por ejemplo, cuando una consulta está en estado emitido y la respuesta a la consulta no está disponible, GetData devuelve S_FALSE. Cuando el recurso finaliza su trabajo y la aplicación ha emitido un extremo de consulta, el recurso pasa la consulta al estado señalado. Desde el estado señalado, GetData devuelve S_OK lo que significa que la respuesta a la consulta también se devuelve en pData. Por ejemplo, esta es la secuencia de eventos para devolver el número de píxeles (o muestras cuando se habilita el muestreo múltiple) dibujado en una secuencia de representación:
- Cree la consulta.
- Emita un evento begin.
- Dibuje algo.
- Emita un evento final.
A continuación se muestra la secuencia de código correspondiente:
IDirect3DQuery9* pOcclusionQuery;
DWORD numberOfSamplesDrawn;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery);
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue(D3DISSUE_BEGIN);
// API render loop
...
Draw(...)
...
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue(D3DISSUE_END);
// Force the driver to execute the commands from the command buffer.
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pOcclusionQuery->GetData( &numberOfSamplesDrawn,
sizeof(DWORD), D3DGETDATA_FLUSH ))
;
// To get the number of pixels drawn when multisampling is enabled,
// divide numberOfSamplesDrawn by the sample count of the render target.
Estas líneas de código hacen varias cosas:
- Llame a GetData para devolver el número de píxeles o muestras dibujados.
- Especifique D3DGETDATA_FLUSH para permitir que el recurso realice la transición de la consulta al estado señalado.
- Sondee el recurso de consulta mediante una llamada a GetData desde un bucle. Siempre que GetData devuelva S_FALSE, significa que el recurso aún no ha devuelto la respuesta.
El valor devuelto de GetData básicamente le indica en qué estado está la consulta. Los valores posibles son S_OK, S_FALSE y un error. No llame a GetData en una consulta que esté en estado de creación.
- S_OK significa que el recurso (GPU o controlador o tiempo de ejecución) ha finalizado. La consulta vuelve al estado señalado. La respuesta (si existe) se devuelve mediante GetData.
- S_FALSE significa que el recurso (GPU o controlador o tiempo de ejecución) aún no puede devolver una respuesta. Esto podría deberse a que la GPU no ha finalizado o aún no ha visto el trabajo.
- Un error significa que la consulta ha generado un error desde el que no se puede recuperar. Esto podría ser el caso si el dispositivo se pierde durante una consulta. Una vez que una consulta ha generado un error (distinto de S_FALSE), la consulta debe volver a crearse, lo que reiniciará la secuencia de consulta desde el estado señalado.
En lugar de especificar D3DGETDATA_FLUSH, que proporciona más información de up-to-date, podría proporcionar cero, que es una comprobación más ligera si la consulta está en estado emitido. Proporcionar cero hará que GetData no vaciar el búfer de comandos. Por este motivo, se debe tener cuidado para evitar bucles infinitos (consulte GetData para obtener más información). Dado que el tiempo de ejecución pone en cola el trabajo en el búfer de comandos, D3DGETDATA_FLUSH es un mecanismo para vaciar el búfer de comandos en el controlador (y, por lo tanto, la GPU; consulte Llamadas API direct3D de generación de perfiles precisas de Direct3D (Direct3D 9)). Durante el vaciado del búfer de comandos, una consulta puede pasar al estado señalado.
Ejemplo: una consulta de eventos
Una consulta de eventos no admite un evento begin.
- Cree la consulta.
- Emita un evento final.
- Sondee hasta que la GPU esté inactiva.
- Emita un evento final.
IDirect3DQuery9* pEventQuery = NULL;
m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
// Add an end marker to the command buffer queue.
pEventQuery->Issue(D3DISSUE_END);
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pEventQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ))
;
... // API calls
// Add an end marker to the command buffer queue.
pEventQuery->Issue(D3DISSUE_END);
// Force the driver to execute the commands from the command buffer.
// Empty the command buffer and wait until the GPU is idle.
while(S_FALSE == pEventQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ))
;
Esta es la secuencia de comandos que usa una consulta de eventos para generar perfiles de llamadas de interfaz de programación de aplicaciones (API) (consulte Generación precisa de perfiles de llamadas API de Direct3D (Direct3D 9)). Esta secuencia usa marcadores para ayudar a controlar la cantidad de trabajo en el búfer de comandos.
Tenga en cuenta que las aplicaciones deben prestar especial atención al gran costo asociado al vaciado del búfer de comandos, ya que esto hace que el sistema operativo cambie al modo kernel, lo que conlleva una penalización de rendimiento considerable. Las aplicaciones también deben tener en cuenta la desperdiciación de ciclos de CPU esperando a que se completen las consultas.
Las consultas son una optimización que se usará durante la representación para aumentar el rendimiento. Por lo tanto, no es beneficioso dedicar tiempo a esperar a que finalice una consulta. Si se emite una consulta y si los resultados aún no están listos en el momento en que la aplicación los comprueba, el intento de optimización no se realizó correctamente y la representación debería continuar como normal.
El ejemplo clásico de esto es durante la selección de oclusión. En lugar de la mientras bucle anterior, una aplicación que usa consultas puede implementar la selección de oclusión para comprobar si una consulta ha finalizado por el momento en que necesita el resultado. Si la consulta no ha finalizado, continúe (como escenario de peor caso) como si el objeto que se está probando no se ocluyese (es decir, es visible) y lo represente. El código tendría un aspecto similar al siguiente.
IDirect3DQuery9* pOcclusionQuery = NULL;
m_pD3DDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery );
// Add a begin marker to the command buffer queue.
pOcclusionQuery->Issue( D3DISSUE_BEGIN );
... // API calls
// Add an end marker to the command buffer queue.
pOcclusionQuery->Issue( D3DISSUE_END );
// Avoid flushing and letting the CPU go idle by not using a while loop.
// Check if queries are finished:
DWORD dwOccluded = 0;
if( S_FALSE == pOcclusionQuery->GetData( &dwOccluded, sizeof(DWORD), 0 ) )
{
// Query is not done yet or object not occluded; avoid flushing/wait by continuing with worst-case scenario
pSomeComplexMesh->Render();
}
else if( dwOccluded != 0 )
{
// Query is done and object is not occluded.
pSomeComplexMesh->Render();
}
Temas relacionados