技术经验分享:d3d9查询(QueriesDirect3d9)

简介: 技术经验分享:d3d9查询(QueriesDirect3d9)

D3D9查询(Queries Direct3d9)


来源:d3d9帮助文档 Queries(Direct3d9)


翻译:游蓝海(


说明:费了好大劲,终于看懂了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),查询必须要重新创建,然后从就绪状态重新开始。


除了指定 //代码效果参考:http://www.jhylw.com.cn/330319977.html

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


}

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
4天前
技术经验分享:comparisonmethodviolates必现
技术经验分享:comparisonmethodviolates必现
技术经验分享:comparisonmethodviolates必现
|
3天前
|
SQL 存储 数据可视化
技术经验分享:ArcGISEngine开发之属性查询
技术经验分享:ArcGISEngine开发之属性查询
10 0
|
1月前
|
API 数据库
课6-匿踪查询和隐语PIR的介绍及开发实践
隐匿查询(PIR)允许用户从服务器检索数据而不暴露查询内容。类型包括单服务器与多服务器方案,以及Index PIR和Keyword PIR。隐语支持SealPIR用于单服务器Index PIR,压缩查询并支持多维和多查询处理。另外,它采用Labeled PSI实现单服务器Keyword PIR,优化了计算和通信效率,基于微软代码并扩展了功能,如OPRF、特定ECC曲线支持和预处理结果保存。隐语提供的PIR相关API包括`spu.pir_setup`和`spu.pir_query`。
课6-匿踪查询和隐语PIR的介绍及开发实践
|
1月前
|
敏捷开发 算法 安全
如何精准展现C/C++项目亮点:高级工程师面试指南
如何精准展现C/C++项目亮点:高级工程师面试指南
55 1
|
1月前
|
存储 数据库 流计算
TDengine 资深研发分享解决思路,长查询不再成为系统性能瓶颈!
本文探讨了如何应对和解决长查询问题,以提升 TDengine 在复杂查询场景下的表现。
73 0
|
6月前
|
关系型数据库 MySQL Java
阿里一线专家多年架构优化经验凝聚,手撸595页MySQL笔记
有史以来“最全”SpringBoot实战派,让开发像搭积木一样简单
|
9月前
|
消息中间件 缓存 分布式计算
真牛!阿里最新发布这份《亿级高并发系统设计手册》涵盖所有操作
前言 我们知道,高并发代表着大流量,高并发系统设计的魅力就在于我们能够凭借自己的聪明才智设计巧妙的方案,从而抵抗巨大流量的冲击,带给用户更好的使用体验。这些方案好似能操纵流量,让流量更加平稳得被系统中的服务和组件处理。 那我们改如何应对大流量的三种方式? 第一种方法:Scale-out。 第二种方法:使用缓存提升性能 第三种方法:异步处理 面试京东,阿里这些大厂遇到这些问题改怎么办? 秒杀时如何处理每秒上万次的下单请求? 如何保证消息仅仅被消费一次? 如何降低消息队列系统中消息的延迟?
|
消息中间件 Cloud Native 中间件
盘点2022:开源热度居高,技术思考与经验分享是开发者的最爱
阿里巴巴中间件陪伴大家又是一年了,春节即将到来,我们不禁回望,这一年我们留下了什么,又收获了什么。
127 0
|
SQL 机器学习/深度学习 人工智能
私藏!资深数据专家SQL效率优化技巧 ⛵
同一个数据分析的需求,不同人的SQL代码效率上会差别很大!本文给大家梳理集中效率优化方法,这也是数据岗面试的高频问题哦!快学起来~
808 2
私藏!资深数据专家SQL效率优化技巧 ⛵