D3d9 query (queries Direct3D9)
Source: d3d9 help documentation queries (Direct3D9) Translation: You blue ocean (http://blog.csdn.net/you_lan_hai) Description: a good effort, finally understand the d3d9 queries, translate to share with you. For the first translation of articles, there are many inaccuracies. Please forgive me.
There are many types of queries to query the status of resources, including the status, driver status, and runtime status of the graphics processing unit (GPU. To understand different types of queries, you must first understand the query status. The following status flow diagram shows the status of each query.
Query status chartThe chart lists three States (signaled state, building State, and issued State), which are represented in circles respectively. The solid line indicates the status transfer caused by the application driver event. The dotted line indicates that the resource driver event switches a query from the issued state to the signaled state ), each status has a different usage: signaled state, which is like a idle state. The query object has been generated. Wait for the application to complete the query. When the query is complete and the query status changes to ready, the query results can be obtained.
· Building State: A temporary storage area. In the creation status, the query has been initiated (by calling d3dissue_begin), but has not been switched to the completion status. When the application declares that the query is complete (by calling d3dissue_end), the query is switched to the completion state.
· Issued State: indicates that the queried resource has taken over the query. After the resources are finished, the state machine is converted to the ready state. In the completion phase, the application must check whether it has been changed to the ready state. If it is in the ready state, the query results returned by getdata are required.
Some queries need to start and end events, but some only need to end events. Only one query of the ending event is required and will automatically start after some implied events occur. A result is returned for all queries, and true is always returned for all queries except event queries.
Create a query)Before creating a query, you can check whether runtime supports this query, call createquery, and input a null value, as shown below:
IDirect3DQuery9* pEventQuery;// Create a device pointer m_pd3dDevice// Create a query objectHRESULT hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, NULL);
If the query can be created, a success code is returned by modifying the method; otherwise, an error code is returned. Once createquery is called successfully, you can create a query as follows:IDirect3DQuery9* pEventQuery;m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
If the function call is successful, a query objectThe creation is complete. The query is in the ready state, waiting for activation. After the query object is used up, release it like other d3d objects.
Initiate query issue a queryThe application initiates a query to change the status of a query. Here is an example of initiating a query:
IDirect3DQuery9* pEventQuery;m_pD3DDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);// Issue a Begin eventpEventQuery->Issue(D3DISSUE_BEGIN);or// Issue an End eventpEventQuery->Issue(D3DISSUE_END);
After the launch, a ready query will change as follows:
| Initiation type |
The query becomes like this... |
| D3dissue_begin |
Building state ). |
| D3dissue_end |
Issued state ). |
After the launch, a created query changes as follows:
| Initiation type |
The query becomes like this... |
| D3dissue_begin |
(It is still in the creation status and will reset the query framework .) |
| D3dissue_end |
Completion status. |
After the launch, a query in the completed status will change as follows:
| Initiation type |
The query becomes like this... |
| D3dissue_begin |
Create a status and reset the query framework. |
| D3dissue_end |
Discard an existing query and it is still in the completed status. |
Check the query status and obtain the query result (check the query state and get the answer to the query) getdata does two things: 1. Return the query status through the function return value. 2. the query result is returned through the pdata parameter.
For three query statuses, The getdata return value is as follows:
| Query status |
Getdata Return Value |
| Signaled |
S_ OK |
| Building |
Error Code |
| Issued |
S_false |
For example, if the query result is unavailable when the query is completed, getdata returns s_false. When the resource completes its work and the application has initiated the query end event, the resource changes the query status to ready. If getdata returns s_ OK, the query result is written to pdata. For example, the following query event returns the number of pixels drawn in a rendering: · Create query. · Initiate a query start event. · Rendering something. · Initiate the query end event.
The source code of the query is as follows:
IDirect3DQuery9* pOcclusionQuery;DWORD numberOfPixelsDrawn;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( &numberOfPixelsDrawn, sizeof(DWORD), D3DGETDATA_FLUSH )) ;
These codes do the following:
· Call getdata to obtain the number of pixels that have been drawn. · Set the d3dgetdata_flush parameter to allow the resource to convert the query to the ready state. · Continuously check resources. If s_false is returned, no result is obtained.
Getdata returns the current query status. The returned values may be s_ OK, s_false, or an error code. Note: Do not call getdata In the creation status.
- S_ OK indicates that the resources (GPU or driver, or runtime) have been completed, the query has changed to the ready state, and the query result has been returned by getdata.
- S_false indicates that resources (GPU or driver, or runtime) cannot return results yet .. This indicates that the GPU has not completed the work or the query has not been executed.
- An error occurs, indicating that a fatal error occurs in the query, which may be caused by the loss of the device. If an error has occurred in the query (not s_false), the query must be re-created and re-started from the ready state.
In addition to specifying the d3dgetdata_flush parameter, you can also pass in 0 for lightweight query status detection. When 0 is passed in, getdata will not refresh the command buffer. Therefore, you need to be careful when the query is in an endless loop. When running in the command buffer, the d3dgetdata_flush mode will have a chance to refresh the buffer and convert the query to the ready state.
Example: Event QueryEvent Query does not support begin event.
- Create a query.
- Generates an end event.
- Check until the GPU completes its work.
- Generates an end event.
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 )) ;
Applications need to pay special attention to the overhead produced by refreshing the command buffer. This is because the operating system switches to the kernel mode, resulting in a considerable performance loss. The application should also be aware of the CPU loop that is wasted when the query ends.
During rendering, queries can be used as Optimizations to increase performance. It is not helpful to wait for the query to end. Replace the previous loop position. If the query is completed but the application has not yet obtained the query result, the optimization attempt fails, and the rendering should continue as usual. The typical example is hidden area removal. If the query is complete, the application can use the query results to remove hidden surfaces. If the query is not complete, skip the hidden surface removal test and render the object directly, as if the test was not true, the object is not dropped.
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 scenariopSomeComplexMesh->Render();}else if( dwOccluded != 0 ){// Query is done and object is not occluded.pSomeComplexMesh->Render();}