Vulkan shader problem on Mali Gpu: Accessing array elements inside an Uniform buffer returns all-zero values

One of my game engine demo (Android) app runs well on devices with Adreno and PowerVR Gpus. However, when I test it on devices with Mali Gpus, I can not get any lighting effect on 3D objects, See the attached device screenshot (left) and RenderDoc snapshot (right):


I narrowed down the problem and found that it cause by accessing array elements by an variable index inside an Uniform buffer.

My shading model is a simple Blinn-Phong shading model. All light sources are passed in by a per-scene uniform buffer. There is 1 ambient light and 5 (up to) direction lights defined in this uniform buffer:

struct DirectionalLight
    vec4 color;
    vec3 direction;
    bool isActive;    //Is this light in use?

#define NUM_DIR_LIGHT 5
layout (std140, set = 1, binding = 0) uniform ProjMatrixBuffer
    mat4 projMat;                              // Scene projection matrix

    vec4 ambientColor;                         // Ambient color
    DirectionalLight lights[NUM_DIR_LIGHT];    // 5 directional light
    uint activeLightNum;                       // Num of active light

The light effect is calculated by the following function:

LightingColorOutput blinnPhongShading(vec3 normal)

    for(int i=0; i<activeLightNum; i++) // Loop through all directional lightings
        DirectionalLight dirLight = lights[i];  <<<<======== Problem! using [i] makes dirLight has value of all-zero!
        vec3 lightVec = dirLight.direction;
        vec4 lightCol = dirLight.color;

                calculate the light effect generate by this direction light ...



The line "DirectionalLight dirLight = lights[ i ];" cause the problem. When I use variable "i" to access array element, the structure has all 0 values, and therefore 3D objects appear to be black or very dark.

When I hard code the array index by 0, 1, 2, ..., then I got the correct values that I passed in by Vulkan code.

So the workaround is that I can do the loop unrolling like:

      calculateLightEffect( lights[0]);
      calculateLightEffect( lights[1]);
      calculateLightEffect( lights[2]);
      calculateLightEffect( lights[3]);

Certainly this is not a nice solution. 

Note that my Vulkan shader works well on nVidia, AMD, Intel, PowerVR and Adreno Gpus and I think it complies with Spir-V specs.  Is there any thing wrong when I use variable "i" as array index to access array elements? Or is there a special requirement for Mali Gpu? Thanks for any suggestions.


Parents Reply Children
More questions in this forum