江苏省电力建设一公司网站,济南建设工程业绩公示的网站,长沙网络营销外包,长沙有哪些招聘网站GPU性能调试#xff1a; 通常来说#xff0c;使用CPU时间事件来调试GPU是低效并且是不准确的。D3D API在多数命令下会阻塞#xff0c;甚至是Draw函数。它会在一些时间片上做一些真正的工作#xff0c;而这往往是不可预知的。因此#xff0c;GPU的性能调试只能用PIX或者是其… GPU性能调试 通常来说使用CPU时间事件来调试GPU是低效并且是不准确的。D3D API在多数命令下会阻塞甚至是Draw函数。它会在一些时间片上做一些真正的工作而这往往是不可预知的。因此GPU的性能调试只能用PIX或者是其他专用产品例如NVIDIA’s NVPerfHUD来进行。 显卡所用的内存 显卡所用的内存可以分为两大类本地的和非本地的相对于显卡来说。在显卡处理的某些数据类型的时候需要本地内存例如 帧缓冲。 非本地内存有时也成为AGP卡槽内存(AGP aperture)可以被显卡访问的某些数据类型所在的系统内存例如顶点缓冲。本地内存要比非本地内存快。 本地内存通常是在显卡内的但是有些显卡可以共享系统内存这通常是平衡速度和价格之间的选择。在这种情况下帧缓存可以存在于系统内存中而不是在本地内存中。这种技术下显卡处理某些数据的速度比不使用共享内存的要慢因为数据必须从I/O Bus例如PCI-Express上传输过来。但是这可以使显卡成本大大降低。在NVIDIA这种技术被称为TurboCache而ATI称之为HyperMemory。 着色器和着色模型 Shader是运行在GPU上的处理一些D3D流水管线上一些任务的程序。有三种类型的shader他们分别对应三种可编程的stage Vertex shader (顶点着色器VS) stage, geometry shader (几何着色器GS) stage, 还有pixel shader(像素着色器PS) stage。其中几何着色器只能在DX10平台上使用。 着色模型shader model是在GPU上运行的虚拟机。每个虚拟机定义被称为一种shader profile。并且包含了特定的汇编语言。 着色器的职责 着色器通常是流水管线中描述物体表面的部分。例如一种看起来像木头的材质被称为木头着色器wood shader。而在D3D中这些着色语言指令集可以做的事情远不止描述物体表面。他们可以用来计算光照矩阵转换顶点动画进行裁切动态生成新的几何物体等等。在Mental ray中shader按照职责可以划分为surface shader, light shader, shader shader, output shader等等。 在D3D中这三种着色器的职责划分并不是很明确。例如光照计算过可以在顶点着色器或者是像素着色器中完成这取决于应用程序的需求。因此包含各种着色器的着色器集合应运而生。他们链接起来定义了一个工作流水线。 关于Direct3D 9 资源和内存类型 D3D支持下列类型的资源纹理包括常规的和渲染目标render target顶点缓冲索引缓冲字体交换链swap chain状态组深度模板缓冲特效等等。 有四种内存类型池资源可以在这里分配 · 默认Default在显卡内存中包括AGP卡槽内存和本地显存。在设备丢失之后必须被释放重构。 · 托管Managed存在于系统内存中按需拷贝到显存。 · 系统SystemMem永远存在于系统内存中并且不能直接用于渲染。可以当作源或者目标拷贝。例如UpdateSurface和UpdateTexture。 · Scrach: 永远存在于系统内存中并且不会被设备大小或格式限制例如纹理的2的幂限制。不能把它放到显存中。 查找资源泄露 在关闭一个基于D3D的应用程序时D3D调试运行库会报告内存泄露。按照以下步骤定位泄漏点。 1. 在DirectX Control Panel中通常在DXSDK安装目录中可以找到启用“Use Debug Version of Direct3D 9”并且将Debug Output Level设置为”More”。确保Break on Memory Leaks被禁用。点击Apply。 2. 在VS中调试运行应用程序。在关闭应用程序之后查看VS的输出窗口Direct 3D9: (WARN) : Memory Address: 00xxxxxx, IAllocID xx dwSize xxxxxxxx;(pid xxxxx) 3. 每条记录对应了一个资源泄漏查看并记住ID然后在DirectX Control Panel中输入ID并且点击Apply。 4. 再次运行程序重复以上步骤。程序会在分配点中断你可以检查哪里遗忘释放。 5. 当你调试完成之后别忘了将Break On AllocID设置为0。 处理设备丢失Device Lost 一个D3D设备可以在很多情况下丢失例如从全屏向窗口转换一个电源管理事件按CTRLDELALT返回Windows Security Dialog。 必须采取措施去检查一个设备是否丢失丢失了之后如何恢复。 方法在某些地方调用IDirect3DDevice9::TestCooperativeLevel例如在每帧开始渲染之前调用。当发现设备丢失之后采取下列措施 1. 释放所有在Default内存中的资源 2. 释放其他没有和Default, Managed, SystemMem绑定的资源 3. 调用IDirect3DDevice9::TestCooperativeLevel去确认设备是否可以被重置如果能那么调用IDirect3DDevice9::Reset 如果不能继续等待然后再尝试 4. 重新创建需要的资源 渲染目标和交换链Render Targets and Swap Chains 一个渲染目标是一个用于保存在图形流水线输出像素的表面。也就是说它是一个颜色数组。一个设备可以有一个或者多个活动的渲染目标可以通过SetRenderTarget来启用。一个用于渲染目标的表面只能放在Default池中有三种渲染目标 · 渲染目标表面Render target surfaces通过CreateRenderTarget创建 · 渲染目标纹理Render target texturestongguo D3DUSAGE_RENDERTARGET标识来创建 · 交换链Swap chains 交换链就是后备缓冲的集合它们能够相继渲染到前缓冲也就是屏幕上。一个在交换链中的后备缓冲可以当作一个渲染目标赋给一个设备。但是不像其他的渲染目标交换链可以渲染到屏幕上因为交换链是和窗口/全屏大小绑定的。可以创建多个交换链注意更改默认交换链大小会造成设备丢失所以窗口程序会忽略默认的交换链而使用一个附加的交换链来避免这个问题。渲染目标可以被锁定用来读取但是当这个渲染目标是活动的话会影响系统性能。我们可以根据需要用IDirect3DDevice9::GetRenderTargetData来将一个在Default池中的渲染目标拷贝出来。可以使用IDirect3DDevice9::StrechRectangle在两个在显卡内存中的渲染目标中进行高效拷贝。 批处理Batching D3D的效率在很大程度上受制于传给API的几何模型数据的批次上。一个批处理就是调用一次DrawPrimitive或者DrawIndexPrimitive。在GPU可以处理数据前CPU花相当长时间来处理每批数据。现在常见的CPU和GPU可以参考以下数据 · 使用DX9CPU每秒可以处理50000批次使用DX10这个数据是200000。 · 在DX9中处理2000个三角形在CPU和GPU所花的时间大致相等。在DX10中这个数据是500。简单的着色程序使这个数字增加复杂的着色程序使这个数字减少。在CPU和GPU在同一个批次上花相同时间的情况下实例化Instancing可以提高三角形的输出能力。因为以上原因每个批次中处理数据的数量越大越好这样能够将三角形的吞吐量最大化。 在实践中具体有两种方式 · Consolidation合并将相同性质的几何元素合并起来通常是将一些属性进行排序的结果 · Instancing实例化将相同的几何物体经过一些细微的不同的变换后画出多个实例来。例如世界坐标系的转换和颜色转换。 顶点索引缓冲Vertex / Index Buffer 顶点和索引缓冲有两种类型静态和动态的。 一旦创建之后静态的缓冲使用起来比动态的快一倍。但是动态缓冲的加锁和解锁要比静态的快它们是为更改的每一帧设计的通常被存储在AGP卡槽内存中。经常对静态缓冲加解锁是不明智的因为只有等驱动完成了所有挂起的命令之后才能返回该缓冲的指针。如果经常这样做这会导致CPU和GPU很多不必要的同步这样性能将会变得很差。 为了得到最好的性能必须采用动态缓存。这样驱动可以继续进行并行渲染。使用DISCARD或者是NOOVERWRITING标志可以实现这一点这样驱动可以在更新数据的同时继续处理老的数据。 DISCARD这个标志说明应用程序不关心当前缓冲的内容。所以在缓冲被渲染的同时驱动可以给应用程序一个全新的缓冲。这个处理称之为“buffer renaming”。注意在实践中驱动倾向于不去释放“缓冲重命名”中所用的内存因此这个标志必须尽量少用。 NOOVERWRITE这表示对于之前添加的不带这个标志的数据应用程序不会更改它。例如应用程序只会在现有缓冲之后添加数据。所以驱动可以继续使用现有数据进行渲染。 CPU和GPU的并行处理 D3D runtime会将一堆命令做成命令串传给GPU这就允许GPU和CPU进行并行处理。这样也是硬件加速渲染这么高效的原因之一。但是在很多情况下CPU和GPU必须进行同步之后才能做进一步的处理。通常来说应该尽量避免这种情况因为这会导致整个流水管线的刷新大幅降低性能。例如对静态缓冲加锁这要求GPU先处理完所有的命令之后才能返回被锁缓冲的指针。如果用动态缓冲就可以避免就像前面讲过的一样。 有一些同步是不可避免的例如CPU可能会需要一些GPU还来不及处理的命令结果。在这种情况下用户会感到画面延迟Lag。要避免这种情况可以在GPU落后两三帧的情况下调用Present来强迫CPU等待GPU。因此调用Present可能比较慢但是正式它处理了必要的同步。 状态的更换State Changes 不管冗余还是不冗余状态的转换在到达驱动层的时候开销总是很大。所以在某些层面状态转换必须被过滤。一个对状态进行更换的函数调用并不一定会开销很大因为D3D Runtime很有可能缓冲这些转换请求在真正调用DrawPrimitive函数之前不会去执行它。多次的状态转换也不会加大开销因为只使用最后一个状态值。尽管如此状态转换还是应该尽量避免。某些状态转换会比其他的转换的开销更大。例如对于更改处于活动状态的顶点缓冲和像素缓冲会导致整个流水管线的刷新。因为在某些显卡上同一时间每个类型只有一个着色器可以处于活动状态。一个图形流水线可以很长花一段时间才能完成一个像素的渲染。因此整个流水线的刷新需要尽量避免。在不同的显卡上某个状态的更新的花费差别可能会很大。另外D3D的函数调用个数也必须尽量的少虽然它的开销不如达到驱动层的状态更改那么大。可以使用状态块来减少D3D API的调用状态块可以将状态的更改集中在一起并且可以重用。 转载于:https://www.cnblogs.com/ComputerG/archive/2011/03/10/1979608.html