|
|
我对D3D中的"顶点缓存_vertex buffers"的概念感到迷惑,特别是其分配和锁定的操作,不知道这些名称的含义是什么?
当"allocating vertex buffers_分配顶点缓存"时:
当使用 STATIC标识分配顶点缓存时,这块缓存位于显存中。它的典型应用是只写一次并不被读回内存的情况。
只有当标志 D3DUSAGE_DYNAMIC被设置时 D3DUSAGE_WRITEONLY标志才有意义。
如果使用DYNAMIC标志创建缓存 (使用D3DUSAGE_DYNAMIC创建的缓存) ,并且D3DUSAGE_WRITEONLY 被使用,缓存被分配到显存中。
如果使用DYNAMIC标志创建缓存 (使用D3DUSAGE_DYNAMIC创建的缓存) ,并且D3DUSAGE_WRITEONLY 不被使用, 缓存被分配到AGP 缓存中。(CPU从AGP缓存中读取的速度比显存中快,但比内存慢,是个很好的折中)
如果没有足够的显存,顶点缓存被分配到AGP缓存中;如果AGP缓存也不够时,创建失败,除非使用POOL_ MANAGED 创建。在这种情况下,D3D的运行库会释放足够多的显存,用来创建顶点缓存,并在内存中保存创建的缓存的一个拷贝。那些被运行库释放的显存,在需要它们时可以从内存中复制到显存中。注意标志POOL_ MANAGED 并不被发送到驱动程序,因为这是D3D的附加的功能。
对于NV1X 系列的GPUs, 在进行多数据流渲染得时候,如果有一个顶点缓存位于AGP缓存中,所有的其他位于显存中的顶点缓存会被移动到AGP缓存中。
当" locking vertex buffers_锁定顶点缓存"时:
如果顶点缓存的创建标志是POOL_DEFAULT:
如果没有指定任何标志,程序将被暂停,因为它强制程序和GPU同步操作。->低效
如果指定D3DLOCK_NOOVERWRITE 标志,应用程序不会改变缓存区已存在的内容,运行库会在以后继续使用这块缓存。当应用程序调用这个函数时,驱动程序立即返回。->高效
如果指定D3DLOCK_DISCARD 标志,程序将会更新整个缓存的值,实际上是分配一块新的缓存,即驱动程序重命名它。->高效
[注解:因为CPU和GPU是异步的操作,所以当CPU通过系统总线和GPU同步时,需要等到GPU把当前的工作做完。例如,当GPU正在对一块缓存进行DMA操作时,由于CPU并不对GPU操作的那块缓存进行操作,所以CPU可以和GPU一起工作。当不指定操作标志时,CPU等待GPU完成工作,所以低效。如果指定D3DLOCK_NOOVERWRITE,由于CPU只更新分配的缓存中剩余的缓存,而不更新已经写入的顶点值,所以在CPU写入的时候,GPU可以并行的对那些已经存在的顶点值进行DMA等操作,所以高效;如果使用D3DLOCK_DISCARD 标志,说明当前分配的缓存大小不够了,需要重新分配更大的缓存,CPU对这些新分配的缓存区域进行写操作,GPU这时可能还在异步处理旧的缓存区,所以这种调用也是高效的。调用完毕,收回释放的缓存。]
如果顶点缓存的创建标志是POOL_ MANAGED:
驱动程序对这个标志不做任何响应。
对于这些标志,运行库会在系统内存中创建一个缓存的备份(在必要的时候使用)并且在需要这些缓存的渲染操作,执行的前一刻,把它们从内存复制到显存中。
/******************************************/
I'm confused about vertex buffers in Direct3D. What do the various parameters mean when allocating and locking vertex buffers?
When allocating vertex buffers:
If the buffer is created as STATIC (D3DUSAGE_DYNAMIC not specified), it goes into video memory, period. These vertex buffers are meant to be written once and not read back.
The D3DUSAGE_WRITEONLY flag has a meaning only when the D3DUSAGE_DYNAMIC flag is set.
If the buffer is created as DYNAMIC (D3DUSAGE_DYNAMIC specified) and D3DUSAGE_WRITEONLY is specified, it goes into video memory.
If the buffer is created as DYNAMIC (D3DUSAGE_DYNAMIC specified) and D3DUSAGE_WRITEONLY is not specified, it goes into AGP memory. (CPU reads faster from AGP than video memory, but not as fast as from system memory, good compromise)
If there is no more video memory the buffer goes into AGP memory; if there is no more AGP memory, creation fails unless the buffer’s allocation pool is POOL_ MANAGED in which case the RUNTIME will actually free as many other buffers as necessary until the creation does not fail anymore and keep a copy of the vertex buffer in system memory; the freed buffers will get re-created whenever they are used. Note that the POOL_ MANAGED flag is not passed to the driver.
For NV1X GPUs only, any vertex buffer located in video memory may get demoted to AGP memory in case of multi-stream rendering: If the APPLICATION renders from several vertex buffers and one of them is in AGP memory, every other one that is in video memory will get dumped into AGP.
When locking vertex buffers:
If the vertex buffer’s allocation pool is POOL_DEFAULT:
If no flag is specified: The lock can be blocking because it forces a synch between the GPU and the app -> bad.
If the D3DLOCK_NOOVERWRITE flag is specified, the RUNTIME reuses the locks because the APPLICATION promises not to overwrite data that is being rendered. The DRIVER receives the lock calls, but returns immediately -> efficient.
If the D3DLOCK_DISCARD flag is specified, the APPLICATION will refresh the whole content of the buffer. This allows the DRIVER to rename -> efficient
If the vertex buffer’s allocation pool is POOL_ MANAGED:
The DRIVER never sees the locks on these ones.
For those buffers, the RUNTIME has created a cache in system memory (used to restore the buffer after a driver loss) and updates the DRIVER’s vertex buffer in video memory with the "buffer blit" method right before it is used by a rendering operation.
|
|