PDA

View Full Version : Querying fragment varying out variable names



menzel
02-23-2012, 09:04 AM
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:



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, &amp;length, &amp;size, &amp;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.

Alfonse Reinheart
02-23-2012, 10:06 AM
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 (http://www.opengl.org/wiki/GLAPI/glGetActiveAttrib) and glGetActiveUniform (http://www.opengl.org/wiki/GLAPI/glGetActiveUniform). So your function is incorrectly named.


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.

menzel
02-23-2012, 11:06 AM
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.

aqnuep
02-23-2012, 07:14 PM
Why would you need anything like that?
What is it useful for?

menzel
02-24-2012, 02:55 AM
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.

kRogue
02-25-2012, 07:54 AM
I'd see an immediate use in a framework kind of setting when playing with separate shader objects (http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt), 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:



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:



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.

DmitryM
04-02-2012, 07:50 AM
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.

Groovounet
04-28-2012, 02:50 PM
Is there really still people using OpenGL with a client and a server not being the same computer?

kyle_
04-29-2012, 06:27 AM
I don't think DmitryM means GL client/server, but more general concept instead. Yeah, client/server in GL is pretty silly currently. They could probably drop it by now from the spec.

I myself would be for dumber GL then that - such logic belongs in upper level layers imo.

aqnuep
04-29-2012, 10:36 AM
You can't really drop the GL client/server model as it is needed for remote rendering which, even though it's surprising, is still used.

mbentrup
04-30-2012, 01:36 AM
You can't really drop the GL client/server model as it is needed for remote rendering which, even though it's surprising, is still used.

This is getting a bit off-topic, but the ARB stopped extending the GLX protocol somewhere before OpenGL 3.0., so you're restricted to pretty ancient functionality if you use remote rendering.

l_belev
05-01-2012, 05:05 PM
menzel, what do you mean by "fragment varying out variable"? 'Varying' was used for the interpolators that link vertex/geometry with fragment shaders, but now the term is dropped altogether.
If you mean just the fragment shader outputs, then i'm for it. If vertex attribs and uniforms can be queried then fragment outputs should too, at least for consistency.
There are APIs (BindFragDataLocation, GetFragDataLocation) that accept those names as arguments but there is no way to find what the names are (except by parsing the shader text by hand).
I think this inconsistency should be addressed.

menzel
05-02-2012, 02:41 AM
I_belev : Yes, I mean the fragment shader outputs.

l_belev
05-02-2012, 03:11 AM
As for it's usefulness, it sure is useful. For example you can think of some wrapper library that stays between the application and the OpenGL. That wrapper does not know the names of the fragment output variables in the shaders that the application gives (its a separate piece of software) but it still may want to do something with them (depending on what is the purpose of the wrapper).

DmitryM
11-11-2012, 10:42 AM
I'm disappointed that my words were misinterpreted and ignored. Here is the whole article explaining why I need that:
http://claymore-dev.blogspot.com/2012/11/draw-call-verification.html

ScottManDeath
11-12-2012, 09:59 PM
Have you looked into this GL 4.3 feature, especially issue (2)?

http://www.opengl.org/registry/specs/ARB/program_interface_query.txt

Alfonse Reinheart
11-13-2012, 07:49 AM
I'm disappointed that my words were misinterpreted and ignored.

Welcome to three months ago; glad you could make it. I even made a convenient OpenGL Wiki article on the topic (http://www.opengl.org/wiki/Program_Introspection#Interface_query).

DmitryM
11-13-2012, 12:56 PM
Thanks ScottManDepth and Alfonse!

My knowledge of cutting-edge GL is not up to date, and looking for fragment output queries got me only to this thread.

That's nice to finally have this functionality in GL4.3! I'm still a bit sad that it's not possible to query fragment outputs on my R700.

Alfonse Reinheart
11-13-2012, 01:22 PM
Blame AMD's slow implosion for that, not OpenGL.