Accurately Profiling Direct3D API Calls 笔记

来源:互联网 发布:莞城金域名苑怎么样 编辑:程序博客网 时间:2024/06/10 07:23

Accurately Profiling Direct3D API Calls (Direct3D 9)

笔记

【Microsoft DirectX SDK (August 2009) => Windows DirectX Graphics Documentation => Accurately Profiling Direct3D API Calls (Direct3D 9)】

(本人对此文进行了翻译,英语水平有限不将全文共享了,仅把文中一些语句摘录且夹杂了自己的理解,请大家帮忙指出理解上的问题,还有几个疑问。谢谢)

每个API调用要经过几个组件:

 

应用程序=>Direct3D 运行时=>软件驱动=>显卡=>显示器屏幕

 

API命令在运行时被“翻译”成“设备无关格式”。

“设备无关格式”指令在驱动中被“翻译”成硬件指令,传送到GPU。

 

API命令本身不依赖于硬件,但是应用程序应该知道显卡支持哪些特征。

软件驱动使用硬件的关于显卡的具体知识(能力)转换设备无关命令为一序列显卡命令。

驱动会将指令优化,再发送到显卡。使得显卡更有效率。

在显卡接受到指令后,驱动将控制权返回给运行时。即:CPU工作已经全部完成。

运行时和驱动内部都存在优化。

 

CPU 和 GPU 是并行工作的

 

CPU和GPU通常有2个不同的速度,彼此独立。

GPU将图形工作从CPU中移除,以便减轻CPU负载,且可以进行并行工作。

为了调整出一个高性能的图形应用程序,需要测量CPU和GPU两个的性能,并且平衡两个处理器之间的工作。

 

测量状态改变需要注意渲染序列

Direct3DDevice9::DrawPrimitive、IDirect3DDevice9::DrawIndexedPrimitive 命令,像IDirect3DDevice9::SetTextureture、IDirect3DDevice9::SetVertexDeclaration、和 IDirect3DDevice9::SetRenderState

这些命令都会触发管线状态改变。

优化运行时和驱动,是通过减少在其上的工作需求数量。

 

因,驱动保存一个当前状态。且,驱动的工作方式是:延期工作直到必须执行(懒惰算法)。所以驱动可以删除冗余的状态改变。

 

怎样准确分析一个Direct3D渲染序列

分析时间开销要懂得如何排除干扰。

分析转换的结果,计算时钟周期更优于计算真实时间,因为在速度不同的CPU下执行相同指令,时间会不同,但时钟周期相同。

运行时通过命令缓冲区来优化,使其尽可能减少模式转换。好的策略是将渲染序列的指令多于模式转换。 

应用程序将API传递给运行时,运行时翻译成“设备无关命令”并将命令添加到运行时内的“命令缓冲区”

当命令缓冲区被填满时,运行时将所有“设备无关指令”一次发送到驱动。

 

清空命令缓冲区,将触发一次模式从运行时(运行在用户模式)到驱动(运行在内核模式)的转换。

【用户模式 user mode】非特权处理模式,处理应用程序代码。没有获取系统数据的权限(除非通过系统服务)

【内核模式 kernel mode】特权处理模式。驱动或线程运行在内核模式,可以访问所有系统内存,直接访问硬件,和CPU指令执行,I/O硬件。

 

模式转换的开销大于单个API命令的调用开销

“命令缓冲区”是运行时的优化策略,针对模式过渡带来的开销。

运行时每添加一个命令到命令缓冲区后,如果命令缓冲区没有充满(即:不执行从运行时到驱动的模式转换),控制权立即交还给应用程序。如果命令缓冲区已经填满,触发模式转换,控制权交由驱动控制。

分析器无法得知是否进行过模式转换。

1.清空命令缓冲区,将指令传送到驱动,运行时过渡到驱动

2.驱动处理所有设备无关格式的指令

3.驱动过渡到运行时,控制权交回给运行时。

4.运行时处理将DrawPrimite翻译成设备无关格式,且添加到命令缓冲区

 

查询机制可以控制命令缓冲区的两个属性:

1.  什么时候清空命令缓冲区

2.  多少工作在缓冲区中

1.  清空命令缓冲区

2.  开始计时

3.  应用程序将API传入运行时,运行时翻译API为设备无关格式,

4.  强行清除命令缓冲区,执行运行时翻译设备无关命令为硬件指令,且传送硬件指令到显卡。循环等待直到GPU空闲。此后CPU的工作完成,返回控制权。

5.  结束计时

 

6.IDirect3DQuery9::GetData 直到GPU空闲,才会返回S_OK。

7.  While循环等待,是为了在第一时间得到GPU空闲的信息,也是CPU工作全部完成的时刻。

 

下列情况都将导致模式转变:

1.顶点缓冲区、索引缓冲区、纹理等调用Lock函数,会引起模式转换。

2.当设备、顶点缓冲区、索引缓冲区、纹理被“创建”或“销毁”时,导致模式转换。

3.当ValidateDevice被调用

4.当Present被调用

5.当命令缓冲区被填满

6.IDirect3DQuery9::GetData(…D3DGETDATA_FLUSH…)函数调用。

在渲染序列小心观察这些条件。

每次模式过渡被添加,1万周期的驱动工作将被添加。

运行时可能改变命令缓冲区的大小。影响工作总量。(问:什么情况下会改变,改变的依据是什么?)

在没做任何事情的情况下,模式转换的消耗将近1万周期。应采用增加渲染序列内的工作,来尽可能减少模式转换次数,减少总开销。

 

例子中使用两种大小、格式相同的纹理,首先,避免了因纹理相同带来的运行时优化,其次,不会引起其它的状态改变。

使用高性能的计数器QueryPerformanceCounter来测量每个API命令的执行时间。

使用QueryPerformanceFrequency和CPU时钟频率来转换成每个API调用的时间周期。

 

分析Direct3D的状态变化

除了 Draw*Primitive以外还有一些API命令会触发状态改变。

每次状态改变,管线都要做相同的工作。

有一些状态改变直接影响了管线执行的工作数量。比如:当Z_Test开启测试时,每个象素都要进行新象素Z值与已有象素Z值的对比。而,关闭Z_Test测试,每个象素都没有进行Z值测试,且写入更快。两种状态的不同,明显体现CPU和GPU工作量上存在较大差异。

在驱动中,有一个占位标志(dirty bit)描述状态。此后应该也是靠这个存储的状态来优化冗余。

 

设置相同的状态改变,一定会被忽略。

状态改变在运行时、驱动或GPU中被优化。每次调用状态改变并没用立即执行,而是采用标记的方式,待Draw指令被执行,状态改变才被真正执行。

这是一种好方法,延期工作直到必须执行。

 

驱动是在不断更新改善的(即:适用于某些版本的最新驱动更新),所以优化列表在新的驱动中也会不断增加。

 

警惕状态改变优化

运行时会检测、合并两个Draw*Primite为一个有效指令。这样节省了驱动50%的时间,因为只需要执行一次Draw*Primite。

运行时会检测连续的Draw*Primite且类型为D3DPT_TRIANGLELIST的命令,如果它们在相同顶点缓冲区中存在连续的顶点,那么运行时会合并两个Draw*Primite命令

遇到符合:

【指定起始顶点 = 前一个开始顶点 + 前一个图元数量*3】的情况。两个Draw*Primite被合并。

应该将显而易见的冗余工作排除,这样可以有效的减少工作量。

 

有些指令只会给CPU造成很小的负担,但是会给GPU造成很大的工作量。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 车辆被恶意损坏怎么办 汽车划伤见底怎么办 汽车被刀片划伤怎么办 汽车被笔画了怎么办 车被划了一条线怎么办 微信附近人上门被骗怎么办 交通事故认定书不服怎么办 自动挡下坡刹车失灵怎么办 自动挡汽车刹车失灵怎么办 重车刹车失灵怎么办 12306买票待核验怎么办 单位分流不想去怎么办 公司降薪不同意怎么办 浙江违章扣分太多怎么办 船员进出青岛港怎么办 顶楼供暖不热怎么办 成都地铁掉东西怎么办 首都航空航班取消怎么办 猫不舒服躲起来怎么办 狗生病躲起来怎么办 猫咪躲起来了怎么办 vivo手机起热怎么办 vivo手机充电热怎么办 卵泡大于12个怎么办 到排卵期卵泡小怎么办 排卵期卵泡不长怎么办 排卵期没有优势卵泡怎么办 排卵期卵泡发育不好怎么办 成熟卵泡不排卵怎么办 排卵期子宫内膜薄怎么办 双侧卵巢增大怎么办 前列腺3个加号怎么办 武汉华美失败了怎么办 无档案人员怎么办退休 装修欠款不给怎么办 想贷款还信用卡怎么办 国企改私企员工怎么办 吸顶灯灯管坏了怎么办 led灯接触不良怎么办 灯开关接触不良怎么办 错过了买房时机怎么办