PDA

View Full Version : invalid operation after glUseProgram



destiny
03-13-2008, 08:24 PM
I'm a begginer with glsl.I tried to load and use shaders in my program.According to gDEbugger,my shaders have been compiled successfully and the program has been linked successfully too.
But when I use a VBO to render something, an OPENGL error occurred,
Function Name: glDrawArrays
Error code: GL_INVALID_OPERATION.
Error description:
The specified operation is not allowed in the current state. The offending function is ignored, having no side effect other than to set the error flag.
Here are my source code:
glUseProgram(p);
glEnableClientState(GL_VERTEX_ARRAY);
//VBO
GLuint iVertexBuffer = 0;
glGenBuffers(1, &iVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, iVertexBuffer);
length=length*sizeof(VertexArray);
glBufferData(GL_ARRAY_BUFFER, length,VertexArray, GL_STATIC_DRAW);
delete [] VertexArray;
glBindBuffer(GL_ARRAY_BUFFER, iVertexBuffer);
glVertexPointer( 2, GL_INT, 0, (char *) NULL );
length=imageInUseSize[1]*2+1;
glDrawArrays(GL_TRIANGLE_FAN,0,length);
glUseProgram(0);

Thank you in advance.

Relic
03-14-2008, 01:26 AM
First, avoid GL_INT vertex array data, that might not be accelerated. Use GL_FLOAT.

There are a little too many "length" variables with different meanings inside that snippet to know what's going on.

Is the length=imageInUseSize[1]*2+1; matching the number of vertices you put into the draw buffer earlier with length=length*sizeof(VertexArray);

Are all other attribute arrays disabled?

destiny
03-14-2008, 01:49 AM
int length=imageInUseSize[1]*4+2;
int *VertexArray=new int[length];

The length of the vertexarray is imageInUseSize[1]*4+2,and the number of vertices is imageInUseSize[1]*2+1.
IS it wrong?
And also the using of uniforms is an invalid operation?

GLint loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8,loc9,loc10 ,loc11,loc12,loc13,loc14,loc15;

loc1 = glGetUniformLocation(p,"centerscale");
glUniform1f(loc1,centerScale);

loc2=glGetUniformLocation(p,"offset");
glUniform2f(loc2,offsetX,offsetY);

loc3=glGetUniformLocation(p,"imageViewportSize");
glUniform2f(loc3,static_cast<float>(imageViewportSize[0]),
static_cast<float>(imageViewportSize[1]));

destiny
03-14-2008, 02:15 AM
I'm sure all the other array attributes are disabled.

GL_LIST_MODE is GL_COMPILE, does it matter?

light,blend,texture1d,GL_PACK_ALIGNMENT are true

Relic
03-14-2008, 06:37 AM
Sorry, you simply need to post more code (use the code tags!) or debug that more thoroughly.

For example things not visible inside your code snippet:
length=length*sizeof(VertexArray);

What is length before this point?
The sizeof() on the array variable already returns the total number of bytes in that array. So unless length is 1 before, this accesses the array out of bounds in glBufferData (=> could crash).

glUniform only works on the currently bound program (obviously because it has no program object as parameter), you must issue glUniform calls AFTER glUseProgram(yourprogram).

PACK_ALIGNMENT is related to pixel store, not vertex arrays.

And what have display lists to do with any of the above?

Other things to try: Does the code above run if you use standard vertex arrays and no VBO?

destiny
03-14-2008, 06:53 AM
the length before this point is int length=imageInUseSize[1]*4+2

The display list has nothing with my code.I just tried to extent other people's class library.And I find an error(invalid operation) when it comes to glcalllist,but I think it would have no side effect,is that right?

I have tried just vertex array,failed too

destiny
03-14-2008, 07:01 AM
int centerj=imageInUseSize[1]/2;
int centeri=(rowBounds[centerj*2]+rowBounds[centerj*2+1])/2;

int length=imageInUseSize[1]*4+2;
float *VertexArray=new float[length];

*VertexArray=centeri;
*(VertexArray+1)=centerj;
for ( j = 0; j < imageInUseSize[1]; j++ )
{
VertexArray[2+2*j] = static_cast<float>(rowBounds[j*2]);
VertexArray[2+2*j+1]=static_cast<float>(j);
}
k=2+2*j;
i=0;
j--;
for(;j>=0;j--)
{
VertexArray[k+2*i]=static_cast<float>(rowBounds[j*2+1]);
VertexArray[k+2*i+1]=static_cast<float>(j);
i++;
}

glewInit();
glGenBuffers = (PFNGLGENBUFFERSARBPROC) wglGetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERARBPROC) wglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAARBPROC) wglGetProcAddress("glBufferData");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC) wglGetProcAddress("glDeleteBuffers");
glDisable( GL_LIGHTING );
initShader();

//load shader
GLuint v=0,f=0,p=0;
char *vs = NULL,*fs = NULL;
glCreateProgram_ptr glCreateProgram;
if(0 == (glCreateProgram = reinterpret_cast<glCreateProgram_ptr>(wglGetProcAddress("glCreateProgram"))))
exit(0);

v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);


vs = textFileRead("F:\\&amp;#31243;&amp;#24207;\\vtkbin\\raycaster.vert");
fs = textFileRead("F:\\&amp;#31243;&amp;#24207;\\vtkbin\\raycaster.frag");

const char * vv = vs;
const char * ff = fs;

glShaderSource(v, 1, &amp;vv,NULL);
glShaderSource(f, 1, &amp;ff,NULL);


glCompileShader(v);
glCompileShader(f);

printShaderInfoLog(v);
printShaderInfoLog(f);

p = glCreateProgram();

glAttachShader(p,v);
glAttachShader(p,f);
glLinkProgram(p);
printProgramInfoLog(p);
glUseProgram(p);

glEnableClientState(GL_VERTEX_ARRAY);
GLuint iVertexBuffer = 0;
glGenBuffers(1, &amp;iVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, iVertexBuffer);
length=length*sizeof(float);
glBufferData(GL_ARRAY_BUFFER, length,VertexArray, GL_STATIC_DRAW);
delete [] VertexArray;

glBindBuffer(GL_ARRAY_BUFFER, iVertexBuffer);
glVertexPointer( 2, GL_FLOAT, 0, (char *) NULL );
length=imageInUseSize[1]*2+1;
glDrawArrays(GL_TRIANGLE_FAN,0,length);


glUseProgram(0);
GLint loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8,loc9,loc10 ,loc11,loc12,loc13,loc14,loc15;

loc1 = glGetUniformLocation(p,"centerscale");
glUniform1f(loc1,centerScale);

loc2=glGetUniformLocation(p,"offset");
glUniform2f(loc2,offsetX,offsetY);

loc3=glGetUniformLocation(p,"imageViewportSize");
glUniform2f(loc3,static_cast<float>(imageViewportSize[0]),
static_cast<float>(imageViewportSize[1]));

Relic
03-14-2008, 07:05 AM
Ok, your new code now.

int length=imageInUseSize[1]*4+2;
float *VertexArray=new float[length];
...
length = length * sizeof(VertexArray);
glBufferData(GL_ARRAY_BUFFER, length,VertexArray, GL_STATIC_DRAW);
...

That should crash mightily.

Assume imageInUseSize[1] == 1

int length = 1*4+2 = 6
float *VertexArray=new float[6]; // 6 * 4 = 24 bytes.
...
length = length * sizeof(VertexArray); // == 6 * 6 * sizeof(float) = 144.
glBufferDataglBufferData(GL_ARRAY_BUFFER, 144, VertexArray, GL_STATIC_DRAW);

Booom!

Instead of
length = length * sizeof(VertexArray);
use
length = sizeof(VertexArray);
or
length *= sizeof(VertexArray[0]); // a float
or
length *= sizeof(float);

destiny
03-14-2008, 07:18 AM
Thank you very much!I just didn't see that.
I have modified my codes according to your advice, still crash.
The codes above length*=sizeof(float)

destiny
03-14-2008, 07:32 AM
and sizeof(vertexarray)=4.because vertexarray is a pointer

Relic
03-14-2008, 07:52 AM
>>and sizeof(vertexarray)=4. because vertexarray is a pointer.<<

Ok, I was mislead on the array thing because of the new float[] allocation. Would still be fatal under 64-bit where the pointer size is 8 bytes.

destiny
03-14-2008, 06:46 PM
Thank you! I traced my program.
float *VertexArray=new float[ 1310]
glBufferData(GL_ARRAY_BUFFER, 5240,VertexArray, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLE_FAN,0,655)
Maybe it's not because the length of arrays.
I tried vertex at a time,still,when it came to glEnd ,invalid operation.I'm so confused. Maybe it's because of glcalllist above.

destiny
03-14-2008, 08:35 PM
I seemed to understand what's wrong,but I don't know how to solve the problem.I found my codes are in the display list, the display list is an invalid operation ,So whatever I draw would be wrong

destiny
03-16-2008, 12:57 AM
Thank you, Relic! Finally find my problem, before drawing something ,I should give the uniforms.