Visual bug on Android with GPU Qualcomm Adreno

Found a bug? Post information about it here so we can fix it!

Moderator: Moderators

User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Visual bug on Android with GPU Qualcomm Adreno

Post by Ats »

After a lot of tries, I managed to find what's making the polygons to be upside down on API26+ with GPU Qualcomm Adreno, only with my game, definitely a weird bug...

It comes from BitmapCombine !!!

In order to create my randomly generated galaxy background, I create a Bitmap with:

Code: Select all

BitmapNoise (R)
BitmapNoise (G)
BitmapCombine
BitmapNoise (B)
BitmapCombine
BitmapExpression
(The last BitmapExpression is for forcing Pixel.A=1; otherwise it appears blank on API26+)

I made a quick mock-up in order to try (if you have a Huawei, Xiamoi or Xperia phone). Just press the screen to switch the background material and show the bug.

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="test" ScreenMode="0" FileVersion="2" AndroidPackageName="com.txori.test" AndroidPortrait="2">
  <OnLoaded>
    <SpawnModel Model="BackgroundModel"/>
    <SpawnModel Model="DebugModel"/>
  </OnLoaded>
  <OnUpdate>
    <ZExpression>
      <Expression>
<![CDATA[TouchCount=0;
if (touchGetCount()>0) TouchCount=1;]]>
      </Expression>
    </ZExpression>
    <KeyPress Comment="Mouse click" Keys="{">
      <OnPressed>
        <ZExpression Expression="TouchCount = 1;"/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <Content>
    <Mesh Name="DebugMesh">
      <Producers>
        <MeshBox/>
        <MeshSphere/>
        <MeshCombine/>
      </Producers>
    </Mesh>
    <Model Name="DebugModel" RotationVelocity="0.1 0.1 0.1">
      <OnRender>
        <UseMaterial Material="FlatMaterial"/>
        <RenderMesh Mesh="DebugMesh"/>
      </OnRender>
    </Model>
    <Material Name="FlatMaterial" Shading="1"/>
    <Group Comment="Background">
      <Children>
        <Model Name="BackgroundModel" Position="0 0 4">
          <OnRender>
            <Condition Expression="return TouchCount;">
              <OnTrue>
                <UseMaterial Material="MultiMaterial"/>
              </OnTrue>
              <OnFalse>
                <UseMaterial Material="SingleMaterial"/>
              </OnFalse>
            </Condition>
            <RenderMesh Mesh="BackgroundMesh"/>
          </OnRender>
        </Model>
        <Mesh Name="BackgroundMesh">
          <Producers>
            <MeshBox Scale="8 4.5 1" Grid2DOnly="255"/>
          </Producers>
        </Mesh>
        <Material Name="SingleMaterial" Shading="1" Light="0" ZBuffer="0">
          <Textures>
            <MaterialTexture Texture="SingleBitmap" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Material Name="MultiMaterial" Shading="1" Light="0" ZBuffer="0">
          <Textures>
            <MaterialTexture Texture="MultiBitmap" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Bitmap Name="SingleBitmap">
          <Producers>
            <BitmapNoise Color="1"/>
            <BitmapExpression>
              <Expression>
<![CDATA[//X,Y : current coordinate (0..1)
//Pixel : current color (rgb)
//Sample expression: Pixel.R=abs(sin(X*16));
//Pixel.R *= .6;
//Pixel.G *= .6;
//Pixel.B *= .6;
Pixel.A = 1;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Bitmap Name="MultiBitmap">
          <Producers>
            <BitmapNoise Comment="R" Offset="0.143" Persistence="0" ZHeight="0" Color="1" Tile="255"/>
            <BitmapNoise Comment="B" Offset="0.0637" Persistence="0" ZHeight="0" Color="3" Tile="255"/>
            <BitmapCombine/>
            <BitmapNoise Comment="G" Offset="0.0547" Persistence="0" ZHeight="0" Color="2" Tile="255"/>
            <BitmapCombine/>
            <BitmapExpression>
              <Expression>
<![CDATA[//X,Y : current coordinate (0..1)
//Pixel : current color (rgb)
//Sample expression: Pixel.R=abs(sin(X*16));
/*Pixel.R *= .8;
Pixel.G *= .8;
Pixel.B *= .8;*/
Pixel.A = 1;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
      </Children>
    </Group>
    <Variable Name="TouchCount" Type="4"/>
  </Content>
</ZApplication>
So either we find a way to make BitmapCombine to work, or I search how to get a fine galaxy texture using a single and clever BitmapExpression, or I can make three separate bitmaps and use blending to combine them... What do you think would be the best?

Edit:
For starters, I'm going to use this in order to release a working APK on Google Play:

Code: Select all

BitmapNoise (white)
BitmapExpression
  Pixel.R *= sin(X);
  Pixel.G *= sin(Y);
  Pixel.B *= cos(X);
  Pixel.A = 1;
Last edited by Ats on Sun Apr 25, 2021 5:34 am, edited 1 time in total.
User avatar
VilleK
Site Admin
Posts: 2318
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: OMEGANAUT

Post by VilleK »

I checked the source code for BitmapCombine and I can't see a way that would fail unless the OpenGL driver for the device is buggy. Which, sadly, might be a possibility.
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

No problem, I'm quite happy with my new galaxy using only one BitmapNoise, but it's good to know :wink:
User avatar
Kjell
Posts: 1910
Joined: Sat Feb 23, 2008 11:15 pm

Re: OMEGANAUT

Post by Kjell »

Hi guys,

BitmapCombine does seem to disable face culling inadvertently(?) on Android / ES ( using TBitmapCombine.ProduceOutput > GetCopyAsFloats > GLESPixelsFromTexture ) .. could have something to do with that.

K
User avatar
VilleK
Site Admin
Posts: 2318
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: OMEGANAUT

Post by VilleK »

Kjell: Yes I saw that but it saves and restores previous setting (via platform_android push/pop attrib).
User avatar
Kjell
Posts: 1910
Joined: Sat Feb 23, 2008 11:15 pm

Re: OMEGANAUT

Post by Kjell »

Hey,
VilleK wrote: Mon Jan 14, 2019 7:46 pmYes I saw that but it saves and restores previous setting (via platform_android push/pop attrib).
Ah right, the fakePushAttrib / fakePopAttrib procedures .. not sure what's going on then :-(

@Ats, I tried to replicate the problem on a couple of Android devices, but no cigar. What Adreno chipset are you experiencing the problem with? And you're sure it only happens with API26+?

K
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

You have to make the APK with the Android 9 template.
Here's all the devices I managed to test. The ones that have the bug are orange in the API28 column.
(White = did not test, red = crash at start, orange = bug, green = ok)

https://docs.google.com/spreadsheets/d/ ... p=drivesdk

The funny thing is that Samsung with Adreno are ok. Maybe it comes from something else such as EMUI interface. Anyway, if you have one of those devices, you'll see that you can see the inside of the rotating cube once you press the screen. And it don't come back to normal.

Edit: I've provided the apk API28 with the bug.
Attachments
bitmapcombine-debug.apk
(268.88 KiB) Downloaded 741 times
User avatar
VilleK
Site Admin
Posts: 2318
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: OMEGANAUT

Post by VilleK »

Kjell wrote: Mon Jan 14, 2019 8:32 pmAh right, the fakePushAttrib / fakePopAttrib procedures .. not sure what's going on then :-(
It could be a driver bug that the glGetIntegerv (used in PushAttrib) doesn't get the correct value for one or more of the flags. Which ends up with wrong values for face culling etc.
User avatar
Kjell
Posts: 1910
Joined: Sat Feb 23, 2008 11:15 pm

Re: OMEGANAUT

Post by Kjell »

Hi guys,

That should be pretty straight-forward to test though ... perhaps Ats can run the following project on a Android device that displays the problem and one that doesn't and see whether there's a difference? If not, the problem probably lies elsewhere.

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" ClearColor="0 0 0 1" FileVersion="2">
  <OnLoaded>
    <ZExternalLibrary ModuleName="opengl32">
      <BeforeInitExp>
<![CDATA[//

if(ANDROID)
{
  ModuleName = "libGLESv1_CM.so";
}]]>
      </BeforeInitExp>
      <Source>
<![CDATA[//

const int GL_CULL_FACE = 0x0B44;
const int GL_DEPTH_TEST = 0x0B71;

void glDisable(int cap){}
void glEnable(int cap){}
void glGetIntegerv(int pname, xptr params){}]]>
      </Source>
    </ZExternalLibrary>
    <SpawnModel Model="Donut"/>
  </OnLoaded>
  <OnUpdate>
    <Condition>
      <Expression>
<![CDATA[//

return App.Time < 4;]]>
      </Expression>
      <OnFalse>
        <ZExpression>
          <Expression>
<![CDATA[//

int flag = frac(App.Time * 0.5) < 0.5;

//

if(flag)
{
  glDisable(GL_CULL_FACE);
  glDisable(GL_DEPTH_TEST);
}
else
{
  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);
}]]>
          </Expression>
        </ZExpression>
      </OnFalse>
    </Condition>
    <ZExpression>
      <Expression>
<![CDATA[//

int c, d;

glGetIntegerv(GL_CULL_FACE, c);
glGetIntegerv(GL_DEPTH_TEST, d);

Print.Text =   "CULL   " + (c ? "TRUE " : "FALSE") + " " + intToStr(c)
           + "\nDEPTH  " + (d ? "TRUE " : "FALSE") + " " + intToStr(d);]]>
      </Expression>
    </ZExpression>
  </OnUpdate>
  <OnRender>
    <UseMaterial Material="PixelMaterial"/>
    <RenderText Name="Print" X="-0.9" Align="1"/>
    <Condition>
      <Expression>
<![CDATA[//

return App.Time < 4;]]>
      </Expression>
      <OnTrue>
        <RenderText Text="PLEASE WAIT" X="-0.9" Y="0.25" Align="1"/>
      </OnTrue>
    </Condition>
  </OnRender>
  <Content>
    <Font Name="Pixel" Bitmap="PixelBitmap" FirstChar="48" CharPixelWidth="6" CharPixelHeight="8"/>
    <Bitmap Name="PixelBitmap" Width="258" Height="8" Filter="1">
      <Producers>
        <BitmapFromFile DataWidth="258" DataHeight="8">
          <BitmapFile>
<![CDATA[78DAED58810E852008CCFFFFE8DA6B7B2E098E036DD9CAB5D64C45F00E9065F9DAC35BD91FF0975CE4DD6DFD37AB676D9B35ABF69F670159C729E47E6E3797F866340506AC9DAA82E75972273B0B541B5678E33DFF7A8A3E061CAB7A76423ABF0E8904758C58169C146379E6DBFD6B9925210BCB9D8A059D3DBC9D19163490288B0A1229AB8CD70220338D0415F32EE3D27866B08D7C4B84050C979FCB0266D6581634030A657FCC02E033937B0E22104B07D420F11CE28B19760D0FE066053860A9216C9E04F2880D374F60F228B08E2A2BC402C7AD151357D8D362DDF98CB1870539FF998B1AEE6A2043633C7954D3B7C582D0BD201D0BC41B38D8B1D9E04016F4246FAAE749E4751F0B6EBF17582C70EF0502FC5768DA732F182B6BC86D3D5423021506A6FA34558D88A9FFA46B448CC57A586072B0A34694D09D41C2A51C14B236950B2D48]]>
          </BitmapFile>
        </BitmapFromFile>
      </Producers>
    </Bitmap>
    <Material Name="PixelMaterial" Font="Pixel"/>
    <Model Name="Donut" RotationVelocity="0.2 0 0.1">
      <OnRender>
        <UseMaterial Material="DonutMaterial"/>
        <RenderMesh Mesh="DonutMesh"/>
      </OnRender>
    </Model>
    <Mesh Name="DonutMesh">
      <Producers>
        <MeshBox XCount="7" YCount="7" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0">
          <Expression>
<![CDATA[//

float s, r, x, y;

x = V.X*PI;
y = V.Y*PI;

V.X = cos(x)*cos(y)+cos(x)*2;
V.Y = sin(x)*cos(y)+sin(x)*2;
V.Z = sin(y);

N.X = cos(x)*cos(y);
N.Y = sin(x)*cos(y);
N.Z = V.Z;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Bitmap Name="RedBitmap">
      <Producers>
        <BitmapExpression>
          <Expression>
<![CDATA[//

Pixel.R = 1;
Pixel.G = X;
Pixel.B = Y;
Pixel.A = 1;]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Bitmap Name="BlueBitmap">
      <Producers>
        <BitmapExpression>
          <Expression>
<![CDATA[//

Pixel.R = X;
Pixel.G = Y;
Pixel.B = 1;
Pixel.A = 1;]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Bitmap Name="DonutBitmap">
      <Producers>
        <BitmapLoad Bitmap="RedBitmap"/>
        <BitmapLoad Bitmap="BlueBitmap"/>
        <BitmapCombine Method="2"/>
      </Producers>
    </Bitmap>
    <Material Name="DonutMaterial" Shading="1">
      <Textures>
        <MaterialTexture Texture="DonutBitmap" TextureScale="8 8 1" TextureWrapMode="1" TexCoords="1" Origin="0 0 0"/>
      </Textures>
    </Material>
  </Content>
</ZApplication>
K
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

No problem. Here's the apk and the results:

On my Galaxy S6:

Code: Select all

cull   false 0  true 1
depth  false 0  true 1
And the same result on a friend's Nexus 5 that have the bug:

Code: Select all

cull   false 0  true 1
depth  false 0  true 1
Tomorow, I can try the Xperia X that have the bug too.
Attachments
test_cull_face-debug.apk
(269.31 KiB) Downloaded 681 times
User avatar
Kjell
Posts: 1910
Joined: Sat Feb 23, 2008 11:15 pm

Re: OMEGANAUT

Post by Kjell »

Hi Ats,

I've updated the project code snippet ( see my previous post ) with a spinning donut in the background that uses a texture generated using BitmapCombine. Also, for the first 3 seconds the OpenGL cull_face and depth_test states aren't written, so it should use whatever state they are in after the bitmaps have been generated ( for those 3 seconds ) .. just to confirm that BitmapCombine is really causing the problem.

Could you give it another spin? :wink:

Thanks!
K
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

For starters, I had to add Pixel.A=1 to your BitmapExpression otherwise it appears white on API28 (since API23):

Image

Since there's a lot of things going on and I'm not sure what to explain, I made a video.
On Galaxy S6, faces are inverted when false, but only on one side on the donut, same as on PC:

https://streamable.com/s/yfcn2/ezmhcv

And I asked my friend in Argentina to do the same. It's worldwide debugging 8)
On Nexus 5, it seems to be the same:

https://streamable.com/j7l36
User avatar
Kjell
Posts: 1910
Joined: Sat Feb 23, 2008 11:15 pm

Re: OMEGANAUT

Post by Kjell »

Hi Ats,
Ats wrote: Tue Jan 15, 2019 4:03 pmI had to add Pixel.A=1 to your BitmapExpression otherwise it appears white on API28
Ah sorry, forgot about that :oops:

I noticed a interesting difference .. seems like on Nexus 5 both CULL and DEPTH start as false ( which is incorrect ) while on Galaxy S6 they start as true. On both phones they do switch between TRUE and FALSE though, which would mean it's a ZGE bug. It's not very clear whether the 3 seconds are over or not right now though, so i've added a "PLEASE WAIT" message during that period ( check the updated code snippet here ).

K
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

I'll test that tomorrow when I'll have a Xperia X (with the bug) to test next to my Galaxy S6.
User avatar
Ats
Posts: 710
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: OMEGANAUT

Post by Ats »

So the Android phone with the bug definitely starts with everything being false:

Galaxy S6

Image

Xperia X

Image

Can that come from the compilation parameters of the libzgeandroid.so? Or is it a bug in the source code?
Post Reply