glMapBuffer()和glBuffers,使用(void*)访问如何使用硬件?

use*_*501 3 hardware opengl

阅读OpenGL编程指南,第8版.

这实际上是一个硬件问题,实际上......

我来到一个关于OpenGL缓冲区的部分,据我所知,它们是在显卡内存中分配的内存空间,这是正确的吗?

如果是这样,我们如何使用glMapBuffer()获取指向读取或修改该内存的指针?据我所知,所有可能的内存地址(例如在64位系统上都有uint64_t num = 0x0; num = ~num;可能的地址)用于系统内存,如RAM/CPU端内存.

glMapBuffers()向某些内存返回一个void*.该指针如何指向显卡内存?特别是如果我有一个32位系统,超过4GB的RAM,然后一个显卡说2GB/4GB的内存.肯定没有足够的地址?!

dat*_*olf 6

这实际上是一个硬件问题,实际上......

不,这不对.你马上就会明白为什么.

我来到一个关于OpenGL缓冲区的部分,据我所知,它们是在显卡内存中分配的内存空间,这是正确的吗?

不完全的.您必须明白,虽然OpenGL让您真正接近实际硬件,但您仍然远远不能直接触摸它.glMapBuffer的作用是,它设置一个虚拟地址范围映射.在现代计算机系统上,软件不在物理地址上运行.而是使用虚拟地址空间(某种大小).这个虚拟地址空间看起来像是软件的一个大的连续内存块,而实际上它是由物理页面拼凑而成的.这些页面无论如何都可以实现,它们可以是实际的物理内存,它们可以是I/O内存,甚至可以由另一个程序在原位创建.其机制由CPU的内存管理单元与OS协作提供.

因此,对于每个进程,OS管理一个表,该表将进程虚拟地址空间的哪个部分映射到哪个页面处理程序.如果您正在运行Linux,请查看/proc/$PID/maps.如果你有一个程序在地图缓冲区之前和之后使用glMapBuffer读取(使用你的程序,不要调用系统)/proc/self/maps并查找差异.

据我所知,所有可能的内存地址(例如在64位系统上有uint64_t num = 0x0; num = ~num;可能的地址)用于系统内存,如RAM/CPU端内存.

什么让你有那个想法?无论谁告诉你(如果有人告诉你的话)应该被打耳光......很难.

你拥有的是一个虚拟地址空间.并且该地址空间与硬件侧的物理地址空间完全不同.实际上,虚拟地址空间的大小和物理地址空间的大小可以大不相同.例如,很长一段时间,有32位CPU和32位操作系统.但是已经有了超过4 GiB的系统内存.因此,虽然CPU只支持32位地址空间用于进程(指针的最大大小),但它可能已经为内存提供了36位物理地址线,以支持大约64 GiB的系统RAM; 然后,操作系统的工作就是手动切换那些额外的位,这样每个进程只能看到总共3个GiB的系统RAM(最大)进程可能会传播.像这样的技术被称为物理地址扩展(PAE).

此外,并非进程中的所有地址空间都由RAM支持.就像我已经解释的那样,地址空间映射可以得到任何支持.内存页面故障处理程序通常也会实现交换,即如果周围没有足够的可用RAM,它将使用HDD存储(实际上在Linux上,所有用户空间内存请求都由磁盘I/O缓存处理程序支持).此外,由于地址空间映射是按进程进行的,因此地址空间的某些部分是映射内核内存,它对所有进程(物理上)相同,并且也驻留在所有进程中的相同位置.从用户空间来看,这个地址空间映射是不可访问的,但是一旦系统调用进入内核空间就可以访问它; 是的,OS内核也在内部使用虚拟内存.它无法从可用的背景中进行广泛的选择(例如,如果网络驱动程序的内存由网络本身支持,则网络驱动程序将很难操作).

无论如何:在现代64位系统上,你有64位指针大小,而目前的硬件有48位物理RAM地址线.这留下了足够的空间,即16×48位(编辑,这意味着2 ^ 16 - 1倍48位地址空间),用于虚拟映射,其中没有RAM.而且因为有很多东西可以绕过,每个PCI卡都有自己的地址空间,它的行为有点像CPU的CPU(请记住我之前提到过的那些PAE,好吧,好旧的32位时间就像这样必须要完成与扩展卡交谈).

现在来了OpenGL驱动程序.它只是提供了一个新的地址映射处理程序,它通常只构建在PCI地址空间处理程序之上,它将映射进程的一部分虚拟地址空间.并且该地址空间中发生的任何事情都将被该映射处理器反射到最终由GPU访问的缓冲区中.但是GPU本身可能直接访问CPU内存.AMD计划的是,GPU和CPU将存在于相同的Die上并访问相同的内存,因此不再存在物理上的区别.