zoukankan      html  css  js  c++  java
  • d3d9查询(Queries Direct3d9)

    D3D9查询(Queries Direct3d9)


    来源:d3d9帮助文档 Queries(Direct3d9)
    翻译:游蓝海(http://blog.csdn.net/you_lan_hai
    说明:费了好大劲,终于看懂了d3d9 queries,翻译一下跟大家共享。第一次翻译文章,有很多地方不准确,请多多见谅。

    概述

           有很多种查询,用来查询资源的状态,这些资源状态包括图形处理单元(GPU)的状态、驱动状态、运行时状态。为了理解不同类型的查询,你需要先理解查询状态。下面的状态流图,说明了每个查询的状态。

    查询状态图
        图表列举出了3种状态(Signaled State, Building State, Issued State),分别用圆圈表示。实线表示应用程序驱动事件引发的状态传递,虚线表示资源驱动事件将一个查询从完成状态(Issued State)切换到了就绪状态(Signaled State),每种状态都有不同的用处:
        ·就绪状态(Signaled State):像是一个空闲的状态。查询对象已经生成,等待应用程序来完成此次查询。当查询结束,查询状态转变为就绪状态时,就可以获取到查询结果了。
        ·创建状态(Building State): 像是一个暂存区域。在创建状态,查询已经被发起(通过调用D3DISSUE_BEGIN),但还没有转换到完成状态。当应用程序申明查询结束(通过调用D3DISSUE_END),查询便转换到了完成状态。
        ·完成状态(Issued State): 表示被查询的资源已经接管了查询。当资源完成工作后,会将状态机转换到就绪状态。在完成阶段,应用程序必须检测是否已经转变成就绪状态,如果是就绪状态,那么GetData返回的就是需要的查询结果了。

        一些查询需要开始和结束事件,但是有些仅需要结束事件。仅需要一个结束事件的查询,会在一些暗含的事件发生后自动开始。所有的查询都会返回一个结果,除了事件查询(event query)总是会返回TRUE。


    创建查询(Create a query)

        在创建查询之前,你可以检查运行时(runtime)是否支持此查询,调用CreateQuery,并传入一个NULL,如下:
    IDirect3DQuery9* pEventQuery;
    
    // Create a device pointer m_pd3dDevice
    
    // Create a query object
    HRESULT hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, NULL);
    如果该查询可以被创建,改方法返回成功码;否则,返回一个错误码。一旦CreateQuery调用成功,你可以这样创建一个查询:
    IDirect3DQuery9* pEventQuery;
    m_pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);

    如果函数调用成功,一个查询对象就创建完成了。查询初始为就绪状态,等待被激活。当查询对象使用完毕之后,像其他d3d对象一样,释放掉它。


    发起查询Issue a Query

    应用程序通过发起查询来改变一个查询的状态,这里有一个发起查询的例子:

    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);

    当发起之后,一个处于就绪状态的查询,将会这样改变:

    发起类型 查询变成这样 . . .
    D3DISSUE_BEGIN 创建状态(Building state).
    D3DISSUE_END 完成状态(Issued state).

    发起之后,一个处于创建状态的查询,将会这样改变:
    发起类型 查询变成这样 . . .
    D3DISSUE_BEGIN (仍然是创建状态,会 重置查询框架 .)
    D3DISSUE_END 完成状态.

    发起之后,一个处于完成状态的查询,将会这样改变:
    发起类型 查询变成这样 . . .
    D3DISSUE_BEGIN 创建状态并且重置查询框架。
    D3DISSUE_END 放弃已经存在的查询,仍然是完成状态。


    检查查询状态以及获得查询结果(Check the Query State and Get the Answer to the Query)

    GetData做了两件事情:
    1.通过函数返回值,返回查询状态。
    2.通过参数pData,返回查询结果。

    针对三种查询状态,GetData的返回值如下:

    查询状态  GetData 返回值
    Signaled S_OK
    Building Error code
    Issued S_FALSE

    例如,当查询处于完成状态时,查询结果不可用,GetData会返回S_FALSE。当资源完成它的工作并且应用程序已经发起过查询结束事件,资源将使查询状态转为就绪状态。在就绪状态中,如果GetData返回S_OK,则表示查询结果已经写入了pData中。举个例子,以下查询事件,返回了一次渲染中绘制的像素个数:
        ·创建查询。
        ·发起查询开始事件。
        ·渲染一些东西。
        ·发起查询结束事件。

    下面是该查询的源码:

    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 ))
        ;

    这些代码做了这些事情:

    ·调用GetData获取已经绘制的像素个数。
    ·设定 D3DGETDATA_FLUSH参数,表明允许资源将查询转换成就绪状态。
    ·不断的检查资源,只要返回S_FALSE,就表示还没有拿到结果。


    GetData返回了当前的查询状态。他的返回值可能是S_OK,S_FALSE或者是一个错误码。注意,不要在创建状态调用GetData.
    • S_OK表示资源 (GPU or driver, or runtime)  已经完成了工作,此时查询已经变成了就绪状态,GetData已经返回了查询结果。
    • S_FALSE 表示资源 (GPU or driver, or runtime) 目前还不能返回结果.。这表示GPU还没完成工作或者还没执行到查询。
    • 出现错误,表示查询出现了致命错误,这可能是设备丢失导致的。如果查询已经出现了错误(不是S_FALSE),查询必须要重新创建,然后从就绪状态重新开始。
        除了指定 D3DGETDATA_FLUSH参数外,也可以传入0,进行轻量级的查询状态检测。传入0时,GetData将不会刷新命令缓冲区,因此,需要小心查询陷入死循环。当运行时工作在命令缓冲区时,D3DGETDATA_FLUSH模式将有一次机会刷新缓冲区,将查询转变成就绪状态。


    例子: 事件查询

    事件查询不支持begin event.

    • 创建查询。
    • 产生一个结束事件。
    • 一直检测,直到GPU完成工作。
    • 产生一个结束事件。
    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 ))
        ;

    应用程序需要特别注意刷新命令缓冲区产生的开销,这源于操作系统会切换到内核模式,因此产生了相当大的性能损耗。应用程序也应该意识到等待查询结束时浪费的cpu循环。

        在渲染期间,查询可作为优化来增加性能。花费时间等待查询结束没有益处。取代上面循环的位置,如果查询已经是完成状态,但是应用程序还没有拿到查询结果,优化尝试失败,渲染应该像平常一样继续进行。经典的例子就是隐藏面剔除。如果查询完成,应用程序可以使用查询结果来实现隐藏面剔除;如果查询没有完成,这时跳过隐藏面剔除测试,直接渲染物体,就仿佛是测试不成立,物体没有被裁减。

    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();
    }




  • 相关阅读:
    Java 调用存储过程、函数
    Java BaseDao
    写好Java代码的30条经验总结
    15款Java程序员必备的开发工具
    Oracle基础 表分区
    Oracle基础 索引
    Oracle基础 触发器
    Oracle基础 程序包
    Oracle基础 自定义函数
    Oracle基础 存储过程和事务
  • 原文地址:https://www.cnblogs.com/ygxsk/p/7693997.html
Copyright © 2011-2022 走看看