blob: fe1c600834ceef61b02e166d151e636929f2d3f6 [file] [log] [blame]
Name
NV_viewport_array2
Name Strings
GL_NV_viewport_array2
Contact
Jeff Bolz, NVIDIA Corporation (jbolz 'at' nvidia.com)
Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)
Contributors
Pat Brown, NVIDIA
Mathias Heyer, NVIDIA
Status
Shipping
Version
Last Modified Date: March 27, 2015
Revision: 2
Number
OpenGL Extension #476
OpenGL ES Extension #237
Dependencies
This extension is written against the OpenGL 4.3 specification
(Compatibility Profile).
This extension interacts with the OpenGL ES 3.1 (March 17, 2014)
specification.
If implemented in OpenGL ES, NV_viewport_array, EXT_geometry_shader
and EXT_shader_io_blocks are required.
This extension interacts with EXT_tessellation_shader.
This extension interacts with NV_geometry_shader_passthrough.
This extension interacts with NV_gpu_program4.
Overview
This extension provides new support allowing a single primitive to be
broadcast to multiple viewports and/or multiple layers. A shader output
gl_ViewportMask[] is provided, allowing a single primitive to be output to
multiple viewports simultaneously. Also, a new shader option is provided
to control whether the effective viewport index is added into gl_Layer.
These capabilities allow a single primitive to be output to multiple
layers simultaneously.
The gl_ViewportMask[] output is available in vertex, tessellation
control, tessellation evaluation, and geometry shaders. gl_ViewportIndex
and gl_Layer are also made available in all these shader stages. The
actual viewport index or mask and render target layer values are taken
from the last active shader stage from this set of stages.
This extension is a superset of the GL_AMD_vertex_shader_layer and
GL_AMD_vertex_shader_viewport_index extensions, and thus those extension
strings are expected to be exported if GL_NV_viewport_array2 is
supported. This extension includes the edits for those extensions, recast
against the reorganized OpenGL 4.3 specification.
New Procedures and Functions
None.
New Tokens
None.
Additions to Chapter 11 of the OpenGL 4.3 (Compatibility Profile) Specification
(Programmable Vertex Processing)
Add to Section 11.1.3.10 (Shader Outputs)
The built-in output variables gl_ViewportIndex, gl_ViewportMask[], and
gl_Layer hold the viewport index/mask and render target layer, as described
in Section 11.4 (Viewport Index and Layer).
Add to Section 11.2.1.2.3 (Tessellation Control Shader Outputs)
The built-in output variables gl_ViewportIndex, gl_ViewportMask[], and
gl_Layer hold the viewport index/mask and render target layer, as described
in Section 11.4 (Viewport Index and Layer).
Add to Section 11.2.3.4 (Tessellation Evaluation Shader Outputs)
The built-in output variables gl_ViewportIndex, gl_ViewportMask[], and
gl_Layer hold the viewport index/mask and render target layer, as described
in Section 11.4 (Viewport Index and Layer).
Modify Section 11.3.4.5 (Geometry Shader Outputs)
Replace the paragraph about gl_ViewportIndex:
The built-in output variables gl_ViewportIndex, gl_ViewportMask[], and
gl_Layer hold the viewport index/mask and render target layer, as described
in Section 11.4 (Viewport Index and Layer).
Replace Section 11.3.4.6 (Layer and Viewport Selection) with new Section
11.4 (Layer and Viewport Selection)
Geometry may be rendered to one of several different layers of cube map
textures, three-dimensional textures, or one- or two-dimensional texture
arrays. This functionality allows an application to bind an entire complex
texture to a framebuffer object, and render primitives to arbitrary layers
computed at run time. For example, it can be used render a scene into
multiple layers of an array texture in one pass, or to select a particular
layer to render to in shader code. The layer to render to is specified by
writing to the built-in output variable gl_Layer. Layered rendering
requires the use of framebuffer objects (see section 9.8).
Shaders may also direct each primitive to zero or more viewports. The
destination viewports for a primitive may be selected in the shader by
writing to the built-in output variable gl_ViewportIndex (selecting a
single viewport) or gl_ViewportMask[] (selecting multiple viewports).
This functionality allows a shader to direct its output to different
viewports for each primitive, or to draw multiple versions of a primitive
into several different viewports.
The specific vertex of a primitive used to select the rendering layer or
viewport index/mask is implementation-dependent and thus portable
applications will assign the same layer and viewport index for all
vertices in a primitive. The vertex conventions followed for gl_Layer and
gl_ViewportIndex/gl_ViewportMask[] may be determined by calling
GetIntegerv with the symbolic constants LAYER_PROVOKING_VERTEX and
VIEWPORT_INDEX_PROVOKING_VERTEX, respectively. For either query, if the
value returned is PROVOKING_VERTEX, then vertex selection follows the
convention specified by ProvokingVertex (see section 13.4). If the value
returned is FIRST_VERTEX_CONVENTION, selection is always taken from the
first vertex of a primitive. If the value returned is
LAST_VERTEX_CONVENTION, the selection is always taken from the last vertex
of a primitive. If the value returned is UNDEFINED_VERTEX, the selection
is not guaranteed to be taken from any specific vertex in the
primitive. The vertex considered the provoking vertex for particular
primitive types is given in table 13.2.
The layer selection may be made a function of the viewport index, as
described in Section 7.1 of the GLSL specification.
The viewport index, viewport mask, and layer outputs are available in
vertex, tessellation control, tessellation evaluation, and geometry
shaders. Only the last active shader stage (in pipeline order) from this
list controls the viewport index/mask and layer; outputs in previous
shader stages are not used, even if the last stage fails to write one of
the outputs.
Additions to Chapter 13 of the OpenGL 4.3 (Compatibility Profile) Specification
(Fixed-Function Vertex Post-Processing)
Modify Section 13.2 (Transform Feedback), p. 453
Modify the first paragraph:
...The vertices are fed back after vertex color clamping, but before
viewport mask expansion, flatshading, and clipping. ...
Modify Section 13.6.1 (Controlling the Viewport)
Multiple viewports are available and are numbered zero through the value
of MAX_VIEWPORTS minus one. If last active vertex, tessellation, or
geometry shader writes to gl_ViewportIndex, the primitive is emitted to
the viewport corresponding to the value assigned to gl_ViewportIndex, as
taken from an implementation-dependent provoking vertex. The primitive is
then transformed using the state of the selected viewport. If the value
of the viewport index is outside the range zero to the value of
MAX_VIEWPORTS minus one, the results of the viewport transformation are
undefined.
If last active vertex, tessellation, or geometry shader writes to
gl_ViewportMask[], the primitive is emitted to zero or more viewports. If
bit <i> is set in the mask, the primitive is emitted to viewport <i> and
transformed using the state of viewport <i>. However, each primitive will
still be captured by transform feedback and counted by primitive queries
only once. If bits of gl_ViewportMask[] greater than or equal to the
value of MAX_VIEWPORTS are set, the number of times the primitive is
emitted and which viewport transformations are used are undefined.
If neither gl_ViewportIndex nor gl_ViewportMask[] are written, the
viewport numbered zero is used by the viewport transformation.
Modify Section 14.5.2.1 (Line Stipple)
(add to the end of the section)
When rasterizing line segments that could be sent to multiple viewports
via the gl_ViewportMask[] built-in geometry shader output (section
13.6.1), the line stipple pattern is not guaranteed to be continuous if
segments are sent to multiple viewports. If a line segment is not an
independent line segment and is not the first in a series of connected
segments (where the stipple counter <s> is reset to 0), the initial value
of <s> for the segment is undefined unless that line segment and all
previous segments in the series were sent to the same single viewport.
New Implementation Dependent State
None.
New State
None.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
None.
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_viewport_array2 : <behavior>
where <behavior> is as specified in section 3.3.
New preprocessor #defines are added to the OpenGL Shading Language:
#define GL_NV_viewport_array2 1
Modify Section 7.1 (Built-In Language Variables), p. 116
Add to the list of vertex shader built-ins:
out gl_PerVertex {
highp int gl_ViewportIndex;
highp int gl_ViewportMask[];
highp int gl_Layer;
};
Add to the list of geometry shader built-ins:
out highp int gl_ViewportMask[];
Add to the list of tessellation control shader built-ins:
out gl_PerVertex {
highp int gl_ViewportIndex;
highp int gl_ViewportMask[];
highp int gl_Layer;
} gl_out[];
Add to the list of tessellation evaluation shader built-ins:
out gl_PerVertex {
highp int gl_ViewportIndex;
highp int gl_ViewportMask[];
highp int gl_Layer;
};
Modify descriptions of gl_Layer and gl_ViewportIndex as follows:
The variable gl_Layer is available as an output variable in the vertex,
tessellation, and geometry (VTG) languages and an input variable in the
fragment language. In the VTG languages, it is used to select a specific
layer (or face and layer of a cube map) of a multi-layer framebuffer
attachment. The actual layer used will come from one of the vertices in
the primitive being shaded. Which vertex the layer comes from is undefined,
so it is best to write the same layer value for all vertices of a
primitive. If a shader statically assigns a value to gl_Layer, layered
rendering mode is enabled. See section 11.4 "Layer and Viewport Selection"
and section 9.4.9 "Layered Framebuffers" of the OpenGL Graphics System
Specification for more information. If a shader statically assigns a value
to gl_Layer, and there is an execution path through the shader that does
not set gl_Layer, then the value of gl_Layer is undefined for executions
of the shader that take that path.
...
The input variable gl_Layer in the fragment language will have the same
value that was written to the output variable gl_Layer in the VTG
languages. If the final VTG stage does not dynamically assign a value to
gl_Layer, the value of gl_Layer in the fragment stage will be undefined.
If the final VTG stage makes no static assignment to gl_Layer, the input
gl_Value in the fragment stage will be zero. Otherwise, the fragment stage
will read the same value written by the final VTG stage, even if that value
is out of range. If a fragment shader contains a static access to gl_Layer,
it will count against the implementation defined limit for the maximum
number of inputs to the fragment stage.
The variable gl_ViewportIndex is available as an output variable in the
VTG languages and an input variable in the fragment language. In the
geometry language, it provides the index of the viewport to which the next
primitive emitted from the geometry shader should be drawn. In the vertex
and tessellation languages, it provides the index of the viewport
associated with the vertex being shaded. Primitives will undergo viewport
transformation and scissor testing using the viewport transformation and
scissor rectangle selected by the value of gl_ViewportIndex. The viewport
index used will come from one of the vertices in the primitive being
shaded. However, which vertex the viewport index comes from is
implementation-dependent, so it is best to use the same viewport index for
all vertices of the primitive. If the final VTG stage does not assign a
value to gl_ViewportIndex or gl_ViewportMask[], viewport transform and
scissor rectangle zero will be used. If a shader statically assigns a value
to gl_ViewportIndex and there is a path through the shader that does not
assign a value to gl_ViewportIndex, the value of gl_ViewportIndex is
undefined for executions of the shader that take that path. See section
11.4 "Layer and Viewport Selection" of the OpenGL Graphics System
Specification for more information.
The input variable gl_ViewportIndex in the fragment stage will have the
same value that was written to the output variable gl_ViewportIndex in the
final VTG stage. If the final VTG stage does not dynamically assign to
gl_ViewportIndex, the value of gl_ViewportIndex in the fragment shader will
be undefined. If the final VTG stage makes no static assignment to
gl_ViewportIndex, the fragment stage will read zero. Otherwise, the
fragment stage will read the same value written by the final VTG stage,
even if that value is out of range. If a fragment shader contains a static
access to gl_ViewportIndex, it will count against the implementation
defined limit for the maximum number of inputs to the fragment stage.
The variable gl_ViewportMask[] is available as an output variable in the
VTG languages. The array has ceil(v/32) elements where v is the maximum
number of viewports supported by the implementation. When a shader writes
this variable, bit B of element M controls whether the primitive is
emitted to viewport 32*M+B. If gl_ViewportIndex is written by the final
VTG stage, then gl_ViewportIndex in the fragment stage will have the same
value. If gl_ViewportMask[] is written by the final VTG stage, then
gl_ViewportIndex in the fragment stage will have the index of the viewport
that was used in generating that fragment.
If a shader statically assigns a value to gl_ViewportIndex, it may not
assign a value to any element of gl_ViewportMask[]. If a shader
statically writes a value to any element of gl_ViewportMask[], it may
not assign a value to gl_ViewportIndex. That is, a shader may assign
values to either gl_ViewportIndex or gl_ViewportMask[], but not
both. Multiple shaders linked together must also consistently write just
one of these variables. These incorrect usages all generate compile-time
or link-time errors.
The shader output gl_Layer may be redeclared with a layout qualifer
<viewport_relative> as follows:
layout (viewport_relative) out highp int gl_Layer;
If gl_Layer is <viewport_relative>, then the viewport index is added to
the layer used for rendering (and available in the fragment shader). If
the shader writes gl_ViewportMask[], then gl_Layer has a different value
for each viewport the primitive is rendered to. If gl_Layer is
<viewport_relative> and the shader writes neither gl_ViewportIndex nor
gl_ViewportMask[], a link-error will result.
Modify Section 8.15 (Geometry Shader Functions)
The function EmitStreamVertex() specifies that a vertex is completed. A
vertex is added to the current output primitive in vertex stream <stream>
using the current values of all output variables associated with <stream>.
These include gl_PointSize, gl_ClipDistance, gl_Layer, gl_Position,
gl_PrimitiveID, gl_ViewportIndex, and gl_ViewportMask[]. The values of
all output variables for all output streams are undefined after a call to
EmitStreamVertex().
Errors
None.
Interactions with OpenGL ES 3.1
Unless functionality similar to ARB_provoking_vertex is supported, remove
references to PROVOKING_VERTEX and ProvokingVertex(). Also remove
reference to 'vertex color clamping'. The modifications to Line Stippling
don't apply.
Interactions with EXT_tessellation_shader
If implemented on OpenGL ES and EXT_tessellation_shader is not supported,
remove all language referring to the tesselation control and tessellation
evaluation pipeline stages.
Interactions with NV_geometry_shader_passthrough
If NV_geometry_shader_passthrough is supported, the NV_gpu_program4 and
NV_geometry_program4 language describing the PASSTHROUGH declaration
statement should be modified to state that "result.viewportmask" may not
be used in such a declaration.
Interactions with NV_gpu_program4
If NV_gpu_program4 is supported and the "NV_viewport_array2" program
option is specified, vertex, tessellation control/evaluation, and geometry
program result variable "result.viewportmask" can be used to specify the
mask of viewports that the primitive will be emitted to, "result.viewport"
can be used to specify the index of the viewport that the primitive will
be emitted to, and "result.layer" can be used to specify the layer of a
layered framebuffer attachment that the primitive will be emitted to.
(add the following rule to the NV_gpu_program4 grammar)
<resultBasic> ::= ...
| <resPrefix> "viewportmask" arrayMemAbs
| <resPrefix> "viewport"
| <resPrefix> "layer"
(add the following to the tables of Vertex, Geometry, and Tessellation
Control/Eval Program Result Variable Bindings)
Binding Components Description
----------------------------- ---------- ----------------------------
result.viewportmask[] (v,*,*,*) viewport array mask
result.viewport (v,*,*,*) viewport array index
result.layer (l,*,*,*) layer for cube/array/3D FBOs
(add the following to Section 2.X.2, Program Grammar)
If a result variable binding matches "result.viewportmask", updates to the
"x" component of the result variable provide a single integer that serves
as a mask of viewport indices. The mask must be written as an integer
value; writing a floating-point value will produce undefined results.
If the value has bits greater than or equal to MAX_VIEWPORTS set, the
number of viewports the primitive is emitted to and which viewports are
used are undefined. If the "NV_viewport_array2" program option is not
specified, the "result.viewportmask" binding is unavailable.
If both "result.viewport" and "result.viewportmask" are written,
compilation will fail.
(add the following to Section 2.X.6.Y, Program Options)
+ Viewport Mask (NV_viewport_array2)
If a vertex, geometry, tessellation control, or tessellation evaluation
program specifies the "NV_viewport_array2" option, the result binding
"result.viewportmask" will be available to specify the mask of viewports
to use for primitive viewport transformations and scissoring as described
in section 2.X.2. Additionally, the "result.viewport" and "result.layer"
result bindings will be available in these same shader stages.
If a program specifies the "NV_layer_viewport_relative" option, the
result.layer will have the viewport index automatically added to it. If
the result.viewportmask is used, the result.layer will be different for
each viewport the primitive is emitted to.
Issues
(1) Where does the viewport mask broadcast occur?
RESOLVED: This operation could potentially be performed before or after
transform feedback, but feeding back several viewports worth of primitives
doesn't seem particularly useful. This specification applies the viewport
mask after transform feedback, and makes primitive queries only count each
primitive once.
Note that it is possible to capture viewport mask shader outputs when
transform feedback is active.
(2) How does the gl_ViewportIndex fragment input behave?
RESOLVED: Whether viewport mask or viewport indices are used in VTG
shaders, the fragment shader input gl_ViewportIndex will contain the
viewport number for the primitive generating each fragment. If the
viewport mask is used to broadcast a single primitive to multiple
viewports, and the same pixel is covered by the primitive in each
viewport, multiple fragment shader invocations for that pixel will be
generated, each with a different value of gl_ViewportIndex.
This extension provides no gl_ViewportMask[] input, so a fragment shader
is not able to see the original viewport mask for the primitive generating
the fragment. If necessary, this value could be passed by a separate
shader variable qualified with "flat".
(3) How does the viewport mask interact with line stipple?
RESOLVED: With viewport mask, it's possible to broadcast line strips to
multiple viewports. If line stipple is enabled in the OpenGL
compatibility profile, implementations are required to maintain a
continuous stipple pattern across the strip. When primitives are
broadcast via viewport mask, implementations will not always be able to
buffer an entire strip and send it to each viewport in turn. So it will
often be necessary to break up a long strip, and send segments to
alternating viewports. An implementation could handle this by breaking up
the strip and keeping N independent stipple counters, but that seems like
overkill.
We relax normal spec requirements and require a continuous stipple pattern
only if the entire strip if sent to exactly one viewport. If any segment
in the strip is sent to multiple viewports, no viewports, or a different
viewport than previous segments, the stipple counter for that segment and
subsequent segments in the strip is undefined.
(4) Can a viewport index or mask written by vertex or tessellation shader
be read by downstream tessellation or geometry shaders?
RESOLVED: No. The fragment shader is able to read the viewport index, but
this extension provides no built-in input allowing VTG shaders to see a
viewport index or mask written by a previous shader stage.
(5) Can this extension be used to "kill" primitives in a passthrough
geometry shader (NV_geometry_shader_passthrough)?
RESOLVED: Yes. In regular geometry shaders, input primitives can be
killed by returning without emitting any vertices. That's not possible
with passthrough geometry shaders, however it is possible to code a
passthrough geometry shader like:
void main()
{
if (shouldKillPrimitive()) {
// Set the viewport mask to zero. A primitive will still be
// emitted from the geometry shader stage, however it will be sent
// to no viewports and thus be discarded. Any other per-primitive
// outputs will be undefined.
gl_ViewportMask[0] = 0;
return;
}
// Since the shader writes the viewport mask in the "kill" path, it
// also needs to write it in the non-"kill" path; otherwise, its
// value would be undefined and the primitive will be sent to an
// undefined set of viewports. Setting the mask to 1 will always
// send a primitive to viewport zero.
gl_ViewportMask[0] = 1;
...
}
Without the viewport mask or a similar feature, it is not possible to kill
primitives in a passthrough geometry shader.
Revision History
Revision 2, 2015/03/27
- Add ES interactions
Revision 1
- Internal revisions.