Querying fragment varying out variable names
Hello,
I'd like to propose an extension of the current API to allow querying of named fragment shader varying out variables of shader programs. As to my knowledge it is not possible yet to get the user defined names of the fragment shader outputs, this is how it could get used:
Code :
GLuint shaderProgram;
...
GLint fragmentVaryingOutCount;
glGetProgramiv( shaderProgram, GL_FRAGMENT_VARYING_OUT_ARB, &fragmentVaryingOutCount );
GLint longestFragmentVaryingOutName;
glGetProgramiv( shaderProgram, GL_FRAGMENT_VARYING_OUT_MAX_LENGTH_ARB, &longestFragmentVaryingOutName );
char *name = new char[longestFragmentVaryingOutName];
for (int i = 0; i < fragmentVaryingOutCount; ++i) {
GLenum type;
GLint size;
GLsizei length;
glGetFragmentVaryingOut( shaderProgram, i, longestFragmentVaryingOutName, &length, &size, &type, name );
GLint fragDataLocation = glGetFragDataLocation(shaderProgram, name);
printf("fragment shader has output named %s at location %d\n", name, fragDataLocation );
}
The functionality is oriented at the uniform/attribute query functions. I'm aware that _ARB might not be the correct extension and the acual numeric values for the new tokens are just placeholders.
Is this plausible? Who would I have to address to get a chance of this functionality becoming a part of OpenGL (NVidia/AMD/Intel driver development team?)?
Name
ARB_query_fragment_varying_out
Dependencies
OpenGL 3.0 is required.
Overview
This extension allows the GL to query a list of names and types of fragment shader varying out variables. APIs already exist to query vertex shader inputs (attributes) as well as uniform specifications, fragment varying out variables however can not be queried.
New Procedures and Functions
void GetFragmentVaryingOut(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
New Tokens
Tokens accepted by GetProgramiv:
FRAGMENT_VARYING_OUT_ARB 0xABCD
FRAGMENT_VARYING_OUT_MAX_LENGTH_ARB 0xABCE
New State
None.
Additions to Chapter 3 of the OpenGL 3.0 Specification (Fragment Shaders)
In section 3.12 - Shader Outputs:
Add to the end of the section: "To determine the set of fragment shader varying out variables used by a program and to determine their sizes and types, use the command:
void GetFragmentVaryingOut(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
This command provides information about the varying out variable selected by index. An index of 0 selects the first fragment varying out variable, and an index of FRAGMENT_VARYING_OUT_ARB-1 selects the last fragment varying out variable. The value of FRAGMENT_VARYING_OUT_ARB can be queried with GetProgramiv. If index is greater than or equal to FRAGMENT_VARYING_OUT_ARB, the error INVALID_VALUE is generated. Note that index simply indentifies a member in a list of fragment varying out variables, and has no relation to the assigned fragment data location.
The parameter program is a name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for program to have been linked successfully.
If an error occurred, the return parameters length, size, type and name will be unmodified.
For the selected fragment varying out variable, the user defined name is returned into name. The string name will be null terminated. The actual number of characters written into name, excluding the null terminator, is returned in length. If length is NULL, no length is returned. The maximum number of characters that may be written into name, including the null terminator, is specified by bufSize.
The length of the longest fragment varying out variable name in program is given by FRAGMENT_VARYING_OUT_MAX_LENGTH_ARB, which can be queried with GetProgramiv.
For the selected fragment varying out variable, the type is returned into type. The size of the fragment varying out variable is returned into size. The value in size is in units of the type returned in type. The type returned can be any of FLOAT, FLOAT_VEC2, FLOAT_VEC3, FLOAT_VEC4, INT, INT_VEC2, INT_VEC3, INT_VEC4.
Issues
(1) What name gets returned if the fragment varying out variable does not have a user defined name, but a build-in name?
There are two options: if the fragment varying out variable has no user defined name, the build-in name gets returned (e.g. 'gl_FragData[0]') or varying out variables without a user defined name will get ignored. In the later case FRAGMENT_VARYING_OUT_ARB will only return the number of user defined varying out variables.
Re: Querying fragment varying out variable names
Quote:
Is this plausible?
What do you mean by that? Is the general functionality plausible? Yes. Is your API? No. Any API the ARB would create would fit into the general rubric of attributes and uniforms. It would probably be called glGetActiveFragmentOut, to match glGetActiveAttrib and glGetActiveUniform. So your function is incorrectly named.
Quote:
Who would I have to address to get a chance of this functionality becoming a part of OpenGL
As a rule, you don't. We make suggestions, the ARB does what they want. That's generally how things work between OpenGL users and the ARB. They generally don't accept full extension specs from random people.
It's probably better to just say that you want the functionality; they'll put it in whatever API package you desire.
Now, if you have clout, if you work for a large company that deals with OpenGL (Blizzard, ID software, one of the CAD firms, etc), then the ARB will likely be willing to listen to you. But if you do work for them, then you probably already know the channels you need to go through to get their attention.
Re: Querying fragment varying out variable names
Hello Alfonse,
in general, I know that extensions are created by members of the ARB but I wanted to give a more specific idea of what I had in mind so I tried to give a specific example of what that API could look like.
I also don't care what the function will be called, as long as I can query the information I need.
The function should mimic the way GetActiveAttrib and GetActiveUniform work, but for the naming I was thinking that for attributes and uniforms the GLSL compiler can detect which are not used, only the (potentially) used ones are considered active and only those can get queried. For fragment outputs I'm not aware that some outputs can be ignored if they are not written to (iirc the spec sais that those rendertargets get undefined values). So I was unsure if 'active' would be a correct attribute to fragment outputs. Also I read 'varying out variable' as the name of the 'out's of a fragment shader in the 3.0 spec and to destinquish them from e.g. varyings between vertex and fragment shader I suggested 'fragment shader varying out variable' - the (probably) more informal name 'fragment out' would be nicer but I'm unsure how strict the naming scheme is.
Yes, we make suggestions and the ARB can do as they like, but my question was, is it enough to post a suggestion here or will never at NVidia, ATI, whoever, ever take notice unless I also post the idea (probably after refinement from this discussion) at a different location I'm not aware of now.
Thanks for your feedback so far.
Re: Querying fragment varying out variable names
Why would you need anything like that?
What is it useful for?
Re: Querying fragment varying out variable names
Hello aqnuep,
when doing application prototyping my framework can check that the number and types of attributes of the models matches the input attributes of the shader program. I can also query all uniforms of a uniformblock and address the offsets within the address with a string instead of an offset (uniformblock->setUniform("foo", 1.0f) ). I can not, however check that the FBO has the correct number of render targets to match the fragment shader. I can give each rendertarget a name and use glBindFragDataLocation to connect them correctly, but i can't detect the case that a user defined one output 'too much' (only missing outputs as glGetFragDataLocation would return -1).
You wouldn't need this API (and also not the existing variants for attributes or uniforms) if you have a final concept for your app, probably you predefine all bindings with explicit locations. But for quick prototyping this helps for better error checking and automatic (probably slower as the user connects everything per strings) location matching.
The desired informations must be already available within the GL implementation as they are the result of the GLSL compiler/parser so they only have to be made available similar to attributes and uniforms.
Re: Querying fragment varying out variable names
I'd see an immediate use in a framework kind of setting when playing with separate shader objects, i.e. the ability to query a program pipeline's individual bits of it's ins and outs, right now the rules for matching are as follows:
Quote:
Originally Posted by SSO spec
When multiple shader stages are active, the outputs of one stage form an
interface with the inputs of the next stage. At each such interface,
shader inputs are matched up against outputs from the previous stage:
* An output block is considered to match an input block in the
subsequent shader if the two blocks have the same block name, and the
members of the block match exactly in name, type, qualification, and
declaration order.
* An output variable is considered to match an input variable in the
subequent shader if:
* the two variables match in name, type, and qualification; or
* the two variables are declared with the same location layout
qualifier and match in type and qualification.
and add to that these rules:
Quote:
Originally Posted by SSO spec
At an interface between program objects, the set of inputs and outputs are
considered to match exactly if and only if:
* The built-in input and output blocks used on the interface
("gl_PerVertex" or "gl_PerFragment") match, as described below.
* Every declared input block or variable must have a matching output, as
described above.
* There are no output blocks or user-defined output variables
declared without a matching input block or variable declaration.
When the set of inputs and outputs on an interface between programs
matches exactly, all inputs are well-defined unless the corresponding
outputs were not written in the previous shader. However, any mismatch
between inputs and outputs results in all inputs being undefined except
for cases noted below. Even if an input has a corresponding output
that matches exactly, mismatches on other inputs or outputs may
adversely affect the executable code generated to read or write the
matching variable.
I can see where in a framework kind of bits where one may wish to do some querying of a pre-exisitng program pipeline before assembling/creating a shader to be used with that pre-existing program pipeline.
Re: Querying fragment varying out variable names
I agree with "menzel" and vote (if there can be any vote) for the ability to query fragment shader outputs.
Vertification of the data passing through pipeline stages is just a part of the possible application of this extension. I like the client-server model, in which such queries are required.
For example, a mesh is a server of vertex attributes. A material is one of the servers of shader parameters. A shader is their client, and when it's used, it matches the provided data with the one it needs, and makes the corresponding bindings (vertex attributes, textures, uniform buffers, etc). Following the same logic, there can be another server, an output surface storage, that provides several named texture layers or render buffers. A procedure of shader activation can query needed surfaces by name (and, potentially, type), and bind them to a target FBO in a specified order.
This client-server scheme is good because it is data-driven, and it's safe as the verification is done implicitely. I'm using it heavily, and getting the fragment output names is a missing part of this puzzle.