1Name 2 3 NV_viewport_array 4 5Name Strings 6 7 GL_NV_viewport_array 8 9Contributors 10 11 Contributors to ARB_viewport_array 12 Mathias Heyer, NVIDIA 13 James Helferty, NVIDIA 14 Daniel Koch, NVIDIA 15 16Contact 17 18 Mathias Heyer, NVIDIA (mheyer 'at' nvidia.com) 19 20Notice 21 22 Copyright (c) 2010-2014 The Khronos Group Inc. Copyright terms at 23 http://www.khronos.org/registry/speccopyright.html 24 25 Portions Copyright (c) 2014 NVIDIA Corporation. 26 27Status 28 29 Complete 30 31Version 32 33 Last Modified Date: 10/24/2014 34 Author Revision: 5 35 36Number 37 38 OpenGL ES Extension #202 39 40Dependencies 41 42 This extension is written against the OpenGL ES 3.1 (March 14, 2014) 43 Specification. 44 45 This extension is written against the OpenGL ES Shading Language 46 Specification version 3.10 (March 14, 2014) 47 48 OpenGL ES 3.1 and the EXT_geometry_shader extension are required. 49 50 This extension interacts with EXT_draw_buffers_indexed. 51 52Overview 53 54 OpenGL ES is modeled on a pipeline of operations. The final stage in this 55 pipeline before rasterization is the viewport transformation. This stage 56 transforms vertices from view space into window coordinates and allows the 57 application to specify a rectangular region of screen space into which 58 OpenGL should draw primitives. Unextended OpenGL implementations provide a 59 single viewport per context. In order to draw primitives into multiple 60 viewports, the OpenGL viewport may be changed between several draw calls. 61 With the advent of Geometry Shaders, it has become possible for an 62 application to amplify geometry and produce multiple output primitives for 63 each primitive input to the Geometry Shader. It is possible to direct these 64 primitives to render into a selected render target. However, all render 65 targets share the same, global OpenGL viewport. 66 67 This extension enhances OpenGL by providing a mechanism to expose multiple 68 viewports. Each viewport is specified as a rectangle. The destination 69 viewport may be selected per-primitive by the geometry shader. This allows 70 the Geometry Shader to produce different versions of primitives destined 71 for separate viewport rectangles on the same surface. Additionally, when 72 combined with multiple framebuffer attachments, it allows a different 73 viewport rectangle to be selected for each. This extension also exposes a 74 separate scissor rectangle for each viewport. Finally, the viewport bounds 75 are now floating point quantities allowing fractional pixel offsets to be 76 applied during the viewport transform. 77 78New Procedures and Functions 79 80 void ViewportArrayvNV(uint first, sizei count, const float * v); 81 void ViewportIndexedfNV(uint index, float x, float y, float w, float h); 82 void ViewportIndexedfvNV(uint index, const float * v); 83 void ScissorArrayvNV(uint first, sizei count, const int * v); 84 void ScissorIndexedNV(uint index, int left, int bottom, sizei width, sizei height); 85 void ScissorIndexedvNV(uint index, const int * v); 86 void DepthRangeArrayfvNV(uint first, sizei count, const float * v); 87 void DepthRangeIndexedfNV(uint index, float n, float f); 88 void GetFloati_vNV(enum target, uint index, float *data); 89 90 void EnableiNV(enum target, uint index); 91 void DisableiNV(enum target, uint index); 92 boolean IsEnablediNV(enum target, uint index); 93 94New Tokens 95 96 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, 97 and GetInteger64v: 98 99 MAX_VIEWPORTS_NV 0x825B 100 VIEWPORT_SUBPIXEL_BITS_NV 0x825C 101 VIEWPORT_BOUNDS_RANGE_NV 0x825D 102 VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F 103 104 Accepted by the <pname> parameter of GetIntegeri_v: 105 106 SCISSOR_BOX 0x0C10 107 108 Accepted by the <pname> parameter of GetFloati_vNV: 109 110 VIEWPORT 0x0BA2 111 DEPTH_RANGE 0x0B70 112 113 Accepted by the <pname> parameter of EnableiNV, DisableiNV, 114 and IsEnablediNV: 115 116 SCISSOR_TEST 0x0C11 117 118Additions to Chapter 11 of the OpenGL ES 3.1 Specification 119(Programmable Vertex Processing) 120 121 Modify section Section 11.1gs.4.5 Layer Selection 122 123 Rename the the "Layer Selection" subsection to "Layer and Viewport 124 Selection". 125 126 After the first paragraph, insert: 127 128 Geometry shaders may also select the destination viewport for each 129 output primitive. The destination viewport for a primitive may be 130 selected in the geometry shader by writing to the built-in output 131 variable gl_ViewportIndex. This functionality allows a geometry 132 shader to direct its output to a different viewport for each 133 primitive, or to draw multiple versions of a primitive into several 134 different viewports. 135 136 Replace the first two sentences of the second paragraph with: 137 138 The specific vertex of a primitive that is used to select the 139 rendering layer or viewport index is implementation-dependent and 140 thus portable applications will assign the same layer and viewport 141 index for all vertices in a primitive. The vertex conventions 142 followed for gl_Layer and gl_ViewportIndex may be determined by 143 calling GetIntegerv with the symbolic constants 144 LAYER_PROVOKING_VERTEX_EXT and VIEWPORT_INDEX_PROVOKING_VERTEX_NV, 145 respectively. 146 147 Modify section 12.5.1 "Controlling the Viewport", page 284. 148 149 Change the first paragraph of section 12.5.1 to read 150 151 The viewport transformation is determined by the selected viewport's 152 width and height in pixels, p_x and p_y, respectively, and its 153 center (o_x,o_y) (also in pixels) ... 154 155 { leave equations intact } 156 157 Multiple viewports are available and are numbered zero through the 158 value of MAX_VIEWPORTS_NV minus one. If a geometry shader is active 159 and writes to gl_ViewportIndex, the viewport transformation uses the 160 viewport corresponding to the value assigned to gl_ViewportIndex 161 taken from an implementation-dependent primitive vertex. If the 162 value of the viewport index is outside the range zero to the value 163 of MAX_VIEWPORTS_NV minus one, the results of the viewport 164 transformation are undefined. If no geometry shader is active, or if 165 the active geometry shader does not write to gl_ViewportIndex, the 166 viewport numbered zero is used by the viewport transformation. 167 168 A single vertex may be used in more than one individual primitive, in 169 primitives such as TRIANGLE_STRIP. In this case, the viewport 170 transformation is applied separately for each primitive. 171 172 The factor and offset applied to Z_d for each viewport encoded by n 173 and f are set using 174 175 void DepthRangeArrayfvNV(uint first, sizei count, const float * v); 176 void DepthRangeIndexedfNV(uint index, float n, float f); 177 void DepthRangef(float n, float f); 178 179 DepthRangeArrayfvNV is used to specify the depth range for multiple 180 viewports simultaneously. <first> specifies the index of the first 181 viewport to modify and <count> specifies the number of viewports. If 182 (<first> + <count>) is greater than the value of MAX_VIEWPORTS_NV then 183 an INVALID_VALUE error will be generated. Viewports whose indices 184 lie outside the range [<first>, <first> + <count>) are not modified. 185 The <v> parameter contains the address of an array of float types 186 specifying near (n) and far (f) for each viewport in that order. 187 (n) and (f) of each viewport will be clamped to [0.0, 1.0]. 188 189 DepthRangeIndexedfNV specifies the depth range for a single viewport 190 and is equivalent (assuming no errors are generated) to: 191 192 float v[] = { n, f }; 193 DepthRangeArrayfvNV(index, 1, v); 194 195 DepthRangef sets the depth range for all viewports to the same values 196 and is equivalent (assuming no errors are generated) to: 197 198 for (uint i = 0; i < MAX_VIEWPORTS_NV; i++) 199 DepthRangeIndexedfNV(i, n, f); 200 201 Z_w is represented as either ... 202 203 Replace the end of section 12.5.1, starting from "Viewport transformation 204 parameters are specified using..." 205 206 Viewport transformation parameters are specified using 207 208 void ViewportArrayvNV(uint first, sizei count, const float * v); 209 void Viewport(int x, int y, sizei w, sizei h); 210 void ViewportIndexedfNV(uint index, float x, float y, float w, float h); 211 void ViewportIndexedfvNV(uint index, const float * v); 212 213 ViewportArrayvNV specifies parameters for multiple viewports 214 simultaneously. <first> specifies the index of the first viewport to 215 modify and <count> specifies the number of viewports. If (<first> + 216 <count>) is greater than the value of MAX_VIEWPORTS_NV then an 217 INVALID_VALUE error will be generated. Viewports whose indices lie 218 outside the range [<first>, <first> + <count>) are not modified. 219 <v> contains the address of an array of floating point values 220 specifying the left (x), bottom (y), width (w) and height (h) of 221 each viewport, in that order. <x> and <y> give the location of the 222 viewport's lower left corner and <w> and <h> give the viewport's 223 width and height, respectively. 224 225 ViewportIndexedfNV and ViewportIndexedfvNV specify parameters for a 226 single viewport and are equivalent (assuming no errors are 227 generated) to: 228 229 float v[4] = { x, y, w, h }; 230 ViewportArrayvNV(index, 1, v); 231 232 and 233 234 ViewportArrayvNV(index, 1, v); 235 236 respectively. 237 238 Viewport sets the parameters for all viewports to the same values 239 and is equivalent (assuming no errors are generated) to: 240 241 for (uint i = 0; i < MAX_VIEWPORTS_NV; i++) 242 ViewportIndexedfNV(i, (float)x, (float)y, (float)w, (float)h); 243 244 The viewport parameters shown in the above equations are found from these 245 values as 246 247 o_x = x + w /2, 248 o_y = y + h / 2, 249 p_x = w, 250 p_y = h. 251 252 The location of the viewport's bottom-left corner, given by (x,y), are 253 clamped to be within the implementation-dependent viewport bounds range. 254 The viewport bounds range [min, max] tuple may be determined by 255 calling GetFloatv with the symbolic constant VIEWPORT_BOUNDS_RANGE_NV 256 (see chapter 20). 257 258 Viewport width and height are clamped to implementation-dependent maximums 259 when specified. The maximum width and height may be found by calling 260 GetFloatv with the symbolic constant MAX_VIEWPORT_DIMS. The maximum 261 viewport dimensions must be greater than or equal to the larger of 262 the visible dimensions of the display being rendered to (if a 263 display exists), and the largest renderbuffer image which can be 264 successfully created and attached to a framebuffer object (see 265 chapter 9). INVALID_VALUE is generated if either w or h is negative. 266 267 The state required to implement the viewport transformations is four 268 floating-point values and two clamped floating-point values for each 269 viewport. In the initial state, w and h for each viewport are set to 270 the width and height, respectively, of the window into which the GL 271 is to do its rendering. If the default framebuffer is bound but no 272 default framebuffer is associated with the GL context (see chapter 273 9), then w and h are initially set to zero. o_x and o_y are set to 274 w/2 and h/2, respectively. n and f are set to 0.0 and 1.0, 275 respectively. 276 277 The precision with which the GL interprets the floating point viewport 278 bounds is implementation-dependent and may be determined by querying the 279 implementation-defined constant VIEWPORT_SUBPIXEL_BITS_NV. 280 281Additions to Chapter 15 of the OpenGL ES 3.1 Specification (Writing 282Fragments and Samples to the Framebuffer) 283 284 Replace section 15.1.2 "Scissor Test", page 309. 285 286 The scissor test determines if (xw, yw) lies within the scissor rectangle 287 defined by four values for each viewport. These values are set with 288 289 void ScissorArrayvNV(uint first, sizei count, const int * v); 290 void ScissorIndexedNV(uint index, int left, int bottom, sizei width, sizei height); 291 void ScissorIndexedvNV(uint index, int * v); 292 void Scissor(int left, int bottom, sizei width, sizei height); 293 294 ScissorArrayvNV defines a set of scissor rectangles that are each 295 applied to the corresponding viewport (see section 12.5.1 296 "Controlling the Viewport"). <first> specifies the index of the 297 first scissor rectangle to modify, and <count> specifies the number 298 of scissor rectangles. If (<first> + <count>) is greater than the 299 value of MAX_VIEWPORTS_NV, then an INVALID_VALUE error is generated. 300 <v> contains the address of an array of integers containing the 301 left, bottom, width and height of the scissor rectangles, in that 302 order. 303 304 If left <= x_w < left + width and bottom <= y_w < bottom + height 305 for the selected scissor rectangle, then the scissor test passes. 306 Otherwise, the test fails and the fragment is discarded. For points, 307 lines, and polygons, the scissor rectangle for a primitive is 308 selected in the same manner as the viewport (see section 12.5.1). 309 310 The scissor test is enabled or disabled for all viewports using 311 Enable or Disable with the symbolic constant SCISSOR_TEST. The test 312 is enabled or disabled for a specific viewport using EnableiNV or 313 DisableiNV with the constant SCISSOR_TEST and the index of the 314 selected viewport. When disabled, it is as if the scissor test 315 always passes. The value of the scissor test enable for viewport <i> 316 can be queried by calling IsEnablediNV with <target> SCISSOR_TEST and 317 <index> <i>. The value of the scissor test enable for viewport zero 318 may also be queried by calling IsEnabled with the same symbolic 319 constant, but no <index> parameter. If either width or height is 320 less than zero for any scissor rectangle, then an INVALID_VALUE 321 error is generated. If the viewport index specified to EnableiNV, 322 DisableiNV or IsEnablediNV is greater or equal to the value of 323 MAX_VIEWPORTS_NV, then an INVALID_VALUE error is generated. 324 325 The state required consists of four integer values per viewport, and 326 a bit indicating whether the test is enabled or disabled for each 327 viewport. In the initial state, left = bottom = 0, and width and 328 height are determined by the size of the window into which the GL is 329 to do its rendering for all viewports. If the default framebuffer is 330 bound but no default framebuffer is associated with the GL context 331 (see chapter 9), then with and height are initially set to zero. 332 Initially, the scissor test is disabled for all viewports. 333 334 ScissorIndexedNV and ScissorIndexedvNV specify the scissor rectangle for 335 a single viewport and are equivalent (assuming no errors are 336 generated) to: 337 338 int v[] = { left, bottom, width, height }; 339 ScissorArrayvNV(index, 1, v); 340 341 and 342 343 ScissorArrayvNV(index, 1, v); 344 345 respectively. 346 347 Scissor sets the scissor rectangle for all viewports to the same 348 values and is equivalent (assuming no errors are generated) to: 349 350 for (uint i = 0; i < MAX_VIEWPORTS_NV; i++) { 351 ScissorIndexedNV(i, left, bottom, width, height); 352 } 353 354 Calling Enable or Disable with the symbolic constant SCISSOR_TEST is 355 equivalent, assuming no errors, to: 356 357 for (uint i = 0; i < MAX_VIEWPORTS_NV; i++) { 358 EnableiNV(SCISSOR_TEST, i); 359 /* or */ 360 DisableiNV(SCISSOR_TEST, i); 361 } 362 363Additions to Chapter 19 of the OpenGL ES 3.1 Specification (Context State 364Queries) 365 366 Modifications to Section 19.1 Simple Queries 367 368 Add to the list of indexed query functions: 369 370 void GetFloati_vNV(enum target, uint index, float *data); 371 372Additions to the OpenGL ES Shading Language Version 3.10 Specification 373 374 Add a new Section 3.4.x, GL_NV_viewport_array Extension (p. 13) 375 376 3.4.x GL_NV_viewport_array Extension 377 378 To use the GL_NV_viewport_array extension in a shader it must be 379 enabled using the #extension directive. 380 381 The shading language preprocessor #define GL_NV_viewport_array will 382 be defined to 1 if the GL_NV_viewport_array extension is supported. 383 384 Modify Section 7.1.1gs, "Geometry Shader Special Variables" 385 386 Add to the list of geometry shader built-in variables: 387 388 out highp int gl_ViewportIndex; // may be written to 389 390 391 Additions to Section 7.1.1gs.2, "Geometry Shader Output Variables" 392 393 Add a paragraph after the paragraph describing gl_Layer, starting 394 "gl_Layer is used to select a specific layer (or face and layer of a 395 cube map) of a multi-layer framebuffer attachment.": 396 397 The built-in variable gl_ViewportIndex is available as an output variable 398 in the geometry shader and an input variable in the fragment shader. In the 399 geometry shader it provides the index of the viewport to which the next 400 primitive emitted from the geometry shader should be drawn. Primitives 401 generated by the geometry shader will undergo viewport transformation and 402 scissor testing using the viewport transformation and scissor rectangle 403 selected by the value of gl_ViewportIndex. The viewport index used will 404 come from one of the vertices in the primitive being shaded. Which vertex 405 the viewport index comes from is implementation-dependent, so it is best to 406 use the same viewport index for all vertices of the primitive. If a 407 geometry shader does not assign a value to gl_ViewportIndex, viewport 408 transform and scissor rectangle zero will be used. If a geometry shader 409 assigns a value to gl_ViewportIndex and there is a path through the shader 410 that does not set gl_ViewportIndex, then the value of gl_ViewportIndex is 411 undefined for executions of the shader that take that path. See section 412 11.1gs.4 "Geometry Shader Outputs" of the OpenGL ES Specification for more 413 information. 414 415 Modify section 7.1.2 "Fragment Shader Special Variables", as modified by 416 EXT_geometry_shader: 417 418 Add to the list of built-in variables: 419 420 in highp int gl_ViewportIndex; 421 422 Add description of the variable: 423 424 The input variable gl_ViewportIndex will have the same value that was 425 written to the output variable gl_ViewportIndex in the geometry stage. If 426 the geometry stage does not dynamically assign to gl_ViewportIndex, the 427 value of gl_ViewportIndex in the fragment shader will be undefined. If the 428 geometry stage makes no static assignment to gl_ViewportIndex, the fragment 429 stage will read zero. Otherwise, the fragment stage will read the same 430 value written by the geometry stage, even if that value is out of range. If 431 a fragment shader contains a static access to gl_ViewportIndex, it will 432 count against the implementation defined limit for the maximum number of 433 inputs to the fragment stage. 434 435 Add to Section 7.2 "Built-In Constants", as modified by 436 EXT_geometry_shader, to the list of built-in constants matching the 437 corresponding API implementation-dependent limits: 438 439 const highp int gl_MaxViewports = 16; 440 441Errors 442 443 INVALID_VALUE is generated by ViewportArrayvNV if <first> + <count> is 444 greater than or equal to the value of MAX_VIEWPORTS_NV, or if any 445 viewport's width or height is less than 0. 446 447 INVALID_VALUE is generated by ScissorArrayvNV if <first> + <count> is 448 greater than or equal to the value of MAX_VIEWPORTS_NV, or if any 449 scissor rectangle's width or height is less than zero. 450 451 INVALID_VALUE is generated by DepthRangeArrayfvNV if <first> + <count> is 452 greater than or equal to the vaue of MAX_VIEWPORTS_NV. 453 454 INVALID_VALUE is generated by EnableiNV, DisableiNV and IsEnablediNV if 455 <index> is greater than or equal to the value of MAX_VIEWPORTS_NV. 456 457New State 458 459 Table 20.5 (p. 356) 460 461 Get Value Type Get Command Initial Value Description Sec 462 ------------------------ ---------------- ------------ ------------- -------------------------- ----- 463 VIEWPORT 16* x 4 x R GetFloati_vNV See 2.11.1 Viewport origin & extent 12.5.1 464 DEPTH_RANGE 16* x 2 x R[0,1] GetFloati_vNV See 2.16.1 Depth range near & far 12.5.1 465 466NOTE: The changes are that VIEWPORT and DEPTH_RANGE are extended to 467accommodate 16* copies and now consist of floating-point and 468double-precision values, respectively. 469 470 Table 20.12 (p. 363) 471 472 Get Value Type Get Command Initial Value Description Sec 473 ------------------------ ---------- ------------- ------------- ------------------- ------ 474 SCISSOR_TEST 16* x B IsEnablediNV FALSE Scissoring enabled 15.1.2 475 SCISSOR_BOX 16* x 4 x Z GetIntegeri_v See 4.1.2 Scissor box 15.1.2 476 477NOTE: The only change is that SCISSOR_TEST and SCISSOR_BOX are extended 478to accommodate 16* copies. 479 480New Implementation Dependent State 481 482 Get Value Type Get Command Minimum Value Description Sec. 483 --------- ---- ----------- ------------- ------------------- ----- 484 MAX_VIEWPORT_DIMS (NOTE 1) 2 x Z+ GetFloatv See 2.16.1 Maximum viewport dimensions 12.5.1 485 MAX_VIEWPORTS_NV Z+ GetIntegerv 16 Maximum number of 12.5.1 486 active viewports 487 VIEWPORT_SUBPIXEL_BITS_NV Z+ GetIntegerv 0 Number of bits of sub-pixel 12.5.1 488 precision for viewport bounds 489 VIEWPORT_BOUNDS_RANGE_NV 2 x R GetFloatv (NOTE 2) Viewport bounds range [min,max] 12.5.1 490 LAYER_PROVOKING_VERTEX_NV Z_4 GetIntegerv -- (NOTE 3) vertex convention followed by 12.5.1 491 the gl_Layer GLSL variable 492 VIEWPORT_INDEX_PROVOKING_VERTEX_NV Z_4 GetIntegerv -- (NOTE 3) vertex convention followed by 12.5.1 493 the gl_ViewportIndex GLSL 494 variable 495 496NOTE 1: The recommended get command is changed from GetIntegerv to GetFloatv. 497NOTE 2: range for viewport bounds: 498 * On ES3.1-capable hardware the VIEWPORT_BOUNDS_RANGE_NV should be at least 499 [-32768, 32767]. 500NOTE 3: Valid values are: FIRST_VERTEX_CONVENTION_NV, 501LAST_VERTEX_CONVENTION_NV, UNDEFINED_VERTEX_NV. 502 503 504Interactions with EXT_draw_buffers_indexed 505 506 If EXT_draw_buffers_indexed is supported, EnableiNV, DisableiNV and 507 IsEnablediNV alias EnableiEXT, DisableiEXT and IsEnablediEXT, respectively. 508 509 510Issues 511 512 See issues section in ARB_viewport_array. 513 514 #1 What are the differences from ARB_viewport_array? 515 516 - OpenGL ES does not support the double datatype. The changed interfaces of 517 glDepthRangeArrayfvNV and DepthRangeIndexedfNV reflect that. 'float' is 518 being used instead of 'clampf', with additional constraints in the text 519 that the values will get clamped. 520 - The ability to access gl_ViewportIndex from the fragment shader was added 521 from ARB_fragment_layer_viewport. 522 523 524Revision History 525 526 Rev. Date Author Changes 527 ---- -------- -------- ----------------------------------------- 528 1 06/18/2014 mheyer Based on ARB_viewport_array, stripped for ES3.1 529 - replaced clampd with float for glDepthRangef 530 - instead of EnableIndexed and DisableIndexed, use 531 Enablei and Disablei 532 - PROVOKING_VERTEX_NV removed 533 2 07/24/2014 mheyer Minor edits. 534 3 08/10/2014 mheyer Edit for consistency. 535 4 09/04/2014 jhelferty Add viewport part of ARB_fragment_layer_viewport 536 as was done with layer in EXT_geometry_shader 537 5 10/24/2014 dkoch Cleanup for publishing. 538