Android GLES20 - 无法创建 VBO - JNI 错误

问题描述 投票:0回答:2

我正在 Android 中使用 GLES20 创建 VBO,目前遇到 JNI 错误。我仔细检查了容量和价值计数。我还检查了缓冲区(我的代码中的 STANDARD_QUAD)是否获取了 ID。 我真的不知道如何继续。我在 2 个不同的物理设备和一个模拟器上进行了测试,因此故障肯定出在代码中的某处。

代码:

    ByteBuffer buffer = ByteBuffer.allocate(30 * 4);
    buffer.order(ByteOrder.nativeOrder());
    buffer.asFloatBuffer().put(new float[]{
            0, 0, 0,    0,0,
            0,  1, 0,   0,1,
             1, 0, 0,   1,0,
             1,  1, 0,  1,1,
            1, 0, 0,    1,0,
             0, 1, 0,   0,1
    });
    buffer.flip();

    int[] vboids = new int[1];
    GLES20.glGenBuffers(1, vboids, 0);
    STANDARD_QUAD = vboids[0];
    System.out.println("init vbo (std quad): " + STANDARD_QUAD + ", buffer.capacity: " + buffer.capacity());
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, STANDARD_QUAD);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity(), buffer, GLES20.GL_STATIC_DRAW);

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

输出:

init vbo (std quad): 1, buffer.capacity: 120
JNI DETECTED ERROR IN APPLICATION: thread Thread[13,tid=19730,Runnable,Thread*=0xb4e08800,peer=0x12c07060,"GLThread 13050"] called too many critical releases
     in call to ReleasePrimitiveArrayCritical
     from void android.opengl.GLES20.glBufferData(int, int, java.nio.Buffer, int)
 "GLThread 13050" prio=5 tid=13 Runnable
   | group="main" sCount=0 dsCount=0 obj=0x12c07060 self=0xb4e08800
   | sysTid=19730 nice=-11 cgrp=apps sched=0/0 handle=0xaf854300
   | state=R schedstat=( 73594541 5530250 17 ) utm=6 stm=1 core=5 HZ=100
   | stack=0xa10fe000-0xa1100000 stackSize=1036KB
   | held mutexes= "mutator lock"(shared held)
   native: #00 pc 00004c58  /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23)
   native: #01 pc 000034c1  /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8)
   native: #02 pc 0025c5ad  /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+84)
   native: #03 pc 0023f8cb  /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+162)
   native: #04 pc 000b313d  /system/lib/libart.so (art::JniAbort(char const*, char const*)+620)
   native: #05 pc 000b386d  /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+68)
   native: #06 pc 000b6b65  /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1436)
   native: #07 pc 000c1de7  /system/lib/libart.so (art::CheckJNI::ReleasePrimitiveArrayCritical(_JNIEnv*, _jarray*, void*, int)+42)
   native: #08 pc 000684d1  /system/lib/libandroid_runtime.so (???)
   native: #09 pc 000736e3  /system/lib/libandroid_runtime.so (???)
   native: #10 pc 01574071  /system/framework/arm/boot.oat (Java_android_opengl_GLES20_glBufferData__IILjava_nio_Buffer_2I+128)
   at android.opengl.GLES20.glBufferData(Native method)
   at my.package.glsl.GuiProgram.initQuad(GuiProgram.java:66)
   at my.package.glsl.GuiProgram.onCreated(GuiProgram.java:111)
   at my.package.glsl.Program.create(Program.java:67)
   at my.package.glsl.Shaders.initialize(Shaders.java:26)
   at my.package.myapplication.FullscreenActivity.renderGL(FullscreenActivity.java:66)
   at my.package.myapplication.FullscreenActivity.access$000(FullscreenActivity.java:22)
   at my.package.myapplication.FullscreenActivity$1.render(FullscreenActivity.java:42)
   at my.package.opengl.OpenglRenderer.onDrawFrame(OpenglRenderer.java:38)
   at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1561)
   at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1278)

编辑:

将代码更改为以下,错误发生变化。

    FloatBuffer buffer = ByteBuffer.allocate(30 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
    buffer.put(new float[]{
            //...
    });
    buffer.flip();
    //...
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * 4, buffer, GLES20.GL_STATIC_DRAW);

错误更改为

JNI DETECTED ERROR IN APPLICATION: jarray was null
。但肯定是 buffer != null。真的很奇怪。

android opengl-es-2.0 vbo
2个回答
1
投票

我最终用

buffer.position(0)
而不是
buffer.flip()
解决了这个问题。

根据文档,

buffer.flip()
应该可以正确工作,因为它也将位置设置为0。唯一的区别是
flip()
还将
limit
设置为最后一个位置(有关更多信息,请参阅文档 )。 所以限制可能会导致奇怪的行为。


0
投票

尝试 allocateDirect,而不是 allocate。

allocate 比 allocateDirect 花费更多时间,因为它在 JVM 中分配内存。

© www.soinside.com 2019 - 2024. All rights reserved.