PDA

View Full Version : OpenGL 4.1 : did i misunderstood separate programs ?



012inf3
10-25-2012, 04:08 PM
Hello everyone,

I am trying to use a ProgramPipelineObject and I have not been able to make it work the way I want.
Maybe I am trying something that is not possible.
I have a "basic" example which works, and a "little bit more complexe" example which does not.

This is the example which works :
ProgramObject 1 :

load vertex shader, compile, set separable true, link

ProgramObject 2 :

load fragment shader, compile, set separable true, link

ProgramPipeline :

generate, bind ProgramPipeline
useStage(ProgramPipeline, Vertex, ProgramObject 1)
useStage(ProgramPipeline, Fragment, ProgramObject 2)
unbind ProgramPipeline

Render pass :

programuniform(ProgramObject 1, "matrix etc...")
programuniform(ProgramObject 2, "color etc...")
bind ProgramPipeline
draw object
unbind ProgramPipeline




This is the example which doest not work (the only modification is bold) :
ProgramObject 1 :

load vertex shader, load fragment shader, compile both, set separable true, link (so this is not a simple program with a vertex shader, but a program with a vertex and a fragment shader)

ProgramObject 2 :

load fragment shader, compile, set separable true, link

ProgramPipeline :

generate, bind ProgramPipeline
useStage(ProgramPipeline, Vertex, ProgramObject 1)
useStage(ProgramPipeline, Fragment, ProgramObject 2)
unbind ProgramPipeline

Render pass :

programuniform(ProgramObject 1, "matrix etc...")
programuniform(ProgramObject 2, "color etc...")
bind ProgramPipeline
draw object
unbind ProgramPipeline


My result is : no object on screen : maybe a uniform problem ?

->Is it possible to create a pipeline taking only one stage of a shaderprogram that contains many stages?
->Do you see any reason that can make it fail ?

Thanks you very much.

PS : I am under linux ubuntu 12.04, nvidia 304 drivers, gtx 480, glew 1.9

Alfonse Reinheart
10-25-2012, 04:41 PM
Is it possible to create a pipeline taking only one stage of a shaderprogram that contains many stages?

According to the specification, yes.


Do you see any reason that can make it fail ?

Yes.

The whole point of separable programs is to not have programs linked together. At all. Indeed, they created a whole new entrypoint dedicated to creating single-stage programs. (http://www.opengl.org/wiki/GLAPI/glCreateShaderProgram)

NVIDIA's drivers certainly should allow this by the specification, so it's probably a driver bug (assuming your code isn't wrong in some other way), so feel free to file a report on it. But it's not exactly a surprise that this doesn't work.

In short, I wouldn't rely on being able to replace one program's stage with another program's stage. It could and should work, but it's a corner case that most users of this functionality (people who want D3D-like shaders) would never touch. So it doesn't get as extensive testing in the field as the other cases.

012inf3
10-26-2012, 07:48 AM
Thanks you for that quick answer.


In short, I wouldn't rely on being able to replace one program's stage with another program's stage. It could and should work, but it's a corner case that most users of this functionality (people who want D3D-like shaders) would never touch. So it doesn't get as extensive testing in the field as the other cases.
I could have been so amazing ...


To make sure this is not a wrong code and a real driver problem, this is what I tested :
On the OpenGL Samples Pack 4.3.0.2 (http://www.g-truc.net/post-0503.html#menu) I changed initSeparateProgram() of gl-410-program-separate.cpp.

This is the diff :

< std::string VertexSourceContent = glf::loadFile(VERTEX_SHADER_SOURCE);
< char const * VertexSourcePointer = VertexSourceContent.c_str();
< SeparateProgramName[program::VERTEX] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &VertexSourcePointer);
---
> // create a shaderprogram containing 2 shader stages
> GLuint VertShaderName = glf::createShader(GL_VERTEX_SHADER, VERTEX_SHADER_SOURCE);
> GLuint FragShaderName = glf::createShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE);
>
> SeparateProgramName[program::VERTEX] = glCreateProgram();
> glAttachShader(SeparateProgramName[program::VERTEX], VertShaderName);
> glAttachShader(SeparateProgramName[program::VERTEX], FragShaderName); // If you comment this line, it works. If you do not (and the program has 2 shaders) it does not.
> glProgramParameteri(SeparateProgramName[program::VERTEX], GL_PROGRAM_SEPARABLE, GL_TRUE);
> glLinkProgram(SeparateProgramName[program::VERTEX]);

Consequently the following line should have taken only one stage :
glUseProgramStages(PipelineName, GL_VERTEX_SHADER_BIT, SeparateProgramName[program::VERTEX]);
// Check program id
int program_id = 0;
glGetProgramPipelineiv(PipelineName, GL_VERTEX_SHADER, &program_id);
std::cout << "Used (vertex) program id : " << program_id << std::endl; // display the correct program id
glGetProgramPipelineiv(PipelineName, GL_FRAGMENT_SHADER, &program_id);
std::cout << "Used (fragment) program id : " << program_id << std::endl; // display 0 which is what we want

So, the use stage "seems" to work, but the display does not work anymore :
glBindProgramPipeline(PipelineName);
glDrawElementsInstancedBaseVertex(GL_TRIANGLES, ElementCount, GL_UNSIGNED_INT, NULL, 1, 0); // crash here
glBindProgramPipeline(0);

OpenGL: error(high) 1282: GL_INVALID_OPERATION error generated. State(s) are invalid: program pipeline config.


If somebody can confirm me that I did not do wrong code, I will report the bug.
Thanks.

012inf3
10-26-2012, 07:49 AM
Thanks you for that quick answer.


In short, I wouldn't rely on being able to replace one program's stage with another program's stage. It could and should work, but it's a corner case that most users of this functionality (people who want D3D-like shaders) would never touch. So it doesn't get as extensive testing in the field as the other cases.
I could have been so amazing ...


To make sure this is not a wrong code and a real driver problem, this is what I tested :
On the OpenGL Samples Pack 4.3.0.2 (http://www.g-truc.net/post-0503.html#menu) I changed initSeparateProgram() of gl-410-program-separate.cpp.

This is the diff :

< std::string VertexSourceContent = glf::loadFile(VERTEX_SHADER_SOURCE);
< char const * VertexSourcePointer = VertexSourceContent.c_str();
< SeparateProgramName[program::VERTEX] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &VertexSourcePointer);
---
> // create a shaderprogram containing 2 shader stages
> GLuint VertShaderName = glf::createShader(GL_VERTEX_SHADER, VERTEX_SHADER_SOURCE);
> GLuint FragShaderName = glf::createShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE);
>
> SeparateProgramName[program::VERTEX] = glCreateProgram();
> glAttachShader(SeparateProgramName[program::VERTEX], VertShaderName);
> glAttachShader(SeparateProgramName[program::VERTEX], FragShaderName); // If you comment this line, it works. If you do not (and the program has 2 shaders) it does not.
> glProgramParameteri(SeparateProgramName[program::VERTEX], GL_PROGRAM_SEPARABLE, GL_TRUE);
> glLinkProgram(SeparateProgramName[program::VERTEX]);

Consequently the following line should have taken only one stage :
glUseProgramStages(PipelineName, GL_VERTEX_SHADER_BIT, SeparateProgramName[program::VERTEX]);
// Check program id
int program_id = 0;
glGetProgramPipelineiv(PipelineName, GL_VERTEX_SHADER, &program_id);
std::cout << "Used (vertex) program id : " << program_id << std::endl; // display the correct program id
glGetProgramPipelineiv(PipelineName, GL_FRAGMENT_SHADER, &program_id);
std::cout << "Used (fragment) program id : " << program_id << std::endl; // display 0 which is what we want

So, the use stage "seems" to work, but the display does not work anymore :
glBindProgramPipeline(PipelineName);
glDrawElementsInstancedBaseVertex(GL_TRIANGLES, ElementCount, GL_UNSIGNED_INT, NULL, 1, 0); // crash here
glBindProgramPipeline(0);

OpenGL: error(high) 1282: GL_INVALID_OPERATION error generated. State(s) are invalid: program pipeline config.


If somebody can confirm me that I did not do wrong code, I will report the bug.
Thanks.