在 Android/Java 上安全使用 glMapBufferRange()

2022-09-02 22:33:54

我有来自Android上的OpenGL-ES 3.0的工作代码,看起来像这样:glMapBufferRange()

  glBindBuffer(GL_ARRAY_BUFFER, myVertexBufferName);
  glBufferData(GL_ARRAY_BUFFER, myVertexBufferSize, null, GL_STATIC_DRAW);
  ByteBuffer mappedBuffer = (ByteBuffer)glMapBufferRange(
    GL_ARRAY_BUFFER,
    0, myVertexBufferSize,
    GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);

  // [fill buffer...]

  glUnmapBuffer(GL_ARRAY_BUFFER);

我的问题是关于将结果向下投射到第三行。 被声明为返回缓冲区glMapBufferRange()ByteBufferglMapBufferRange()

public static Buffer glMapBufferRange (int target, int offset, int length, int access)

在我的测试平台上,该函数返回一个子类,因此强制转换工作,但是对于支持OpenGL-ES 3 +的所有平台或Android版本进行此假设似乎不是很安全。尽管这看起来很合理,但我还没有找到任何可以保证它的文档,如果它得到保证,似乎应该将该函数声明为返回 。ByteBufferByteBuffer

使用返回者的正确方法(最好有文档支持)是什么?BufferglMapBufferRange()


答案 1

正如您已经发现的那样,缺少文档。但仍有一个相当确凿的参考:OpenGL Java绑定的实现是公共Android源代码的一部分。

如果您查看 文件 glMapBufferRange 中 .cpp 的 JNI 包装器的实现,您可以看到缓冲区是通过调用名为 的函数来分配的。基于此,可以安全地假设缓冲区确实是 .glMapBufferRange()NewDirectByteBuffer()ByteBuffer

虽然供应商可以更改Android代码,但似乎不太可能有人会更改Java绑定的行为(除了修复错误)。如果您担心在以后的Android版本中实现可能会发生变化,您当然可以使用标准的Java类型检查:

Buffer buf = glMapBufferRange(...);
ByteBuffer byteBuf = null;
if (buf instanceof ByteBuffer) {
    byteBuf = (ByteBuffer)buf;
}

或者,您可以使用更详细的反射,从调用返回的缓冲区开始。下一个问题当然是,如果返回的缓冲区不是 .这真的是唯一对我有意义的类型。getClass()ByteBuffer


答案 2

推荐