zoukankan      html  css  js  c++  java
  • D3D Lock Pool

    一 pool

    D3D RUTIME的内存类型,分为3种,VIDEO MEMORY(VM)、AGP MEMORY(AM)和SYSTEM MEMORY(SM),
    所有D3D资源都创建在这3种内存之中,在创建资源时,我们可以指定如下存储标志,
    D3DPOOL_DEFAULT、D3DPOOL_MANAGED、D3DPOOL_SYSTEMMEM和D3DPOOL_SCRATCH。
    VM就是位于显卡上的显存,CPU只能通过AGP或PCI-E总线访问到,读写速度都是非常慢的,
    CPU连续写VM稍微快于读,因为CPU写VM时会在CACHE中分配32或64个字节(取决于CACHE LINE长度)
    的写缓冲,当缓冲满后会一次性写入VM;SM就是系统内存,CPU读写都非常快,
    因为SM是被CACHE到2级缓冲的,但GPU却不能直接访问到系统缓冲,所以创建在SM中的资源,
    GPU是不能直接使用的;AM是最麻烦的一个类型,AM实际也存在于系统内存中,
    但这部分MEM不会被CPU CACHE,意味着CPU读写AM都会写来个CACHE MISSING然后才通过内存总线访问AM,
    所以CPU读写AM相比SM会比较慢,但连续的写会稍微快于读,
    原因就是CPU写AM使用了“write combining”,而且GPU可以直接通过AGP或PCI-E总线访问AM。

    如果我们使用D3DPOOL_DEFAULT来创建资源,则表示让D3D RUNTIME根据我们指定的资源使用
    方法来自动使用存储类型,一般是VM或AM,系统不会在其他地方进行额外备份,当设备丢失后,
    这些资源内容也会被丢失掉。但系统并不会在创建的时候使用D3DPOOL_SYSTEMMEM或D3DPOOL_MANAGED
    来替换它,注意他们是完全不同的POOL类型,创建到D3DPOOL_DEFAULT中的纹理是不能被CPU LOCK的,
    除非是动态纹理。但创建在D3DPOOL_DEFAULT中的VB IB RENDERTARGET BACK BUFFERS可以被LOCK。
    当你用D3DPOOL_DEFAULT创建资源时,如果显存已经使用完毕,则托管资源会被换出显存来释放足够的空间。
    D3DPOOL_SYSTEMMEM和D3DPOOL_SCRATCH都是位于SM中的,其差别是使用D3DPOOL_SYSTEMMEM时,
    资源格式受限于Device性能,因为资源很可能会被更新到AM或VM中去供图形系统使用,
    但SCRATCH只受RUNTIME限制,所以这种资源无法被图形系统使用。
    D3DRUNTIME会优化D3DUSAGE_DYNAMIC 资源,一般将其放置于AM中,但不敢完全保证。
    另外为什么静态纹理不能被LOCK,动态纹理却可以,都关系到D3D RUNTIME的设计,
    在后面D3DLOCK说明中会叙述。

    D3DPOOL_MANAGED表示让D3D RUNTIME来管理资源,被创建的资源会有2份拷贝,一份在SM中,
    一份在VM/AM中,创建的时候被放置L在SM,在GPU需要使用资源时D3D RUNTIME自动将数据拷贝到
    VM中去,当资源被GPU修改后,RUNTIME在必要时自动将其更新到SM中来,
    而在SM中修改后也会被UPDATE到VM去中。所以被CPU或者GPU频发修改的数据,
    一定不要使用托管类型,这样会产生非常昂贵的同步负担。当LOST DEVICE发生后,
    RESET时RUNTIME会自动利用SM中的COPY来恢复VM中的数据

    二 lock

    如果LOCK DEFAULT资源会发生什么情况呢?DEFAULT资源可能在VM或AM中,如果在VM中,
    必须在系统内容中开辟一个临时缓冲返回给数据,当应用程序将数据填充到临时缓冲后,
    UNLOCK的时候,RUNTIME会将临时缓冲的数据传回到VM中去,如果资源D3DUSAGE属性不是WRITEONLY的,
    则系统还需要先从VM里拷贝一份原始数据到临时缓冲区,这就是为什么不指定WRITEONLY会降低
    程序性能的原因。CPU写AM也有需要注意的地方,因为CPU写AM一般是WRITE COMBINING,
    也就是说将写缓冲到一个CACHE LINE上,当CACHE LINE满了之后才FLUSH到AM中去,
    第一个要注意的就是写数据必须是WEAK ORDER的(图形数据一般都满足这个要求),
    据说D3DRUNTIME和NV DIRVER有点小BUG,就是在CPU没有FLUSH到AM时,GPU就开始绘制相关资源产生
    的错误,这时请使用SFENCE等指令FLUSH CACHE LINE。第二请尽量一次写满一个CACHE LINE,
    否则会有额外延迟,因为CPU每次必须FLUSH整个CACHE LINE到目标,但如果我们只写了LINE中部分字节,
    CPU必须先从AM中读取整个LINE长数据COMBINE后重新FLUSH。第三尽可能顺序写,
    随机写会让WRITE COMBINING反而变成累赘,如果是随机写资源,不要使用D3DUSAGE_DYNAMIC创建,
    请使用D3DPOOL_MANAGED,这样写会完全在SM中完成。

    普通纹理(D3DPOOL_DEFAULT)是不能被锁定的,因为其位于VM中,只能通过UPDATESURFACE和
    UPDATETEXTURE来访问,为什么D3D不让我们锁定静态纹理,却让我们锁定静态VB IB呢?我猜测可能
    有2个方面的原因,第一就是纹理矩阵一般十分庞大,且纹理在GPU内部已二维方式存储;
    第二是纹理在GPU内部是以NATIVE FORMAT方式存储的,并不是明文enRGBA格式。动态纹理因为表明
    这个纹理需要经常修改,所以D3D会特别存储对待,高频率修改的动态纹理不适合用动态属性创建,
    在此分两种情况说明,一种是GPU写入的RENDERTARGET,一种是CPU写入的TEXTURE VIDEO,
    我们知道动态资源一般是放置在AM中的,GPU访问AM需要经过AGP/PCI-E总线,速度较VM慢许多,
    而CPU访问AM又较SM慢很多,如果资源为动态属性,意味着GPU和CPU访问资源会持续的延迟,
    所以此类资源最好以D3DPOOL_DEFAULT和D3DPOOL_SYSTEMMEM各创建一份,自己手动进行双向更新更好。
    千万别 RENDERTARGET以D3DPOOL_MANAGED 属性创建,这样效率极低,原因自己分析。
    而对于改动不太频繁的资源则推荐使用DEFAULT创建,自己手动更新,因为一次更新的效率损
    失远比GPU持续访问AM带来的损失要小。

    不合理的LOCK会严重影响程序性能,因为一般LOCK需要等待COMMAND BUFFER前面的绘制指令全部
    执行完毕才能返回,否则很可能修改正在使用的资源,从LOCK返回到修改完毕UNLOCK这段时间GPU
    全部处于空闲状态,没有合理使用GPU和CPU的并行性,DX8.0引进了一个新的LOCK标志D3DLOCK_DISCARD,
    表示不会读取资源,只会全写资源,这样驱动和RUNTIME配合来了个瞒天过海,立即返回给应用程序
    另外块VM地址指针,而原指针在本次UNLOCK之后被丢弃不再使用,这样CPU LOCK无需等待GPU使用
    资源完毕,能继续操作图形资源(顶点缓冲和索引缓冲),这技术叫VB IB换名(renaming)。

  • 相关阅读:
    regasm.exe程序集注册工具
    C#获取CPU温度
    检测已连接显示器
    防火墙规则修改
    WPF中播放声音
    python获取火狐浏览器的历史记录
    python学习-[小甲鱼]零基础入门教学
    推荐一些常用感觉不错的jQuery插件
    HTML5本地存储 Web Storage
    Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。
  • 原文地址:https://www.cnblogs.com/lancidie/p/1848444.html
Copyright © 2011-2022 走看看