Forums - Problem with setting 2D-texture in shader on GPU Adreno 200 (Android)

16 posts / 0 new
Last post
Problem with setting 2D-texture in shader on GPU Adreno 200 (Android)
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Wed, 2012-01-18 12:52
I've found the problem with setting 2D-texture in shader on GPU Adreno 200(HTC Desire, LG P500).
One shader is using in the scene for all objects:

vertexs shader:
----------------------
attribute vec4 av4position;
attribute vec2 av2texcoord;

uniform mat4 mvp;

varying vec2 vv2texcoord;

void main()
{
	vv2texcoord = av2texcoord;
	gl_Position = mvp*av4position;
}
----------------------

fragment shader:
----------------------
precision mediump float;

uniform sampler2D texture0;

varying vec2 vv2texcoord;

void main()
{
	gl_FragColor = texture2D(texture0, vv2texcoord);
}
----------------------

I'm calling glUseProgram once in program.
Once in program I'm loading textures to texture units GL_TEXTURE0-GL_TEXTURE3 (Adreno profiler
shows that they are correctly downloaded and installed).

Next, for each object is setting the texture through glUniform1i(one of 0-3),
setting matrix ModelView, vertex buffers and calling glDrawElements.

The commands from the window API Calls in Adreno profiler for one object are below:
----------------------
glBindBuffer(target=GL_ARRAY_BUFFER, buffer=4)

glBindBuffer(target=GL_ELEMET_ARRAY_BUFFER, buffer=5)

glUniform1i(location=1. x=1)

glUniformMatrix4fv(location=0. count=1. transpose=0)
( 0.056976. -0.007855. 0.065743. 0.065612)
(-0.103458. -0.004326. 0.036206. 0.036134)
( 0.000000. 0.176937. 0.003804. 0.003796)
(-30.800861.-29.093822. 113.769836. 115.540527)

glVertexAttribPointer(indx=1. size=3.type=GL_FLOAT. normalized=0. stride=20. ptr=0x00000000)

glEnableVertexAttribPointer(index=1)

glVertexAttribPointer(indx=0. size=2.type=GL_FLOAT. normalized=0. stride=20. ptr=0x0000000C)

glEnableVertexAttribPointer(index=0)

glDraWElements(mode=GL_TRIANGLES. count=1638. type=GL_UNSIGNED_SHORT. indices=0x00000000. CurrentElementArrayBinding=5)
----------------------

As a result, all objects in the scene have the same texture as the first drawn object.
The captured frame in Adreno profiler (Scrubber v2.x) is drawing correctly.
On the other GPU (PowerVR 540, Tegra2, Mali400) the same scene is drawing correctly.
If use your own copy of the shader for each object, it is drawn correctly.

If for each object call glUseProgram(my_shader), and after drawing the set null-shader glUseProgram(0)
the scene is drawn correctly. But the FPS goes down due to frequent changes of shaders.

It looks like after calling glDrawElements driver remembers the number of texture for active shader.
And it can not be changed after that.
Can you tell me please where is the issue?
  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Mon, 2012-02-13 08:51

You can confirm or deny that this is a problem in the driver?

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Thu, 2012-04-05 09:04

Any ideas?

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Thu, 2012-04-05 09:48

Hi Alexander..

Seems like you are correct with your assumptions about not wanting to switch the shader program for performance reasons.  It would be useful to better analyze the problem if you could submit an apk that shows the different rendering results from on an Adreno 200 device and the Adreno profiler.  Showing more of your sample code (all per frame, per object calls) would help as well..

-mark

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Fri, 2012-04-06 04:01

apk file https://docs.google.com/open?id=0ByhICHiEz2nsREFMU2dUcVJRQk9ZNzQwU01IbzYtdw

Ship and sky have same texture on device.

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Fri, 2012-04-13 08:00

are there any news?

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Mon, 2012-04-16 09:29

Hi Alex - I'm not seeing a call to glGetUniformLocation to get the uniform's location.  Looks like it's possibly hardcoded to 1, but that could change depending on the shader compiler being used.

Also the example you pointed me to looks like it has 3 shaders (might want to simplfy a bit more).

 

-mark

 

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Tue, 2012-04-17 02:30

I created simple test without using ndk. Link https://docs.google.com/open?id=0ByhICHiEz2nsMHMxSnFPUm9MZG8

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Tue, 2012-04-17 07:38

Alex - appreciate your effort in creating this simple example.  Having some problems pulling down the zip file (is there another location you can put it?), but was able to browse GLSurface.java  Was able to run the apk (on more recent hardware) and saw 3 triangles (greem, red, and blue).  Noticed in your code that you are using glGetUniformLocation.

 

1) Not able to run profiler since no network permissions set in the manifest

2) With this simple example, what are you seeing when you run on your hardware?

 

thanks,

mark

 

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Tue, 2012-04-17 09:21

Sorry, I forgot about setting permissions in the manifest. Here is a link to a new apk https://docs.google.com/open?id=0ByhICHiEz2nsVWhwUGZ1TW5kdzQ

On Adreno200(HTC Desire) all 3 triangles have red color. On my NexusS(PowerVR540) or else non-adreno devices everything looks fine.

 

P.S. for easy downloading previous zip-file just press ctrl+s.

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Tue, 2012-04-17 11:32

Was able to successfully run the apk and profile on one our current test devices, and also confirmed that on an Adreno 200 device the triangles are indeed all red. 

Curious about your glGenTextures call - looks like there's a 3rd parameter - 0

Also profiler is showing the blue texture as RGBA and the red and green as RGB.  Any reason they would be different?

One more item:  Check out: http://www.opengl.org/wiki/GLSL_Sampler#Binding_textures_to_samplers

You probably need to add a glActiveTexture call before binding.

 

-mark

 

 

thanks,

mark f.

 

 

 

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Wed, 2012-04-18 01:32

I modified the project. Format of textures now RGB. I added calls glActiveTexture and glBindTexture to drawObject function. Result is the same. In glGenTextures the 3rd parameter must be 0 - is the offset in the array. https://docs.google.com/open?id=0ByhICHiEz2nsTDBvVFdMSHY4Z2M

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Wed, 2012-04-18 07:52

Alex - Could you verify the values of the 3 texture_id's created in loadTexture?  It's not too common to use the offset parameter in glGenTextures...  You could get by with:

 

int texture_id;

GLES20.glGenTextures(1, &texture_id);

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Wed, 2012-04-18 10:05

For C++ we have void glGenTextures(GLsizei n, GLuint* textures) defined in "gl2.h" on example.

But for java-android available only public static void glGenTextures (int n, IntBuffer textures) or public static void glGenTextures (int n, int[] textures, int offset) in android.opengl.GLES20 class (http://developer.android.com/reference/android/opengl/GLES20.html#glGenT...)

  • Up0
  • Down0
Mark_Feldman Moderator
Join Date: 4 Jan 12
Posts: 61
Posted: Thu, 2012-04-19 08:02

We've looked at this more closely and believe it might actually be an issue in our Adreno 200 drivers.  It's not a common way of using multiple textures in a shader, but still should work as you have noted.

Adding an addition glBindTexture(GL_TEXTURE_2D,0)  call to reset the textures should be an easy workaround:

 

    public void drawObject(Buffer vb, Buffer tb, int texture_bind_index, int texture_id)
    {
        GLES20.glUseProgram(program);
       
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0+texture_bind_index);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture_id);
       
        GLES20.glUniformMatrix4fv(loc_matrix, 1, false, matrix, 0);
        GLES20.glUniform1i(loc_sampler, texture_bind_index);
       
        GLES20.glVertexAttribPointer(loc_position, 3, GLES20.GL_FLOAT, false, 0, vb);
        GLES20.glVertexAttribPointer(loc_texcoord, 2, GLES20.GL_FLOAT, false, 0, tb);
       
        GLES20.glEnableVertexAttribArray(loc_position);
        GLES20.glEnableVertexAttribArray(loc_texcoord);
       
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
       
        GLES20.glDisableVertexAttribArray(loc_position);
        GLES20.glDisableVertexAttribArray(loc_texcoord);
       
       
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
       
       
    }

  • Up0
  • Down0
alorken@bk.ru
Join Date: 10 Jan 12
Posts: 20
Posted: Fri, 2012-04-20 02:35

Mark, thank you for your answers. In my case glBindTexture(GL_TEXTURE_2D,0)  call nullify an attempt to reduce the number of installing of textures. I think better will be created for each object instance of a shader. glUseProgam is easier to glBindTexture for performance?

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.