Imagination PowerVR SDK Blog

compile error

pvrtrace

#1

Hello.


I got a compile error on Galaxy S.


This shader works fine on Tegra2, Adreno200,205,220,Mali-400M.


Why doesn’t it work on PowerVR SGX540?





However, I removed this line:


       #define USE_HWSKINNING 1


It works fine on Galaxy S.





Sample APK(This apk doesn’t work on Galaxy S)


http://chototsumoushinp.dip.jp/miku/download/AndroidSample_tinyar-112beta1.apk





Release version(This apk works on Galaxy S, but it’s slow because GLSL skinning is disabled).


https://market.android.com/details?id=jp.co.pscnet.mms.tinyar





Thanks.







#define COLORRAMP 1

#define DIFFUSEMAP 1

#define MATERIAL_COLORS 1

#define NUM_BONES 20

#define USE_HWSKINNING 1

#define VERTEX_LIGHTING 1

// #import "MatDefs/pmd/Skinning.glsllib"

#ifdef USE_HWSKINNING

uniform mat4 m_BoneMatrices[NUM_BONES];

#endif

#define ATTENUATION

// #define HQ_ATTENUATION



uniform mat4 g_WorldViewProjectionMatrix;

uniform mat4 g_WorldViewMatrix;

uniform mat3 g_NormalMatrix;

uniform mat4 g_ViewMatrix;



uniform vec4 m_Ambient;

uniform vec4 m_Diffuse;

uniform vec4 m_Specular;

uniform float m_Shininess;



uniform vec4 g_LightColor;

uniform vec4 g_LightPosition;

uniform vec4 g_AmbientLightColor;



varying vec2 texCoord;



varying vec4 AmbientSum;

varying vec4 DiffuseSum;

varying vec4 SpecularSum;



attribute vec3 inPosition;

attribute vec2 inTexCoord;

attribute vec3 inNormal;



// uniform Sampler2D m_BoneParameter;

// uniform sampler2D m_BoneParameter;



#ifdef HQ_ATTENUATION

varying vec3 lightVec;

#endif



#ifdef VERTEX_COLOR

attribute vec4 inColor;

#endif



#ifndef VERTEX_LIGHTING

attribute vec4 inTangent;



#ifndef NORMALMAP

    varying vec3 vNormal;

#endif

varying vec3 vPosition;

varying vec3 vViewDir;

varying vec4 vLightDir;

#endif



// #ifdef USE_REFLECTION

    uniform vec3 g_CameraPosition;

    uniform mat4 g_WorldMatrix;



    uniform vec3 m_FresnelParams;

    varying vec4 refVec;





    /**

     * Input:

     * attribute inPosition

     * attribute inNormal

     * uniform g_WorldMatrix

     * uniform g_CameraPosition

     *

     * Output:

     * varying refVec

     */

    void computeRef(in vec4 position, in vec4 normal){

        vec3 worldPos = (g_WorldMatrix * vec4(normalize(position.xyz),1.0)).xyz;



        vec3 I = normalize( g_CameraPosition - worldPos ).xyz;

        vec3 N = normalize( (g_WorldMatrix * vec4(normalize(normal.xyz), 0.0)).xyz );



        refVec.xyz = reflect(I, N);

        refVec.w   = 1.0;//m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);

    }

// #endif



// JME3 lights in world space

void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){

    float posLight = step(0.5, color.w);

    vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);

    #ifdef ATTENUATION

     float dist = length(tempVec);

     lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);

     lightDir.xyz = tempVec / vec3(dist);

     #ifdef HQ_ATTENUATION

       lightVec = tempVec;

     #endif

    #else

     lightDir = vec4(normalize(tempVec), 1.0);

    #endif

}



#ifdef VERTEX_LIGHTING

float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){

      return max(0.0, dot(norm, lightdir));

}



float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){

      #ifndef LOW_QUALITY

        vec3 H = (viewdir + lightdir) * vec3(0.5);

        return pow(max(dot(H, norm), 0.0), shiny);

      #else

        return 0.0;

      #endif

}



vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){

     vec4 lightDir;

     lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);



     float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);

     float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);

     //specularFactor *= step(0.01, diffuseFactor);

     return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w);

}

#endif

attribute vec4 inBoneWeight;

attribute vec4 inBoneIndices;

attribute vec4 inBoneIndex;

#ifdef USE_HWSKINNING

void Skinning_Compute(inout vec4 position, inout vec4 normal){

//    vec4 index = inBoneIndices;

    vec4 index = inBoneIndex;

    vec4 weight = inBoneWeight;



    vec4 newPos    = vec4(0.0,0.0,0.0,0.0);

    vec4 newNormal = vec4(0.0,0.0,0.0,0.0);



    //for (float i = 1.0; i < 2.0; i += 1.0){

        mat4 skinMat = m_BoneMatrices[int(index.x)];

        newPos    = weight.x * (skinMat * position);

        newNormal = weight.x * (skinMat * normal);

        //index = index.yzwx;

        //weight = weight.yzwx;

        skinMat = m_BoneMatrices[int(index.y)];

        newPos    = newPos + weight.y * (skinMat * position);

        newNormal = newNormal + weight.y * (skinMat * normal);

    //}



    position = newPos;

    normal = newNormal;

}

#endif

void main(){

   vec4 pos = vec4(inPosition, 1.0);

   vec4 normal = vec4(inNormal,0.0);

#ifdef USE_HWSKINNING

   Skinning_Compute(pos, normal);

#endif

//    pos = m_BoneMatrices[0] * pos;

   gl_Position = g_WorldViewProjectionMatrix * pos;

   texCoord = inTexCoord;



   vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;

   vec3 wvNormal = normalize(g_NormalMatrix * normal.xyz);



//   vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;

//   vec3 wvNormal = normalize(g_NormalMatrix * inNormal);



   vec3 viewDir = normalize(-wvPosition);



       //vec4 lightColor = g_LightColor[gl_InstanceID];

       //vec4 lightPos   = g_LightPosition[gl_InstanceID];

       //vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));

       //wvLightPos.w = lightPos.w;



   vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));

   wvLightPos.w = g_LightPosition.w;

   vec4 lightColor = g_LightColor;



   #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)

     vec3 wvTangent = normalize(g_NormalMatrix * inTangent.xyz);

     vec3 wvBinormal = cross(wvNormal, wvTangent);



     mat3 tbnMat = mat3(wvTangent, wvBinormal * -inTangent.w,wvNormal);

     

     vPosition = wvPosition * tbnMat;

     vViewDir = viewDir * tbnMat;

     lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);

     vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;

   #elif !defined(VERTEX_LIGHTING)

     vNormal = wvNormal;



     vPosition = wvPosition;

     vViewDir = viewDir;



     lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);



     #ifdef V_TANGENT

        vNormal = normalize(g_NormalMatrix * inTangent.xyz);

        vNormal = -cross(cross(vLightDir.xyz, vNormal), vNormal);

     #endif

   #endif



   lightColor.w = 1.0;

   #ifdef MATERIAL_COLORS

      AmbientSum = m_Ambient * g_AmbientLightColor;

      DiffuseSum = m_Diffuse * lightColor;

      SpecularSum = m_Specular * lightColor;

    #else

      AmbientSum = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray

      DiffuseSum = lightColor;

      SpecularSum = lightColor;

    #endif



    #ifdef VERTEX_COLOR

      AmbientSum *= inColor;

      DiffuseSum *= inColor;

    #endif



    #ifdef VERTEX_LIGHTING

       vec2 light = computeLighting(wvPosition, wvNormal, viewDir, wvLightPos);



       AmbientSum.a = light.x;

       SpecularSum.a = light.y * 0.3;

    #endif



    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_H)

        computeRef(pos,normal);

    #endif

}



                  

#2

This shader works on Galaxy NEXUS.


However it doesn’t work on Galaxy S, EPSON MOVERIO, FUJITSU ARROWS X.


Why does the compile error happen?


How should I fix it?





Thanks.



#3

Hi,


Just to let you know that we are currently investigating this issue and we’ll keep you updated if we find anything out.



#4

Hi, Arron.


Thank you for your quick reply.


I send all source code to you if you need.


This is an open source product.





Thanks.



#5

Hi chototsu.


If you could send the source that would be great. Please send a zipped package to devtech@imgtec.com.


#6

Hi chototsu.





We may have found the problem. It seems that the statement “precision mediump float;” is being prepended to your vertex shader. This seems to have some issues on the Galaxy S & Nexus S.





Although your vertex shader doesn’t actually contain this declaration, it seems as though your shader loading code is adding the line and causing the issue.





If you can track this down and perhaps retest the application with this line removed it may work.





Regards.


#7

Hi, Arron.


> your shader loading code is adding the line


Sorry, I forgot it.


I changed my renderer code and build my app.


http://chototsumoushinp.dip.jp/miku/download/AndroidSample_tinyar-112beta3.apk


(However, I don’t yet test it because I don’t have Galaxy S.)





Thank you very much.





OGLESShaderRenderer.java:





        if (source.getType().equals(ShaderType.Vertex)


               && GLES20.glGetString(GLES20.GL_RENDERER).indexOf(“PowerVR”)>=0) {


            GLES20.glShaderSource(


                    id,


                     source.getDefines()


                    + source.getSource());


        } else {


            GLES20.glShaderSource(


                    id,


                    “precision mediump float;n”


                    + source.getDefines()


                    + source.getSource());


        }



#8

Hi chototsu,


This no longer fails to compile so that problem is solved :).





However, on our Galaxy S the application runs very, very slow - around 4-5fps. This appears to be due to very high CPU load.Arron2012-02-03 16:26:15


#9

Thank you for test my app.


> However, on our Galaxy S the application runs very, very slow


Which of release version or 112beta3 is faster?





On my test machine(ASUS TF101 Tegra2), it’s same frame rate as release version.





(Don’t select Megurine Luka models because it’s too heavy for Galaxy S.


Please select Miku model.)





Thanks.


#10

Old version of my app runs around 25fps on Galaxy S.


It uses GLSL skinning.


It works fine.


However, I updated to new version, it didn’t work on Galaxy S.


I didn’t change my shader.


I am confused very much.


It runs around 25fps on Galaxy S if GLSL skinning works.





Thanks.


#11

Hi chototsu,





I have downloaded your release app and can confirm that 112beta3 runs faster than the released version. I assume this is because you have now enabled HW skinning?





I believe I was using the Miku model, but I cannot find a way to switch models.





Regards.Arron2012-02-03 17:07:47


#12

Thank you for test.


> I assume this is because you have now enabled HW skinning?


Yes, 112beta3 uses GLSL skinning.


However, I head that old version(uses GLSL skinning) runs around 25 fps on Galaxy S from users.


My app runs around 40fps on TF101(Tegra2).


4-5fps is too slow…


I don’t understand the cause.





> I believe I was using the Miku model, but I cannot find a way to switch models.


Please push menu button.


(Default model is Miku, you don’t need to change model.)





Thanks.



#13

Hi chototsu.


I’m not really sure. I’ve profiled your app with our internal tools and can see that the GPU does very little work, while the CPU is fully loaded. There’s approximately a 200ms gap between a GPU calls.





The app runs well (40-50fps+) on a Galaxy Nexus which is also an SGX540 although clocked higher, so I do not think that the issue is with the graphics hardware.





Your other models vary with speed - some run around 17-20fps while as you say Megurine Luka runs very very slow.





I’ll continue profiling your application next week and I’ll update this post if I find any more information which may be of use.





Best regards.Arron2012-02-03 18:00:56


#14

> I do not think that the issue is with the graphics hardware.


OK.


I investigate My app code.





Thank you for your kindness.



#15

You’re welcome.





One thing I have noticed is that you seem to call glGetError a lot (317 times per frame). This should be disabled in release code as that number of calls may affect performance.


#16

I try it.


Thanks.


#17

Hi again chototsu,


I’ve been looking at your application again and have a few recommendations which may improve performance:





* Your shaders use default high precision for every floating point type. This is not optimal and variables such as colour types could be stored as low precision instead. This should improve performance for vertex-heavy processing such as your application.





* You have lots of redundant GL calls to functions glTexParameteri and glVertexAttribPointer. glTexParameteri only needs to be called when a texture is first loaded and bound if it does not need to change parameters again in future frames which I believe yours don’t. Your calls to glVertexAttribPointer always seem to contain the same parameters so this could be set at the beginning of the first frame and used for each mesh sub-component.





* Your mesh data is not interleaved. Interleaving mesh data will reduce the number of required vertex buffer objects and allow the graphics hardware to read the data more efficiently.





* You have a large number of vertex buffer objects. If you could possibly reduce this amount by combining the mesh sub objects in to fewer, larger arrays and instead use offsets in to the buffers when you wish to draw individual components.





* You seem to pass a lot of redundant bone transformation data to the vertex shader. It looks like you pass 20 4x4 matrices for each mesh sub-component even if all the matrices are identical. It would be more optimal to control the amount of matrices that you pass using the count parameter of glUniformMatrix4f such that you only pass the exact number of required matrices.





By the way, have you tried your application with the glGetError’s removed? This should also provide a performance gain.


I also recommend taking a look at our performance recommendation guidelines.





Best regards.


Arron2012-02-06 11:03:59


#18

Hi, sorry for my late answer.


I will try your advice this weekend.


Thank you very much.



#19

Hi,


I tried your advice.


> colour types could be stored as low precision instead.


I changed color types into lowp.





> You have lots of redundant GL calls to functions glTexParameteri and glVertexAttribPointer.


I removed glTexParameteri which was unnecessary.


However glVertexAttribPointer are not same(offset, stride), I can’t remove them.





> Your mesh data is not interleaved.


> You have a large number of vertex buffer objects.


I combined meshes and I changed them into interleaved.





> You seem to pass a lot of redundant bone transformation data to the vertex shader.


I reduced matrix4 arrays.





> By the way, have you tried your application with the glGetError’s removed?


Yes, I do.





By these improvement, performance improved approximately 10%.





http://chototsumoushinp.dip.jp/miku/download/AndroidSample_tinyar-114beta2.apk





Many thanks.



#20

I tested version 1.14 on Galaxy NEXUS, MOVERIO, Transformer TF101.


It works, but it doesn’t work on GALAXY SII.


I removed this version.