Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


uniforms optimized-out


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 syskrank   Members   -  Reputation: 191

Like
0Likes
Like

Posted 14 August 2014 - 03:09 AM

Hi.

I'm facing the problem that GLSL optimizer eliminates my uniforms, that are actually used.

Here's my vertex shader:

#version 120
#ifdef GL_ES
precision mediump float
#endif

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;

attribute vec2 a_boneWeight0;
attribute vec2 a_boneWeight1;
attribute vec2 a_boneWeight2;
attribute vec2 a_boneWeight3;
attribute vec2 a_boneWeight4;
attribute vec2 a_boneWeight5;
attribute vec2 a_boneWeight6;
attribute vec2 a_boneWeight7;

// uniforms
uniform mat4 MVP;
uniform mat4 shadowMVP;
uniform int useBoneWeight[8]; // use numbered bone or not
uniform mat4 boneTransform[8];
uniform int useSkinning;
 
//// outputs
#ifdef GL_ES
    varying medium vec3 normal;
    varying medium vec3 worldPos;
    varying medium vec2 textureCoord;
    varying medium vec4 shadowCoord;
#else
    varying vec3 normal;
    varying vec3 worldPos;
    varying vec2 textureCoord;
    varying vec4 shadowCoord;
#endif

void main() {
    shadowCoord = shadowMVP * vec4( a_position, 1.0f );
    textureCoord = a_texCoord0;
    mat4 skinning = mat4( 0.0 );
    if ( 1 == useSkinning )  {
        skinning += ( ( a_boneWeight0.y ) * boneTransform[ int( a_boneWeight0.x ) ] * useBoneWeight[ 0 ] );
        skinning += ( ( a_boneWeight1.y ) * boneTransform[ int( a_boneWeight1.x ) ] * useBoneWeight[ 1 ] );
        skinning += ( ( a_boneWeight2.y ) * boneTransform[ int( a_boneWeight2.x ) ] * useBoneWeight[ 2 ] );
        skinning += ( a_boneWeight3.y ) * boneTransform[ int( a_boneWeight3.x ) ] * useBoneWeight[ 3 ];
        skinning += ( a_boneWeight4.y ) * boneTransform[ int( a_boneWeight4.x ) ] * useBoneWeight[ 4 ];
        skinning += ( a_boneWeight5.y ) * boneTransform[ int( a_boneWeight5.x ) ] * useBoneWeight[ 5 ];
        skinning += ( a_boneWeight6.y ) * boneTransform[ int( a_boneWeight6.x ) ] * useBoneWeight[ 6 ];
        skinning += ( a_boneWeight7.y ) * boneTransform[ int( a_boneWeight7.x ) ] * useBoneWeight[ 7 ];
        gl_Position = MVP * skinning * vec4( a_position, 1.0f );
        normal = ( MVP * skinning * vec4( a_normal, 0.0f ) ).xyz;
        worldPos = ( MVP * skinning * vec4( a_position, 1.0f ) ).xyz;
    } else {
        gl_Position = MVP * vec4( a_position, 1.0f );
        normal = ( MVP * vec4( a_normal, 0.0f ) ).xyz;
        worldPos = ( MVP * vec4( a_position, 1.0f ) ).xyz;
    }
}

Uniforms 'useBoneWeights' and 'boneTransform' are erased during optimization.

I've tried to get their location with glGetUniformLocation() querying them by array name and array indexed elements.

All other parts of the shader are working fine.

 

I'm using Java and libgdx1.2.0 ( thus - opengl es 2.0 ) and my semi-custom shader system ( incapsulated libgdx' Shader class to give it more 'native' C/C++ interface ).



Sponsor:

#2 Ashaman73   Crossbones+   -  Reputation: 7793

Like
0Likes
Like

Posted 14 August 2014 - 03:24 AM


I've tried to get their location with glGetUniformLocation() querying them by array name and array indexed elements.

Can you show the code where you query the location ?



#3 syskrank   Members   -  Reputation: 191

Like
0Likes
Like

Posted 14 August 2014 - 03:44 AM

Ok, here it is. I'm building on top of libgdx' ShaderProgram :

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Disposable;

import java.util.Map;
import java.util.HashMap;

public class Shader implements Disposable {
    public ShaderProgram program;
    public Map<String, Integer> uniforms;
    public final static String SHADER_TAG = Shader.class.getSimpleName();

    public static final int SHADER_OK = 0;
    public static final int SHADER_ERROR = 1;

    public Shader( String vertexShader, String fragmentShader ) {
        ShaderProgram.pedantic = false;
        program = new ShaderProgram( Gdx.files.internal( vertexShader ), Gdx.files.internal( fragmentShader ) );
        if ( program.isCompiled() ) {
            Gdx.app.log( SHADER_TAG, "Shader compiled." );
        } else {
            Gdx.app.log( SHADER_TAG, "Shader compilation failed: " + program.getLog() );
        }
        uniforms = new HashMap<String, Integer>();
    }

    public void bind() {
        program.begin();
    }

    public void unbind() {
        program.end();
    }

    public int addUniform( String name ) {
        int location = program.getUniformLocation( name );
        if ( -1 == location ) {
            Gdx.app.log( SHADER_TAG, "Failed to get uniform's '" + name + "' location." );
            return SHADER_ERROR;
        } else {
            uniforms.put( name, location );
        }
        return SHADER_OK;
    }

    public int setUniformInt( String name, int value ) {
        Integer location = uniforms.get( name );
        if ( null == location ) {
            Gdx.app.log( SHADER_TAG, "Integer uniform '" + name + "' doesn't exists." );
            return SHADER_ERROR;
        } else {
            program.setUniformi( location.intValue(), value );
        }
        return SHADER_OK;
    }

    public int setUniformFloat( String name, float value ) {
        Integer location = uniforms.get( name );
        if ( null == location ) {
            Gdx.app.log( SHADER_TAG, "Float uniform '" + name + "' doesn't exists." );
            return SHADER_ERROR;
        } else {
            program.setUniformf( location.intValue(), value );
        }
        return SHADER_OK;
    }

    public int setUniformVec2( String name, Vector2 value ) {
        Integer location = uniforms.get( name );
        if ( null == location ) {
            Gdx.app.log( SHADER_TAG, "Vector2 uniform '" + name + "' doesn't exists." );
            return SHADER_ERROR;
        } else {
            program.setUniformf( location.intValue(), value );
        }
        return SHADER_OK;
    }

    public int setUniformVec3( String name, Vector3 value ) {
        Integer location = uniforms.get( name );
        if ( null == location ) {
            Gdx.app.log( SHADER_TAG, "Vector3 uniform '" + name + "' doesn't exists." );
            return SHADER_ERROR;
        } else {
            program.setUniformf( location.intValue(), value );
        }
        return SHADER_OK;
    }

    public int setUniformMat4( String name, Matrix4 value ) {
        Integer location = uniforms.get( name );
        if ( null == location ) {
            Gdx.app.log( SHADER_TAG, "Matrix4 uniform '" + name + "' doesn't exists." );
            return SHADER_ERROR;
        } else {
            program.setUniformMatrix( location.intValue(), value );
        }
        return SHADER_OK;
    }

    @Override
    public void dispose() {
        program.dispose();
    }

}

ShaderProgram, in it's turn, has the following code inside:

    private void fetchUniforms () {
        params.clear();
        Gdx.gl20.glGetProgramiv(program, GL20.GL_ACTIVE_UNIFORMS, params);
        int numUniforms = params.get(0);

        uniformNames = new String[numUniforms];

        for (int i = 0; i < numUniforms; i++) {
            params.clear();
            params.put(0, 1);
            type.clear();
            String name = Gdx.gl20.glGetActiveUniform(program, i, params, type);
            int location = Gdx.gl20.glGetUniformLocation(program, name);
            uniforms.put(name, location);
            uniformTypes.put(name, type.get(0));
            uniformSizes.put(name, params.get(0));
            uniformNames[i] = name;
        }
    }

So, yeah, basically, I'm fetching uniforms not directly from shader, but from libgdx' object, which kind of sucks.


Edited by syskrank, 14 August 2014 - 03:46 AM.


#4 Stainless   Members   -  Reputation: 1014

Like
0Likes
Like

Posted 14 August 2014 - 06:31 AM

do a sanity check

 

bump #version 120 up and recompile see if the problem persists.

 

From the code above it's too difficult to work out what's wrong. Maybe print out name and location in the for loop of fetchUniforms and see what that tells you.



#5 Erik Rufelt   Crossbones+   -  Reputation: 3512

Like
0Likes
Like

Posted 14 August 2014 - 09:03 AM

What OS/GPU do you run it on?



#6 syskrank   Members   -  Reputation: 191

Like
0Likes
Like

Posted 14 August 2014 - 09:11 AM

Hi, Stainless.

What do you mean by sanity check?

I've tried playing with shader 'version' string with no luck.

 

Edit: I mentioned that my Java Shader object detects only the first element of the uniform array:  'useBoneWeight[0]' and 'boneTransform[0]' are located;

So, theoretically, I can use OpenGL's glUniform*() capabilities to send a whole array of data to the shader.

I will try that somehow.

 

 

What OS/GPU do you run it on?

 

I'm developing on two machines with Linux Mint 16 and Linux Debian 7 resp.

First system has Intel HD4000 and NV GF740M cards ( tried both ) and the last one has NV GT630. I'm using libgdx 1.2.0.

Android emulator produces same results.


Edited by syskrank, 14 August 2014 - 09:26 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS