映射GPU内存时应该使用volatile吗?

OpenGL 和 Vulkan 都允许分别使用glMapBuffer和获取指向部分 GPU 内存的指针vkMapMemory。他们都给void*映射的内存一个。要将其内容解释为某些数据,必须将其强制转换为适当的类型。最简单的示例可能是转换为 afloat*以将内存解释为浮点数或向量或类似数组。

似乎任何类型的内存映射在 C++ 中都是未定义的行为,因为它没有内存映射的概念。但是,这并不是真正的问题,因为该主题超出了 C++ 标准的范围。但是,仍然存在一个问题volatile

在链接的问题中,指针被额外标记为volatile因为它指向的内存内容可以以编译器在编译期间无法预料的方式进行修改。这似乎是合理的,尽管我很少看到人们volatile在这种情况下使用(更广泛地说,这个关键字现在似乎很少使用)。

同时在这个问题中,答案似乎是使用volatile是不必要的。这是因为他们所说的内存是映射使用的mmap,然后msync可以被视为修改内存,这类似于在 Vulkan 或 OpenGL 中显式刷新它。恐怕这不适用于 OpenGL 和 Vulkan。

如果内存被映射为未映射GL_MAP_FLUSH_EXPLICIT_BIT或根本VK_MEMORY_PROPERTY_HOST_COHERENT_BIT不需要刷新,则内存内容会自动更新。即使通过使用手动刷新内存,vkFlushMappedMemoryRanges或者glFlushMappedBufferRange这些函数实际上都没有将映射指针作为参数,因此编译器也不可能知道它们修改了映射内存的内容。

因此,是否有必要将指向映射 GPU 内存的指针标记为volatile?我知道从技术上讲这都是未定义的行为,但我问的是在实际硬件中实际需要什么。

顺便说一下,无论是Vulkan 规范还是OpenGL 规范都没有提到volatile限定符。

编辑:将内存标记为volatile会导致性能开销吗?

回答

好吧,假设我们有一个编译器,它对代码中发生的所有事情都无所不知。这意味着编译器可以跟踪任何指针,即使每次都完美正确地执行代码,无论您如何尝试隐藏它。因此,即使您在程序的一端读取了一个字节,编译器也会以某种方式记住您读取的确切字节,并且无论何时您再次尝试读取它们,它都可以选择不执行该读取而只为您提供先前的值, 除非编译器知道可以改变它的东西。

但我们也可以说,我们无所不知的编译器完全无视 OpenGL/Vulkan 中发生的一切。对于这个编译器,图形 API 是一个黑匣子。在这里,有龙。

所以你从 API 获得一个指针,从中读取,GPU 写入它,然后你想要读取 GPU 刚刚写入的新数据。为什么编译器会认为该指针后面的数据已被更改?毕竟,更改来自系统外部,来自 C++ 标准无法识别的来源。

volatile是为了什么,对吧?

嗯,事情是这样的。在 OpenGL 和 Vulkan 中,为了确保您可以真正读取该数据,您需要做一些事情。即使你连贯地映射内存,你也必须进行 API 调用,以确保写入内存的 GPU 进程已经实际执行。对于 Vulkan,您正在等待围栏或事件。对于 OpenGL,您正在等待围栏或执行完整的完成。

无论哪种方式,在执行从内存中读取之前,无所不知的编译器都会遇到一个函数调用进入一个黑匣子,正如早先建立的那样,编译器对此一无所知。由于映射指针本身来自同一个黑匣子,编译器不能假设黑匣子没有指向该内存的指针。因此,就编译器而言,调用这些函数可能会将数据写入该内存。

因此,我们无所不知但无所不知的编译器无法优化掉此类内存访问。一旦我们从这些函数中获得控制权,编译器就必须假设通过该地址可到达的任何指针的任何内存都可能已被更改。

如果编译器能够查看图形 API 本身,以阅读和理解这些函数在做什么,那么它肯定会看到一些东西会告诉它,“哦,我不应该对通过这些指针。”

这就是为什么你不需要volatile.

另外,请注意这同样适用于写入数据。如果您写入持久的、一致的映射内存,您仍然需要使用图形 API 执行一些同步操作,以便您的 CPU 写入以便 GPU 不会读取它。这就是编译器知道它不能再依赖于先前写入数据的知识的地方。

  • @enthusiastic_3d_graphics_pr...: It would be needed by direct hardware management, where an address of memory is directly shared with some external device *without* any CPU intervention. Vulkan and OpenGL require some form of CPU intervention to make sure that the data exists.

以上是映射GPU内存时应该使用volatile吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>