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
  • Hi Hongkun, 

    Thanks for the bug report.

    First question: What device, Mali GPU, and Mali driver version are you trying to use this on? The quickest means to find the GPU information is to open the URL "chrome://gpu" in the Chrome browser, and look for the GL_RENDERER and GL_VERSION strings in the resulting page.

    Second question: Can you share the complete shader (GLSL and SPIRV) that causes the problem so we can try to reproduce the issue you are seeing.

    Cheers, 
    Pete

Reply
  • Hi Hongkun, 

    Thanks for the bug report.

    First question: What device, Mali GPU, and Mali driver version are you trying to use this on? The quickest means to find the GPU information is to open the URL "chrome://gpu" in the Chrome browser, and look for the GL_RENDERER and GL_VERSION strings in the resulting page.

    Second question: Can you share the complete shader (GLSL and SPIRV) that causes the problem so we can try to reproduce the issue you are seeing.

    Cheers, 
    Pete

Children
More questions in this forum