我正在 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。真的很奇怪。
我最终用
buffer.position(0)
而不是buffer.flip()
解决了这个问题。
根据文档,
buffer.flip()
应该可以正确工作,因为它也将位置设置为0。唯一的区别是flip()
还将limit
设置为最后一个位置(有关更多信息,请参阅文档 )。
所以限制可能会导致奇怪的行为。
尝试 allocateDirect,而不是 allocate。
allocate 比 allocateDirect 花费更多时间,因为它在 JVM 中分配内存。