这个问题类似于How to get around the performance issues with Buffer.put() and Android OpenGL但我问它是因为:
- 略有不同 - 我的问题是纹理,而不是顶点缓冲区
- 虽然问题很清楚,但似乎大多数答案都没有抓住重点
- 这个问题已经 3 岁了,也许有一些新的东西可以解决我的问题
- 这是一个问题真的让我感到惊讶......我觉得我一定是误解了一些东西。
无论如何,我在 Android 上使用 OpenGL ES 2.0。我有一个大纹理(比如 1024x1024),必须随每一帧更新。没有办法绕过这个 AFAIK - 纹理的内容本质上是一个视频。
问题是 OpenGL 的 Android Java 接口使用 java.nio.Buffer 对象,而不是数组。特别是最后一个参数
public static void GLES20.glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, Buffer pixels)
是一个缓冲区,而不是一个byte[]
或int[]
。
glTexImage2D
因此,我必须将内容生成到 int[] 中,然后为整个巨大的数组调用 IntBuffer.put() ,而不是将纹理的内容(对于每一帧)直接生成到可以传递给的 int[] 中. Traceview 和调用周围的 System.nanoTime() 表明这是一个占用大量 CPU,不足为奇。
如何解决这个问题?我尝试使用 IntBuffer.array() 将内容作为数组获取,但是
- 对于
array()
分配的缓冲区,调用不成功IntBuffer.allocateDirect()
- 该
glTexImage2D()
调用不适用于分配的缓冲区IntBuffer.allocate()
其他我能想到的:
- 从本机代码调用
glTexImage2D
,我认为这不是 Android GL 本机代码接口的问题 - 在另一个线程上完成工作。但我不知道这是否会导致产生纹理内容的线程和调用 glTexImage2D 的 GL 线程之间出现争用问题。无论如何,当逻辑上没有必要时,复制内存仍然需要额外的 CPU 周期。
如果只有一个 GLES20.glTexImage2D 版本采用 int[] 或其他数组类型而不是缓冲区,我似乎不会成为问题。