4

通读 OpenGL 编程指南,第 8 版。

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

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

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

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

4

3 回答 3

7

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

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

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

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

因此,对于每个进程,操作系统管理一个表,其中进程虚拟地址空间的哪一部分映射到哪个页面处理程序。如果您正在运行 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(最大),但进程可以传播。

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

无论如何:在现代 64 位系统上,指针大小为 64 位,而当前硬件有 48 位物理 RAM 地址线。这为周围没有 RAM 的虚拟映射留下了足够的空间,即 16 × 48 位(EDIT表示 2^16 - 48 位地址空间的 1 倍)。而且因为有很多事情要做,每张 PCI 卡都有自己的地址空间,它的行为有点像 CPU 的 RAM(记住我之前提到的那些 PAE,好吧,在旧的 32 位时代类似的东西必须已经与扩展卡通话)。

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

于 2013-07-23T08:51:41.403 回答
2

glMapBuffers()在应用程序的虚拟内存空间中返回一个指针,这就是为什么指针可以指向 64 位系统上超过 4GB 的东西。

您使用映射指针操作的内存可能是分配在 gpu 上的纹理(或缓冲区)的 cpu 副本(阴影),也可能是移动到系统内存的实际纹理。通常由操作系统决定纹理是驻留在系统内存还是 gpu 内存上。操作系统可以将纹理从一个位置移动到另一个位置,并可以对其进行复制(阴影)

于 2013-07-23T01:39:42.283 回答
2

计算机具有多层内存映射。首先,所有可物理寻址的组件(包括 RAM、PCI 内存窗口、其他设备寄存器等)都被分配了一个物理地址。该地址的大小各不相同。即使在 32 位 Intel 设备上,物理空间也可能是 36 位地址(对于 CPU),而它在 PCI 内存空间中是 64 位地址。

在该映射之上是一个虚拟映射。有许多不同的虚拟映射,包括每个进程一个。在那个空间(在 64 位系统上和你说的一样大)内,可以映射物理空间的任何组合(包括重复!),只要它适合。在 64 位系统上,可用的虚拟空间非常大,以至于每个可能的物理设备都可以轻松映射。

于 2013-07-23T01:41:10.847 回答