Mali GPU上的HALF_FLOAT问题

时间:2019-03-10 14:33:19

标签: android opengl-es opengl-es-3.0 mali

我从用户那里收到有关在某些使用Mali GPU(华为荣誉9和三星Galaxy S10 +分别带有Mali G71和G76)的设备上渲染半浮点数据的问题的报告。

这会导致这些设备呈现乱码,而在Adreno和PowerVR GPU上却可以正常工作。

我已经仔细检查过代码,这似乎是正确的:

...
     if (model.hasHalfFloats()) {
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Vertex(), 3, GLES20.GL_FLOAT, false, 18, 0);
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, getGL_HALF_FLOAT(), false, 18, 12);
     } else {
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Vertex(), 3, GLES20.GL_FLOAT, false, 24, 0);
         GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, GLES20.GL_FLOAT, false, 24, 12);
     }
...

/**
 * Returns either OES extension for GL 16-bit floats (if used in ES 2.0) or ES 3.0 constant.
 */
protected int getGL_HALF_FLOAT() {
    if(isES3()) {
        return GLES30.GL_HALF_FLOAT;
    } else {
        return GL_HALF_FLOAT_OES;
    }
}

代码似乎可以正确检测OpenGL ES 3,并在GLES30.GL_HALF_FLOAT中使用getGL_HALF_FLOAT()值。

示例着色器代码:

    vertexShaderCode = "attribute vec4 rm_Vertex;\r\n" + 
            "attribute mediump vec3 rm_Normal;\r\n" +
            "uniform mat4 view_proj_matrix;\r\n" + 
            "uniform float uThickness1;\r\n" + 
            "void main( void )\r\n" + 
            "{\r\n" + 
            "   vec4 pos = vec4(rm_Vertex.xyz, 1.0);\r\n" + 
            "   float dist = (view_proj_matrix * pos).w;\r\n" + 
            "   vec4 normal = vec4(rm_Normal, 0.0);\r\n" + 
            "   pos += normal * uThickness1 * dist;\r\n" + 
            "   gl_Position = view_proj_matrix * pos;\r\n" + 
            "}";

    fragmentShaderCode = "precision mediump float;\r\n" + 
            "uniform vec4 uColor;\r\n" + 
            "void main( void )\r\n" + 
            "{\r\n" + 
            "    gl_FragColor = uColor;\r\n" + 
            "}";

1 个答案:

答案 0 :(得分:1)

我认为您遇到对齐问题。从此代码段(和您的顶点着色器)开始:

tf.io.parse_single_sequence_example()

我可以推断出您正在尝试这样的顶点结构:

GLES20.glVertexAttribPointer(shaderOutline.getRm_Normal(), 3, getGL_HALF_FLOAT(), false, 18, 12);

您得出的顶点跨度为18,大概是通过将元素float fPos[3]; half fNormal[3]; 的各个大小相加得出的。

但是,步幅应为20,因为否则您的顶点将未对齐。 4字节浮点数必须在4字节边界处开始,但事实并非如此。

根据GLES3规范:

  

客户必须使数据元素与客户平台的要求保持一致,并附加基本级别要求,即缓冲区中包含N个基本机器单元的数据的偏移量应为N的倍数。