| Name |
| |
| NV_geometry_shader_passthrough |
| |
| Name Strings |
| |
| GL_NV_geometry_shader_passthrough |
| |
| Contact |
| |
| Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com) |
| |
| Contributors |
| |
| Jeff Bolz, NVIDIA Corporation |
| Piers Daniell, NVIDIA Corporation |
| Christoph Kubisch, NVIDIA Corporation |
| Mathias Heyer, NVIDIA Corporation |
| Mark Kilgard, NVIDIA Corporation |
| |
| Status |
| |
| Shipping |
| |
| Version |
| |
| Last Modified Date: February 15, 2017 |
| NVIDIA Revision: 4 |
| |
| Number |
| |
| OpenGL Extension #470 |
| OpenGL ES Extension #233 |
| |
| Dependencies |
| |
| This extension is written against the OpenGL 4.3 Specification |
| (Compatibility Profile), dated February 14, 2013 |
| |
| This extension is written against the OpenGL Shading Language |
| Specification, version 4.30, revision 8. |
| |
| OpenGL ES 3.1 and EXT_geometry_shader are required for an |
| implementation in OpenGL ES. |
| |
| This extension interacts with OpenGL 4.4 and ARB_enhanced_layouts. |
| |
| This extension interacts with NV_gpu_program4 and NV_gpu_program5. |
| |
| This extension interacts with NV_geometry_shader4 and NV_gpu_shader4. |
| |
| This extension interacts with NV_geometry_program4 and NV_gpu_program4. |
| |
| This extension interacts with NV_transform_feedback. |
| |
| This extension interacts with a combination of NV_gpu_program4, |
| NV_gpu_program5, NV_transform_feedback, EXT_transform_feedback, and OpenGL |
| 3.0. |
| |
| This extension interacts with NVX_shader_thread_group. |
| |
| Overview |
| |
| Geometry shaders provide the ability for applications to process each |
| primitive sent through the GL using a programmable shader. While geometry |
| shaders can be used to perform a number of different operations, including |
| subdividing primitives and changing primitive type, one common use case |
| treats geometry shaders as largely "passthrough". In this use case, the |
| bulk of the geometry shader code simply copies inputs from each vertex of |
| the input primitive to corresponding outputs in the vertices of the output |
| primitive. Such shaders might also compute values for additional built-in |
| or user-defined per-primitive attributes (e.g., gl_Layer) to be assigned |
| to all the vertices of the output primitive. |
| |
| This extension provides a shading language abstraction to express such |
| shaders without requiring explicit logic to manually copy attributes from |
| input vertices to output vertices. For example, consider the following |
| simple geometry shader in unextended OpenGL: |
| |
| layout(triangles) in; |
| layout(triangle_strip) out; |
| layout(max_vertices=3) out; |
| |
| in Inputs { |
| vec2 texcoord; |
| vec4 baseColor; |
| } v_in[]; |
| out Outputs { |
| vec2 texcoord; |
| vec4 baseColor; |
| }; |
| |
| void main() |
| { |
| int layer = compute_layer(); |
| for (int i = 0; i < 3; i++) { |
| gl_Position = gl_in[i].gl_Position; |
| texcoord = v_in[i].texcoord; |
| baseColor = v_in[i].baseColor; |
| gl_Layer = layer; |
| EmitVertex(); |
| } |
| } |
| |
| In this shader, the inputs "gl_Position", "Inputs.texcoord", and |
| "Inputs.baseColor" are simply copied from the input vertex to the |
| corresponding output vertex. The only "interesting" work done by the |
| geometry shader is computing and emitting a gl_Layer value for the |
| primitive. |
| |
| The following geometry shader, using this extension, is equivalent: |
| |
| #extension GL_NV_geometry_shader_passthrough : require |
| |
| layout(triangles) in; |
| // No output primitive layout qualifiers required. |
| |
| // Redeclare gl_PerVertex to pass through "gl_Position". |
| layout(passthrough) in gl_PerVertex { |
| vec4 gl_Position; |
| } gl_in[]; |
| |
| // Declare "Inputs" with "passthrough" to automatically copy members. |
| layout(passthrough) in Inputs { |
| vec2 texcoord; |
| vec4 baseColor; |
| } v_in[]; |
| |
| // No output block declaration required. |
| |
| void main() |
| { |
| // The shader simply computes and writes gl_Layer. We don't |
| // loop over three vertices or call EmitVertex(). |
| gl_Layer = compute_layer(); |
| } |
| |
| New Procedures and Functions |
| |
| None. |
| |
| New Tokens |
| |
| None. |
| |
| Modifications to the OpenGL 4.3 Specification (Compatibility Profile) |
| |
| Modify Section 11.3.4.5, Geometry Shader Outputs, p. 425 |
| |
| (add to the end of the section, p. 426): |
| |
| For the purposes of component counting, passthrough geometry shaders count |
| all active input variable components declared with the layout qualifier |
| "passthrough" as output components as well, since their values will be |
| copied to the output primitive produced by the geometry shader. |
| |
| |
| Modifications to the OpenGL Shading Language Specification, Version 4.30 |
| |
| Including the following line in a shader can be used to control the |
| language features described in this extension: |
| |
| #extension GL_NV_geometry_shader_passthrough : <behavior> |
| |
| where <behavior> is as specified in section 3.3. |
| |
| New preprocessor #defines are added to the OpenGL Shading Language: |
| |
| #define GL_NV_geometry_shader_passthrough 1 |
| |
| Modify Section 4.4.1.2, Geometry Shader Inputs (p. 57) |
| |
| (add to the list of allowed layout qualifiers, p. 57) |
| |
| layout-qualifier-id |
| ... |
| passthrough |
| |
| (insert after discussion of the "invocations" layout qualifier, p. 57) |
| |
| A geometry shader using the layout qualifier "passthrough" is considered a |
| "passthrough geometry shader". Output primitives in a passthrough |
| geometry shader always have the same topology as the input primitive and |
| are not produced by emitting vertices. The vertices of the output |
| primitive have two different types of attributes. Geometry shader inputs |
| qualified with "passthrough" are considered to produce per-vertex outputs, |
| where values for each output vertex are copied from the corresponding |
| input vertex. Any built-in or user-defined geometry shader outputs are |
| considered per-primitive in a passthrough geometry shader, where a single |
| output value is copied to all output vertices. |
| |
| The identifier "passthrough" can not be used to qualify "in", but can be |
| used to qualify input variables, blocks, or block members. It specifies |
| that values of those inputs will be copied to the corresponding vertex of |
| the output primitive. Input variables and block members not qualified |
| with "passthrough" will be consumed by the geometry shader without being |
| passed through to subsequent stages. For the purposes of matching |
| passthrough geometry shader inputs with outputs of the previous pipeline |
| stages, the "passthrough" qualifier itself is ignored. For separable |
| program objects (where geometry shader inputs and outputs may interface |
| with inputs and outputs in other program objects), all inputs qualified |
| with "passthrough" must also be assigned a location using the "location" |
| layout qualifier. It is a link-time error to specify a passthrough |
| geometry shader input in a separable program without an explicitly |
| assigned location. |
| |
| For the purposes of matching the outputs of the geometry shader with |
| subsequent pipeline stages, each input qualified with "passthrough" is |
| considered to add an equivalent output with the same name, type, and |
| qualification (except using "out" instead of "in") on the output |
| interface. The output declaration corresponding to an input variable |
| qualified with "passthrough" will be identical to the input declaration, |
| except that it will not be treated as arrayed. The output block |
| declaration corresponding to an input block qualified with "passthrough" |
| or having members qualified with "passthrough" will be identical to the |
| input declaration, except that it will not be treated as arrayed and will |
| not have an instance name. If an input block is qualified with |
| "passthrough", the equivalent output block contains all the members of the |
| input block. Otherwise, the equivalent output block contains only those |
| input block members qualified with "passthrough". If such an input block |
| is qualified with "location" or has members qualified with "location", all |
| members of the corresponding output block members are assigned locations |
| identical to those assigned to corresponding input block members. All |
| such outputs are associated with output vertex stream zero (section |
| 4.4.2.2). Output variables and blocks generated from inputs qualified |
| with "passthrough" will only be added to the name space of the output |
| interface; these declarations will not be available to geometry shader |
| code. A program will fail to link if it contains a geometry shader output |
| block with the same name as a geometry shader input block that is |
| qualified with "passthrough" or contains a member qualified with |
| "passthrough". |
| |
| A compile-time error is generated if the non-arrayed input variables |
| "gl_PrimitiveIDIn" or "gl_InvocationID" are redeclared with the |
| "passthrough" layout qualifier. |
| |
| A compile- or link-time error will be generated if a program contains a |
| passthrough geometry shader and: |
| |
| * declares a geometry shader input primitive type using layout |
| qualifiers other than "points", "lines", or "triangles"; |
| |
| * declares a geometry shader output primitive type using the output |
| layout qualifiers "points", "line_strip", or "triangle_strip" (section |
| 4.4.2.2); |
| |
| * declares a geometry shader output primitive vertex count using the |
| output layout qualifier "max_vertices"; |
| |
| * declares a geometry shader invocation count other than one using the |
| input layout qualifier "invocations"; |
| |
| * declares a geometry shader output variable or block qualified with |
| "stream" with an associated output vertex stream other than zero; |
| |
| * includes geometry shader code calling the built-in functions |
| EmitVertex(), EmitStreamVertex(), EndPrimitive(), or |
| EndStreamPrimitive(); or |
| |
| * is configured to use transform feedback, using either the geometry |
| shader output layout qualifiers "xfb_offset", "xfb_stride", and |
| "xfb_buffer", or using the OpenGL API command |
| TransformFeedbackVaryings(). |
| |
| For the purposes of OpenGL API queries, passthrough geometry shaders are |
| considered to include an output layout qualifier (section 4.4.2.2) |
| specifying an output primitive type and maximum vertex count consistent |
| with an equivalent non-passthrough geometry shader, as per the following |
| table. |
| |
| Input Layout Output Layout |
| ---------------- ------------------------------------------ |
| points layout(points, max_vertices=1) out; |
| lines layout(line_strip, max_vertices=2) out; |
| triangles layout(triangle_strip, max_vertices=3) out; |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| None. |
| |
| Errors |
| |
| None. |
| |
| New State |
| |
| None. |
| |
| New Implementation Dependent State |
| |
| None. |
| |
| |
| Interactions with OpenGL ES 3.1 |
| |
| Unless made available by functionality similar to ARB_transform_feedback3 |
| and ARB_gpu_shader5, remove references to EmitStreamVertex() and |
| EndStreamPrimitive(), the "stream = N" layout qualifier as well as |
| the notion of multiple transform feedback streams. |
| |
| Dependencies on OpenGL 4.4 and ARB_enhanced_layouts |
| |
| If neither OpenGL 4.4 nor ARB_enhanced_layouts is supported, remove |
| references to the use of the "xfb_offset", "xfb_buffer", and "xfb_stride" |
| layout qualifiers for transform feedback. |
| |
| Dependencies on NV_gpu_program4 and NV_geometry_program4 |
| |
| Modify Section 2.X.2, Program Grammar, of the NV_geometry_program4 |
| specification (which modifies the NV_gpu_program4 base grammar) |
| |
| <declaration> ::= "PASSTHROUGH" <resultUseD> <optWriteMask> |
| |
| Modify Section 2.X.6, Program Options |
| |
| + Passthrough Geometry Program (NV_geometry_program_passthrough) |
| |
| If a geometry program specifies the "NV_geometry_program_passthrough" |
| option, the program will be configured as a passthrough geometry program. |
| A passthrough geometry program is configured to emit a new output |
| primitive with the same type and vertex count as its input primitive. For |
| any result variable components written by a passthrough geometry program |
| instruction, the values are broadcast to all vertices of the output |
| primitive. For any result binding components specified in PASSTHROUGH |
| statements, the component values for each input primitive vertex are |
| copied ("passed through") to their corresponding output primitive vertex |
| without requiring geometry program code to copy attribute values and emit |
| output primitive vertices. A passthrough geometry program will fail to |
| load if it contains an INVOCATIONS, PRIMITIVE_OUT, or VERTICES_OUT |
| declaration, or an EMIT, EMITS, or ENDPRIM instruction. A passthrough |
| geometry program must declare an input primitive type of POINTS, LINES, or |
| TRIANGLES, and the resulting output primitive produced will be a single |
| point, line, or triangle, respectively. The PASSTHROUGH declaration can |
| be used only in programs using this option. |
| |
| |
| Section 2.X.7.Y, Geometry Program Declarations |
| |
| (modify the first paragraph of the section) |
| |
| Geometry programs support three types of declaration statements specifying |
| input and output primitive types, as described below. .... |
| |
| (add to the end of the section) |
| |
| Additionally, if the "NV_geometry_program_passthrough" option is |
| specified, a geometry program can include zero or more instances of the |
| following declaration statement: |
| |
| - Passthrough Geometry Shader Attribute (PASSTHROUGH) |
| |
| Each PASSTHROUGH declaration statement identifies a set of result binding |
| components whose values for each vertex of the output primitive will be |
| produced by copying the corresponding attribute binding components from |
| the corresponding vertex of the input primitive. The set of result |
| bindings for which this copy is performed is identified by the |
| <resultUseD> grammar rule. For each such binding, the set of components |
| to be copied is identified by the <optWriteMask> grammar rule. If the |
| write mask is omitted, all components of each binding are copied. A |
| program will fail to load if the binding identified by the <resultUseD> |
| grammar rule does not have a corresponding attribute binding; |
| "result.primid", "result.layer", and "result.viewport" may not be used. |
| It is legal to specify an attribute binding more than once in a |
| PASSTHROUGH declaration; a component will be passed through if and only if |
| it is identified in one or more PASSTHROUGH declarations. A program will |
| fail to load if any result binding is both declared in a PASSTHROUGH |
| statement and written by a program instruction, even if the set of |
| components referenced is mutually exclusive. |
| |
| Modify Section 13.2.2 of the OpenGL 4.3 Specification, p. 457 |
| |
| (insert before the errors section, p. 458) |
| |
| Transform feedback can not be used with passthrough geometry programs. |
| When transform back is active and not paused, an INVALID_OPERATION error |
| is generated by any command that transfers vertices to the GL if the |
| current geometry program was declared using the |
| "NV_geometry_shader_passthrough" program option. |
| |
| |
| Dependencies on NV_geometry_shader4 and NV_gpu_shader4 |
| |
| If NV_geometry_shader4 is supported, it is possible to change the maximum |
| geometry shader output vertex count after linking a program. The |
| following language should be added to the end of the description of the |
| the GEOMETRY_VERTICES_OUT_EXT <pname> for the ProgramParameteriEXT API in |
| the NV_geometry_shader4 specification: |
| |
| The error INVALID_OPERATION is generated by ProgramParameteriEXT if |
| <program> identifies a program object that has been linked successfully |
| and includes a passthrough geometry shader (one using the "passthrough" |
| layout qualifier). |
| |
| Note that NV_geometry_shader4 doesn't have its own extension string entry; |
| it is considered present if and only if NV_gpu_shader4 is advertised. |
| |
| Dependencies on NV_geometry_program4 and NV_gpu_program4 |
| |
| If NV_geometry_program4 is supported, it is possible to change the maximum |
| output vertex count after compiling an assembly geometry program. The |
| following language should be added to the end of the description of the |
| ProgramVertexLimitNV API: |
| |
| The error INVALID_OPERATION is generated by ProgramVertexLimitNV if the |
| current geometry program uses the NV_geometry_program_passthrough |
| program option. |
| |
| Note that NV_geometry_program4 doesn't have its own extension string |
| entry; it is considered present if and only if NV_gpu_program4 is |
| advertised. |
| |
| Dependencies on NV_transform_feedback |
| |
| If NV_transform_feedback is supported, the following language should be |
| added to the end of the description of the TransformFeedbackVaryingsNV |
| API: |
| |
| The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV |
| if <program> identifies a program containing a passthrough geometry |
| shader (i.e., one using the "passthrough" layout qualifier). |
| |
| Dependencies on NV_gpu_program4, NV_gpu_program5, NV_transform_feedback, |
| EXT_transform_feedback, and OpenGL 3.0: |
| |
| If NV_gpu_program4 and/or NV_gpu_program5 is supported together with any |
| of NV_transform_feedback, EXT_transform_feedback, or OpenGL 3.0 is |
| supported, the following language should be added to the descriptions of |
| BeginTransformFeedbackNV(), BeginTransformFeedbackEXT(), and |
| BeginTransformFeedback() as applicable: |
| |
| Transform feedback is not supported with passthrough geometry programs. |
| The error INVALID_OPERATION error is generated if there is an active |
| geometry program that uses the NV_geometry_program_passthrough program |
| option. |
| |
| Note that this issue doesn't apply to GLSL program objects, since we are |
| making it impossible to successfully specify a program that uses transform |
| feedback and a passthrough geometry shader concurrently. |
| |
| Dependencies on NVX_shader_thread_group |
| |
| If NVX_shader_thread_group is supported, the new built-in inputs provided |
| by that extension should not be allowed as passthrough: |
| |
| A compile-time error is generated if any of the non-arrayed input |
| variables "gl_PrimitiveIDIn", "gl_InvocationID", "gl_ThreadInWarpNVX", |
| "gl_ThreadEqMaskNVX", "gl_ThreadGeMaskNVX", "gl_ThreadGtMaskNVX", |
| "gl_ThreadLeMaskNVX", "gl_ThreadLtMaskNVX", "gl_WarpIDNVX", or |
| "gl_SMIDNVX" are redeclared with the "passthrough" layout qualifier. |
| |
| |
| Issues |
| |
| (1) What should this extension be called? |
| |
| RESOLVED: NV_geometry_shader_passthrough. The new layout qualifier |
| specifies new semantics where primitives are largely "passed through" by |
| the geometry shader, copying vertices of the input primitive to the |
| output primitive. The only operation performed by geometry shaders |
| using this extension is to compute a collection of per-primitive |
| attributes assigned to all vertices of the geometry shader. |
| |
| (2) This extension is aimed at geometry shaders that show a specific |
| pattern. Why provide an explicit programming model in this extension, |
| as opposed to automatically optimizing regular geometry shaders? |
| |
| RESOLVED: The hardware for which this extension was written provides |
| explicit support for passing attributes of geometry shader input |
| vertices through the geometry stage without an explicit copy. While |
| implementations supporting this extension may optimize geometry shaders |
| to use this hardware, we provide an explicit programming model because |
| (a) application developers may prefer to use this model for programming |
| such shaders and (b) automatic optimization may fail to detect a |
| "passthrough" pattern in some geometry shaders. |
| |
| (3) How do passthrough geometry shaders interact with GLSL built-in |
| variables? |
| |
| RESOLVED: Geometry shaders can redeclare the built-in input block |
| "gl_PerVertex" with the "passthrough" layout qualifier to specify that |
| built-in inputs like "gl_Position" should be passed through. We allow |
| the shader to qualify the entire redeclared block with "passthrough" to |
| pass through all block members. We also allow the shader to qualify |
| individual block members with "passthrough" to pass through some, but |
| not all, block members. |
| |
| (4) How do passthrough geometry shaders interact with geometry shader |
| instancing (using the "invocations=N" layout qualifier)? |
| |
| RESOLVED: We disallow the use of instancing in passthrough geometry |
| shaders; it will result in a link error. |
| |
| We considered specifying the features as orthogonal (with the |
| passthrough geometry shader run N times), but consider the feature to be |
| of limited utility. Making N separate copies of the input primitive |
| type isn't consistent with a model that largely passes through one |
| single primitive. |
| |
| (5) How do passthrough geometry shaders interact with transform feedback? |
| |
| RESOLVED: We disallow the use of transform feedback with programs with |
| a passthrough geometry shader; it will result in a link error. |
| |
| We considered specifying the features as orthogonal, but consider the |
| feature to be of limited utility. In particular, since inputs that are |
| passed through the geometry shader don't have explicit output |
| declarations, there is no way to control transform feedback using the |
| "xfb_offset", "xfb_buffer", and "xfb_stride" layout qualifiers. While |
| it would still be possible to use the OpenGL API command |
| TransformFeedbackVaryings() to specify passed through inputs to capture, |
| we decided it wasn't worth the trouble. |
| |
| For GLSL programs in unextended OpenGL 4.3, we can specify a link-time |
| error to enforce this limitation. For applications using GLSL programs |
| and the NV_transform_feedback extension (where transform feedback |
| varyings can be specified post-link), we throw an error when attempting |
| to update transform feedback. We will also prohibit the use of assembly |
| programs with transform feedback for consistency, but need to specify a |
| Draw-time error for that since transform feedback is completely |
| decoupled from assembly program objects. |
| |
| (6) How do passthrough geometry shaders interact with multi-stream |
| geometry shader support (using the "stream=N" layout qualifier)? |
| |
| RESOLVED: All of the output vertices of a passthrough geometry shader |
| are associated with output vertex stream zero. Additionally, it is an |
| error to declare a GLSL output variable with a stream other than zero. |
| |
| (7) Do passthrough geometry shaders need to use layout qualifiers |
| describing the output primitive type? |
| |
| RESOLVED: No. We will not allow the use of these layout qualifiers |
| with passthrough geometry shaders. The output primitive type and vertex |
| count will be taken directly from the input primitive type for such |
| shaders. |
| |
| (8) Inputs qualified with "passthrough" are copied to the vertices of the |
| output primitive. Do they show up on the PROGRAM_OUTPUT interface for |
| program resource queries (e.g., GetProgramResourceiv)? |
| |
| RESOLVED: Yes, passed through variables, blocks, and block members |
| appear on the output interface. |
| |
| (9) How should geometry shaders indicate that they want to be |
| "passthrough"? Should we have some sort of declaration at global |
| scope (e.g., "layout(passthrough) in") or infer it from the presence |
| of one or more layout qualifiers on variables, blocks, or block |
| members? |
| |
| RESOLVED: We consider a geometry shader to be passthrough if one or |
| more input variables, blocks, or block members are qualified by |
| "passthrough". We won't require or allow the "passthrough" layout |
| qualifier to be used on "in". |
| |
| We considered requiring separate declarations for a global "passthrough" |
| mode and passing through individual variables like this: |
| |
| layout(passthrough) in; // makes the shader passthrough |
| |
| layout(passthrough) in Block { // pass through the contents of <Block> |
| ... |
| } v_in[]; |
| |
| We decided not to do this in part because the inheritance semantics for |
| other layout qualifiers might cause the casual programmer to expect that |
| the applying the qualifier "passthrough" to in might cause all |
| subsequent inputs to inherit "passthrough" behavior. |
| |
| layout(passthrough) in; |
| in Block { |
| ... |
| } v_in[]; |
| |
| We could have resolved this by using a second identifier (e.g., |
| "passthrough_shader") in the layout qualifier, but there don't seem to |
| be any interesting cases where a passthrough geometry shader has no |
| per-vertex outputs. In particular, we expect pass-through geometry |
| shaders to always pass through "gl_Position". |
| |
| (10) Should we provide any query in the OpenGL API to determine whether a |
| geometry shader is a "passthrough" shader? |
| |
| RESOLVED: We are not going to bother to do so in this extension; there |
| are numerous other optional shader features lacking such query support. |
| |
| (11) Should passthrough geometry shaders be allowed to write per-primitive |
| values for arbitrary shader outputs or just the inherently |
| per-primitive built-in outputs (e.g., gl_Layer, gl_ViewportIndex)? |
| |
| RESOLVED: We should allow passthrough geometry shaders to write to both |
| built-in and user-defined outputs. Any output variables declared in |
| passthrough geometry shader without the "passthrough" layout qualifier |
| are treated as per-primitive outputs and will be broadcast to all |
| vertices in the output primitive. For example, this shader |
| |
| layout(passthrough) in; |
| layout(passthrough) in gl_PerVertex { |
| vec4 gl_Position; |
| } gl_in[]; |
| out vec4 batman; |
| |
| void main() |
| { |
| batman = compute_batman(); |
| } |
| |
| will attach the value produced by compute_batman() to all the vertices |
| of the output primitive. The value of gl_Position for each vertex of |
| the output primitive will be copied directly from the value of |
| gl_Position for the corresponding input vertex. |
| |
| (12) How do per-primitive outputs from passthrough geometry shaders |
| interact with fragment shader inputs? |
| |
| RESOLVED: Per-primitive outputs will be broadcast to all the vertices |
| of the output primitive, so reading the corresponding fragment shader |
| input should yield the per-primitive output value. |
| |
| We strongly recommend using the "flat" qualifier on all fragment shader |
| inputs corresponding to per-primitive passthrough geometry shader |
| outputs. Using "flat" on such inputs may result in better performance |
| when using passthrough geometry shaders. |
| |
| We also recommend using the "flat" qualifier on such inputs to avoid |
| possible arithmetic error that can result from evaluating |
| perspective-correct interpolation equations. For example, |
| perspective-correct attribute interpolation for triangles uses the |
| equation: |
| |
| f = (a*f_a/w_a + b*f_b/w_b + c*f_c/w_c) / (a/w_a + b/w_b + c/w_c) |
| |
| where a, b, and c are interpolation weights (adding to 1), f_a, f_b, and |
| f_c are per-vertex attribute values, and w_a, w_b, and w_c are |
| per-vertex clip w coordinates. For per-primitive outputs, f_a == f_b == |
| f_c, which equals the per-primitive attribute value f_p, so the equation |
| simplifies to: |
| |
| f = (a*f_p/w_a + b*f_p/w_b + c*f_p/w_c) / (a/w_a + b/w_b + c/w_c) |
| = f_p * (a/w_a + b/w_b + c/w_c) / (a/w_a + b/w_b + c/w_c) |
| |
| At infinite precision, this computation will produce f_p, however there |
| may be rounding error from the division operators that could result in |
| low-order bit differences in the final interpolated value. |
| |
| (13) What values are returned for queries of geometry shader-related |
| program properties that are not specified passthrough geometry |
| shaders (GEOMETRY_OUTPUT_TYPE, GEOMETRY_VERTICES_OUT)? |
| |
| RESOLVED: We will return values consistent with the input primitive |
| type, as though a non-passthrough geometry shader were specified. For |
| example, if the input primitive type is "triangles", the shader will be |
| treated as having declared: |
| |
| layout(triangle_strip, max_vertices=3) out; |
| |
| (14) Do passed through outputs count against the limit of total geometry |
| shader output components? What about the limit on the product of |
| per-vertex components and vertices emitted? |
| |
| RESOLVED: Yes, we still want a limit on the total number of components |
| in each output vertex. Input components qualified by "passthrough" are |
| also counted as output components for the purposes of both limit checks. |
| We expect that the latter limit (on the product) will never be relevant |
| because the total number of vertices in the output primitive can be at |
| most three. |
| |
| (15) How does this extension interact with the ability to change geometry |
| shader output vertex counts, using ProgramParameteriEXT with |
| GEOMETRY_VERTICES_OUT_EXT for GLSL programs (NV_geometry_shader4) or |
| ProgramVertexLimitNV API for assembly programs |
| (NV_geometry_program4)? |
| |
| RESOLVED: These commands allow applications to override the declared |
| maximum output vertex counts for geometry shaders based on information |
| known at runtime. Given that passthrough geometry shaders (and assembly |
| programs) will fail if they declare an output vertex count, it makes no |
| sense to override a declaration that doesn't exist. We will throw |
| INVALID_OPERATION if you try to use these APIs with passthrough geometry |
| shaders. |
| |
| (16) Does this extension interact with separable program objects? |
| |
| RESOLVED: Yes. All geometry shader inputs qualified with the |
| "passthrough" layout qualifier must also have a location explicitly |
| assigned using the "location" layout qualifier. Failing to do so will |
| result in a link-time error. |
| |
| The reason for this restriction is that inputs/outputs of one separable |
| program object may interface at run time with inputs/outputs of a |
| different separable program object. When linking one separable program |
| object, the GL has no idea what other program objects it may be used |
| with. To avoid requiring GL implementations to dynamically link program |
| objects X and Y at run time when they are used together, unextended |
| OpenGL requires an "interface match" to get defined results passing |
| values between stages. Basically, the outputs of program X and inputs |
| of program Y are considered to match: |
| |
| * for entire programs, if the set of declared inputs and outputs in |
| the programs are identical in name (or location, if assigned), type, |
| and qualification; or |
| |
| * for individual inputs, if the input has a matching output with |
| compatible type and qualification, if both variables use the same |
| location layout qualifier. |
| |
| The idea behind the exact matching requirement is that if you have |
| identical declarations on both sides of the interface, the |
| compiler/linker can employ a deterministic algorithm to assign locations |
| internally, based solely on the declared inputs/outputs. For such an |
| algorithm, the variables on both sides of the interface will naturally |
| get the same locations. For a program pipeline with separate vertex, |
| geometry, and fragment programs with "entire program" matches, this |
| implies that: |
| |
| * vertex outputs and geometry inputs are declared identically, and so |
| the compiler will assign the same locations; and |
| |
| * geometry outputs and fragment inputs are declared identically, and |
| so the compiler will assign the same locations. |
| |
| The problem with this extension is that its implementation introduces |
| one additional constraint -- the internal location assigned to a |
| passthrough geometry shader input must match the location assigned to |
| the matching implicitly-declared output. Adding this constraint to the |
| two bullets in the previous example implies that for any variable used |
| as a passthrough input in a geometry shader, there is one additional |
| rule: |
| |
| * the vertex outputs and fragment inputs matching a passthrough |
| geometry shader input must have the same locations. |
| |
| However, when the vertex and fragment program are linked, they have no |
| idea which variables might interface with a passthrough geometry shader |
| input. And there is clearly no constraint that the vertex outputs and |
| fragment inputs be declared identically -- some vertex outputs may be |
| consumed by the geometry shader, and some fragment inputs may be |
| produced (not by copy) by the geometry shader. Generating matching |
| locations without more information is basically impossible. |
| |
| As a result, we require that the passthrough geometry shader inputs in |
| separable programs must be declared with a location. Combining this |
| restriction with normal shader interface matching rules, it implies that |
| "matching" vertex outputs and fragment inputs must also be declared with |
| identical locations to get a complete interface match. |
| |
| This limitation doesn't apply to non-separable programs; the linker is |
| able to see all program interfaces and can assign internal locations for |
| all stages that satisfy the relevant constraints. The linker could |
| successfully assign internal locations for separable programs containing |
| multiple stages (e.g., GS+FS with no VS), but we chose to apply this |
| restriction to all separable programs for simplicity. |
| |
| (17) When an input block or any of its members is qualified with |
| "passthrough", this extension creates an implicitly declared |
| corresponding output block containing all members to be passed |
| through. How does this feature interact with the "location" layout |
| qualifier? |
| |
| RESOLVED: All members of the output block are treated as having |
| explicitly assigned locations inherited from matching input block |
| members. For example, if you had a geometry shader input block declared |
| as: |
| |
| layout(location=0) in Block { |
| layout(passthrough) vec4 a; // assigned location 0 |
| vec4 b; // assigned location 1 |
| layout(passthrough) vec4 c; // assigned location 2 |
| } v_in[]; |
| |
| the corresponding output block is treated as though it were declared as: |
| |
| out Block { |
| layout(location=0) vec4 a; |
| layout(location=2) vec4 c; |
| }; |
| |
| A fragment shader matching with such a shader must include a similar |
| input block declaration to get a complete interface match. |
| |
| To avoid the need to use location layout qualifiers on a |
| member-by-member basis, a shader author using blocks with location |
| qualifiers could choose to segregate passthrough and other inputs into |
| separate blocks. Alternately, all the passthrough inputs could be |
| placed at the beginning of the geometry input block, which would result |
| in a "normal" output block, except that the non-passthrough inputs would |
| be dropped. |
| |
| (18) Do built-in or user-defined inputs qualified with "passthrough" need |
| to be "arrayed"? |
| |
| RESOLVED: Yes. Normal geometry shader inputs must be declared in |
| "arrayed" form, where each vertex has its own set of inputs. Blocks |
| must be declared as an array of instances: |
| |
| in Block { |
| vec4 a; |
| } v_in[]; |
| |
| and non-block inputs must be declared as arrays: |
| |
| in vec4 a[]; // <a> is indexed by input vertex number |
| |
| It is illegal to declare non-arrayed geometry shader inputs, since it |
| wouldn't be clear which vertex to use when accessing such inputs. |
| |
| Passthrough geometry shaders don't change this requirement. |
| Additionally, the requirement still applies even if no code in the |
| passthrough geometry shader reads from the input. Note that in older |
| versions of this specification, some examples declared passthrough |
| inputs that were missing the per-vertex array declaration. |
| |
| Revision History |
| |
| Revision 4, 2017/02/15 (pbrown) |
| - Fix syntax issues in various sample code, including the introduction. |
| Passthrough inputs need to be declared as "arrayed" (with a separate |
| block instance for each vertex). Added issue (18) to clarify further. |
| |
| Revision 3, 2015/04/06 (mjk) |
| - Fix typos |
| |
| Revision 2, 2015/03/27 |
| - Add ES interactions |
| |
| Revision 1 |
| - Internal revisions. |
| |