【问题标题】:Using glMapBufferRange to read data to a buffer使用 glMapBufferRange 将数据读取到缓冲区
【发布时间】:2019-10-10 08:04:05
【问题描述】:

我有一个问题,我想使用 glMapBufferRange 来读取数据。我的使用方式如下:

 bindBuffer(vboIdx);
 void *ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT);
 int err = glGetError();
 assert(ptr);
 memcpy(dst, ptr, size);
 glUnmapBuffer(GL_ARRAY_BUFFER);
 unbindBuffer();

但是,ptr 似乎为 NULL。如此处文档所述:https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glMapBufferRange.xhtml 如果发生错误,该函数将返回 NULL。因此,我使用 glGetError() 检查了错误。但是我得到的错误是0,和GL_NO_ERROR一样。那么我错过了什么,我做错了什么?

提前致谢!

【问题讨论】:

  • 但是你在那个缓冲区有可访问的数据吗?你的bindBuffer 是做什么的?请注意,“如果发生错误,函数返回 NULL”并不意味着“当函数返回 NULL 时发生错误”。即使没有报错,NULL 可能仍然有效。
  • " 请注意,“如果发生错误,函数返回 NULL”并不意味着“函数返回 NULL 时发生错误”。”我也想过,但最后 ptr 应该指向一个我可以从中复制数据的地址,所以 NULL 似乎肯定是错误的。 bindBuffer fct 看起来如下:assert(vboIdx < numVBOs); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbos[vboIdx]);
  • 我知道这可能听起来像是“它是否已接入电力”的问题之一,但是...在您调用它时,您是否设置了有效的 openGL 上下文?删除上下文似乎会产生您描述的问题。请注意,切换到与您绘制的线程不同的线程可能就足够了。上下文应该是每个线程的。你也可以提供一个调用glBufferData的代码吗?
  • 好吧,我会为您提供更详细的信息,但您提供的代码看起来并不完全像通常的 Android openGL API。无论如何,在大多数情况下,您都会有上下文。它可能由一些更高级别的组件(如表面视图)创建。当没有上下文时,您对“gl”函数的每次调用都不会执行任何操作,返回 0,null ... 这也是您的结果。如果上下文在给定线程上设置为当前,则存在上下文。在 Android 上,您应该始终能够通过 EGLContext.eglGetCurrentContext() 获取它。
  • 哦,你说得对,我实际上设置了一个上下文(请参阅下面的更新帖子)

标签: android opengl-es android-ndk


【解决方案1】:

老实说,到目前为止,我还没有听说过 openGL 上下文(只是阅读一下),我开始基于 android 的传感器图形示例项目编写代码:https://github.com/android/ndk-samples/tree/master/sensor-graph。要回答你的问题,到目前为止我还没有遇到问题,我想是的,但我不是 100% 确定。在请求读取数据之前,我将数据写入缓冲区:

   if(dataSize == 0) {
       return;
   }

    bindBuffer(vboIdx);
    if(dataSize > vertexBufSize[vboIdx] - offset) {
        glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STREAM_DRAW);
        vertexBufSize[vboIdx] = dataSize;
    }

    void *ptr = glMapBufferRange(GL_ARRAY_BUFFER, offset, dataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
    int err = glGetError();
    assert(ptr);

    if(data != nullptr) {
        memcpy(ptr, data, dataSize);
    }

    glUnmapBuffer(GL_ARRAY_BUFFER);
        unbindBuffer();

这是我打电话给glBufferData()的地方

更新: Java端:

mView = (GLSurfaceView) frameLayout.findViewById(R.id.plot_view);
mView.setEGLContextClientVersion(3);
mView.setEGLConfigChooser(true);
if(LOG) Log.d(TAG, "onCreateView(): get ID: " + mView.getId());

isStreaming = true;
mView.setRenderer(new GLSurfaceView.Renderer() {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  mLiveViewJNI.surfaceCreated();
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
  mLiveViewJNI.surfaceChanged(width, height);
}

@Override
public void onDrawFrame(GL10 gl) {
  mLiveViewJNI.drawFrame();
}

});      

更新: @Matic Oblak 你是对的,上下文实际上是一个问题。只要我只通过 onSurfaceCreated、onSurfaceChanged 或 onDrawFrame 中的 JNI 触及缓冲区,一切都很好。但是,一旦我尝试通过 mLiveViewJNI.dummyCall 在外部访问它们,我就遇到了这个问题,一切都返回 0 或 NULL。谢谢:)!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多