Android 5.1 crash - glDrawArrays GL_POINTS - Fatal 7 (SIGBUS) code 2
A few months ago, after I updated my Nexus 4 to Android 5.1 (now 5.1.1 is a factory image wallpaper from Google), one of my games started crashing when drawing particles with glDrawArrays with GL_POINTS. I simplified, redefined Java code and replicated the failure.
The crash is always fatal 7 (SIGBUS), code 2 in what appears to be OpenGL code.
In this test for me, with 118 calls to drawPoint () in the for loop, everything seems to work fine, but it fails (next frame) if I try 119 calls to drawPoint (). Any number of calls to drawPoint () greater than 119 also falls.
This Java code works fine on the Nexus 4 virtual device. The C source code works on PC, iOS, and other Android devices without issue.
It looks like it might be a problem with the Nexus 4 driver. Any ideas?
Logcat:
--------- beginning of crash
A/libc﹕ Fatal signal 7 (SIGBUS), code 2, fault addr 0xa2876000 in tid 17998 (GLThread 14477)
I/DEBUG﹕ *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG﹕ Build fingerprint: 'google/occam/mako:5.1.1/LMY47V/1836172:user/release-keys'
I/DEBUG﹕ Revision: '11'
I/DEBUG﹕ ABI: 'arm'
I/DEBUG﹕ pid: 17822, tid: 17998, name: GLThread 14477 >>> com.joeco.pointsprites <<<
I/DEBUG﹕ signal 7 (SIGBUS), code 2 (BUS_ADRERR), fault addr 0xa2876000
I/DEBUG﹕ r0 c0004600 r1 a2876000 r2 04000000 r3 a2876000
I/DEBUG﹕ r4 b7755818 r5 00000000 r6 b776d550 r7 00000018
I/DEBUG﹕ r8 b776d550 r9 04000000 sl 00008000 fp 00000000
I/DEBUG﹕ ip fc000000 sp a4601850 lr abad3c91 pc abac38e6 cpsr 60030030
I/DEBUG﹕ backtrace:
I/DEBUG﹕ #00 pc 000ab8e6 /system/vendor/lib/egl/libGLESv2_adreno.so (oxili_write_event_write+41)
I/DEBUG﹕ #01 pc 000bbc8d /system/vendor/lib/egl/libGLESv2_adreno.so (oxili_wa_predraw+234)
I/DEBUG﹕ #02 pc 000bbef1 /system/vendor/lib/egl/libGLESv2_adreno.so (oxili_wa_point_sprite_dummy_draw+204)
I/DEBUG﹕ #03 pc 000ba47b /system/vendor/lib/egl/libGLESv2_adreno.so (oxili_primitive_drawarrays+318)
I/DEBUG﹕ #04 pc 000825cf /system/vendor/lib/egl/libGLESv2_adreno.so (rb_primitive_drawarrays+298)
I/DEBUG﹕ #05 pc 0005a4f7 /system/vendor/lib/egl/libGLESv2_adreno.so (core_glDrawArraysInstancedXXX+294)
I/DEBUG﹕ #06 pc 0005a877 /system/vendor/lib/egl/libGLESv2_adreno.so (core_glDrawArrays+6)
I/DEBUG﹕ #07 pc 00049acb /system/vendor/lib/egl/libGLESv2_adreno.so (glDrawArrays+24)
I/DEBUG﹕ #08 pc 00a5befb /data/dalvik-cache/arm/system@framework@boot.oat
Code for MainActivity.java:
// MainActivity.java -- pointsprite crash -- Joe Linhoff 6/15/2015
package com.joeco.pointsprites;
import android.app.Activity;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Bundle;
import android.os.SystemClock;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;
import javax.microedition.khronos.opengles.GL10;
// starting point: http://developer.android.com/training/graphics/opengl/index.html
public class MainActivity extends Activity {
public GLSurfaceView mGLView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new MyGLSurfaceView(this);
setContentView(mGLView);
} // onCreate()
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context) {
super(context);
setEGLContextClientVersion(2); // create OpenGL ES 2.0 context
mRenderer = new MyGLRenderer();
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
} // MyGLSurfaceView()
} // class MyGLSurvaceView
public class PointGeo {
FloatBuffer vertexBuffer;
static final int floatsPerVertex = 3;
float pointCoords[] = { 0.1f, 0.0f, 0.0f }; // xyz
final int vertexCount = pointCoords.length / floatsPerVertex;
final int vertexStride = floatsPerVertex * 4; // 4 bytes per float
public PointGeo() {
ByteBuffer bb = ByteBuffer.allocateDirect(pointCoords.length * 4); // each is 4 bytes
bb.order(ByteOrder.nativeOrder()); // device native byte order
vertexBuffer = bb.asFloatBuffer(); // create floating point buffer
vertexBuffer.put(pointCoords); // copy coordinates into buffer
vertexBuffer.position(0); // set to first item
} // PointGeo()
} // class PointGeo
public class MyGLRenderer implements GLSurfaceView.Renderer {
private boolean mSetup = false;
private PointGeo mPoint;
private int mTriangleShaderProgram;
private int mTriangleShaderLoc_uMVPMat;
private int mTriangleShaderLoc_vPos;
private float[] mViewMat = new float[16];
private float[] mModelMat = new float[16];
private float[] mProjMat = new float[16];
private float[] mMVPMat = new float[16];
public void onDrawFrame(GL10 unused) {
if(!mSetup)
lazySetup();
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// build model matrix -- rotate
int time = (int)SystemClock.uptimeMillis() & 8191;
float angleInDegrees = (360.0f / 8191.0f) * time;
Matrix.setIdentityM(mModelMat, 0);
Matrix.rotateM(mModelMat, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
// draw -- 118:ok 119:crash on next frame
for(int i=0;i<119;i++)
drawPoint();
} // onDrawFrame()
void drawPoint()
{
// setup
GLES20.glUseProgram(mTriangleShaderProgram);
GLES20.glEnableVertexAttribArray(mTriangleShaderLoc_vPos);
GLES20.glVertexAttribPointer(mTriangleShaderLoc_vPos, mPoint.floatsPerVertex,
GLES20.GL_FLOAT, false, mPoint.vertexStride, mPoint.vertexBuffer);
// build mvp matrix
Matrix.multiplyMM(mMVPMat,0,mViewMat,0,mModelMat,0);
Matrix.multiplyMM(mMVPMat, 0, mProjMat, 0, mMVPMat, 0);
GLES20.glUniformMatrix4fv(mTriangleShaderLoc_uMVPMat, 1, false, mMVPMat, 0);
// draw
GLES20.glDrawArrays(GLES20.GL_POINTS, 0, mPoint.vertexCount);
// finish
GLES20.glDisableVertexAttribArray(mTriangleShaderLoc_vPos);
GLES20.glUseProgram(0);
} // drawPoint()
@Override
public void onSurfaceCreated(GL10 gl10, javax.microedition.khronos.egl.EGLConfig eglConfig) {
} // onSurfaceCreated()
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
// create projection matrix
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjMat, 0, left, right, bottom, top, near, far);
} // onSurfaceChanged()
public int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type); // create shader
GLES20.glShaderSource(shader, shaderCode); // add source
GLES20.glCompileShader(shader); // compile
return shader;
} // loadShader()
private final String vertexShaderCode =
"attribute vec4 vPos;" +
"uniform mat4 uMVPMat;" +
"void main() {" +
" gl_Position = vPos*uMVPMat;" +
" gl_PointSize = 40.0f; " +
"}";
private final String fragmentShaderCode =
"void main() {" +
" gl_FragColor = vec4(0.5f,0.7f,0.5f,1.f);" +
"}";
void lazySetup()
{
mSetup=true;
mPoint = new PointGeo();
int vshader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fshader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mTriangleShaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mTriangleShaderProgram, vshader);
GLES20.glAttachShader(mTriangleShaderProgram, fshader);
GLES20.glLinkProgram(mTriangleShaderProgram);
int err = GLES20.glGetError();
mTriangleShaderLoc_uMVPMat = GLES20.glGetUniformLocation(mTriangleShaderProgram, "uMVPMat");
mTriangleShaderLoc_vPos = GLES20.glGetAttribLocation(mTriangleShaderProgram, "vPos");
setViewMat();
Matrix.setIdentityM(mModelMat,0);
} // lazySetup()
void setViewMat()
{
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 5.0f;
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -1.0f;
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
Matrix.setLookAtM(mViewMat, 0, eyeX, eyeY, eyeZ,
lookX, lookY, lookZ, upX, upY, upZ);
} // setViewMat()
} // class MyGLRenderer
} // class MainActivity
source to share