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:

if(lights[0].isActive)
      calculateLightEffect( lights[0]);
if(lights[1].isActive)
      calculateLightEffect( lights[1]);
if(lights[2].isActive)
      calculateLightEffect( lights[2]);
if(lights[3].isActive)
      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
No Data