PDA

View Full Version : Simple OpenGL 4.X does not run on GTX 480 but runs on ATI



sueyllam
08-26-2014, 08:32 AM
A simple program that draws a triangle with 3 vertices in red over a white background using a simple one liner vshader and fshader that simply reads the 3 vertices and sets the color to red respectively runs as expected on a computer with an ATI card but crashes on a computer with GeForce 480X.
Upon examining the capabilities of the cards using GPU_CAPS I found that the shading language version for the NVIDIA card is suffixed by : via cg compiler while the ATI card does not have this suffix in the shading language version.
Older opengl programs 2.X not using shaders run fine on both.

I do not know what need to be done to get the opengl programs using glsl running on GeForce GTX 480? Any clues?

Yandersen
08-26-2014, 01:25 PM
Sorry, there are no telepathy-people here. Give us the code of the program in question - that would help. :)

sueyllam
08-26-2014, 04:28 PM
Well I was expecting an opengl program that draws a red triangle on a white background using programmable shaders and does work on both ATI and GeForce cards.
Anyway here is the code that works on ATI and crashes on GeForce:

test.cpp


// Two-Dimensional Sierpinski Gasket
// Generated using randomly selected vertices and bisection

#include "Angel.h"


//----------------------------------------------------------------------------

void
init( void )
{

// Specifiy the vertices for a triangle
vec4 vertices[3] = {
vec4( -1.0, -1.0, 0.0, 1.0 ), vec4( 0.0, 1.0, 0.0, 1.0 ), vec4( 1.0, -1.0, 0.0, 1.0 )
};

// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW );

// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader21.glsl", "fshader21.glsl" );
glUseProgram( program );

// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );

glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background
}

//----------------------------------------------------------------------------

void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT ); // clear the window
glDrawArrays( GL_TRIANGLES, 0, 3 ); // draw the points
glFlush();
}

//----------------------------------------------------------------------------

void
keyboard( unsigned char key, int x, int y )
{
switch ( key ) {
case 033:
exit( EXIT_SUCCESS );
break;
}
}

//----------------------------------------------------------------------------

int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA );
glutInitWindowSize( 512, 512 );

// If you are using freeglut, the next two lines will check if
// the code is truly 3.2. Otherwise, comment them out

glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );

glutCreateWindow( "Sierpinski Gasket" );

glewInit();

init();

glutDisplayFunc( display );
glutKeyboardFunc( keyboard );

glutMainLoop();
return 0;
}


vshader21.glsl:


#version 150

in vec4 vPosition;

void
main()
{
gl_Position = vPosition;
}


fshader21.glsl:


#version 150

out vec4 fColor;

void
main()
{
fColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}


Finally InitShader.cpp:


#include "Angel.h"

namespace Angel {

// Create a NULL-terminated string by reading the provided file
static char*
readShaderSource(const char* shaderFile)
{
FILE* fp = fopen(shaderFile, "r");

if ( fp == NULL ) { return NULL; }

fseek(fp, 0L, SEEK_END);
long size = ftell(fp);

fseek(fp, 0L, SEEK_SET);
char* buf = new char[size + 1];
fread(buf, 1, size, fp);

buf[size] = '\0';
fclose(fp);

return buf;
}


// Create a GLSL program object from vertex and fragment shader files
GLuint
InitShader(const char* vShaderFile, const char* fShaderFile)
{
struct Shader {
const char* filename;
GLenum type;
GLchar* source;
} shaders[2] = {
{ vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
};

GLuint program = glCreateProgram();

for ( int i = 0; i < 2; ++i ) {
Shader& s = shaders[i];
s.source = readShaderSource( s.filename );
if ( shaders[i].source == NULL ) {
std::cerr << "Failed to read " << s.filename << std::endl;
exit( EXIT_FAILURE );
}

GLuint shader = glCreateShader( s.type );
glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );
glCompileShader( shader );

GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
std::cerr << s.filename << " failed to compile:" << std::endl;
GLint logSize;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( shader, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;

exit( EXIT_FAILURE );
}

delete [] s.source;

glAttachShader( program, shader );
}

/* link and error check */
glLinkProgram(program);

GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
std::cerr << "Shader program failed to link" << std::endl;
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;

exit( EXIT_FAILURE );
}

/* use program object */
glUseProgram(program);

return program;
}

} // Close namespace Angel block

Yandersen
08-26-2014, 06:17 PM
I do not see the call to the glBindFragDataLocation (http://www.opengl.org/sdk/docs/man3/xhtml/glBindFragDataLocation.xml)(program, 0, "fColor")

When exactly does the program crashes? Did you debugged it step-by-step?

malexander
08-26-2014, 06:18 PM
As there is only one fragment shader output, fColor will be at data location zero.

sueyllam
08-27-2014, 01:02 AM
No I did not debug it, but I will add it and see if it works, but where do I add it?

sueyllam
08-27-2014, 01:04 AM
But what about vPosition?

sueyllam
08-27-2014, 01:21 AM
After doing some search on net I found the following shaders:

vshader.glsl

#version 330

layout (location = 0) in vec4 Position;

void main()
{
gl_Position = Position;
}

fshader.glsl:

#version 330

out vec4 FragColor;

void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Would that be enough and sets Position at location 0? or I still need to bind FragColor to location 0?

Yandersen
08-27-2014, 04:28 AM
fshader.glsl:

#version 420

layout(location = 0) out vec4 FragColor;

void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}


---

I am not sure if version of GLSL 4.2 is required though - maybe 3.3 is sufficient. Try and see.

sueyllam
08-28-2014, 01:45 AM
Still does not Work. So I did trace the execution and found that the last message that get printed is just Before the call to glGenVertexArrays inside the init() function in test.cpp and the message just after this call does not get printed. So I guess it crashes inside this openGl function. I am using gcc4.6.2 from mingw and the same configuration works on ATI card. I changed the shader and added layout to both fshader and vshader and still not working.

sueyllam
08-28-2014, 02:43 AM
Well after locating where the crash occurs and doing some serach on net, I found the cause is glGenVertexArrays in GL core mode sometimes cause problems with glew so just before glewInit() add the line:
glewExperimental = GL_TRUE;
and it works
I found the answer here:
http://stackoverflow.com/questions/13558073/program-crash-on-glgenvertexarrays-call
Hope this will help others...

sueyllam
08-28-2014, 02:56 AM
And just for the curious I reverted to the original code without layout in shaders and used version 330 and it did work on both ATI and GeForce. So it was a glew problem...

Yandersen
08-28-2014, 04:23 AM
Well, if you want an easy alternative for glew, may I suggest using my LoadGL.h (https://docs.google.com/uc?export=download&id=0B5M-5LxIj9ZDV3JiQXFBM1Z5eVk) header. It has all OpenGL constants defined in it as well as function pointers up to 4.4 version. In contrast to other wrappers and loaders, this one loads each OpenGL function you ever call the first time it is called, independently from the others, therefore you do not need to bother initializing anything - simply dump the file into your project directory and place an #include "LoadGL.h" somewhere in it.
Just an option. :)

sueyllam
08-28-2014, 05:54 AM
Thanks, I will give it a try. Another fix, is by keeping the original code and just change the profile from GLUT_CORE_PROFILE into GLUT_COMPATIBILITY_PROFILE and it works fine, without adding anything else or changing anything else...