1// Copyright (c) 2015-2018 Khronos Group. This work is licensed under a 2// Creative Commons Attribution 4.0 International License; see 3// http://creativecommons.org/licenses/by/4.0/ 4 5[[vertexpostproc]] 6= Fixed-Function Vertex Post-Processing 7 8After programmable vertex processing, the following fixed-function 9operations are applied to vertices of the resulting primitives: 10 11ifdef::VK_NV_viewport_swizzle[] 12 * Viewport swizzle (see <<vertexpostproc-viewport-swizzle,Viewport 13 Swizzle>>) 14endif::VK_NV_viewport_swizzle[] 15 * Flat shading (see <<vertexpostproc-flatshading>>). 16 * Primitive clipping, including client-defined half-spaces (see 17 <<vertexpostproc-clipping,Primitive Clipping>>). 18 * Shader output attribute clipping (see 19 <<vertexpostproc-clipping-shader-outputs,Clipping Shader Outputs>>). 20ifdef::VK_NV_clip_space_w_scaling[] 21 * Clip space W scaling (see <<vertexpostproc-viewportwscaling,Controlling 22 Viewport W Scaling>>). 23endif::VK_NV_clip_space_w_scaling[] 24 * Perspective division on clip coordinates (see 25 <<vertexpostproc-coord-transform,Coordinate Transformations>>). 26 * Viewport mapping, including depth range scaling (see 27 <<vertexpostproc-viewport,Controlling the Viewport>>). 28 * Front face determination for polygon primitives (see 29 <<primsrast-polygons-basic,Basic Polygon Rasterization>>). 30 31ifdef::editing-notes[] 32[NOTE] 33.editing-note 34==== 35TODO:Odd that this one link to a different chapter is in this list. 36==== 37endif::editing-notes[] 38 39Next, rasterization is performed on primitives as described in chapter 40<<primsrast,Rasterization>>. 41 42ifdef::VK_NV_viewport_swizzle[] 43[[vertexpostproc-viewport-swizzle]] 44== Viewport Swizzle 45 46[open,refpage='VkPipelineViewportSwizzleStateCreateInfoNV',desc='Structure specifying swizzle applied to primitive clip coordinates',type='structs'] 47-- 48 49Each primitive sent to a given viewport has a swizzle and optional: negation 50applied to its clip coordinates. 51The swizzle that is applied depends on the viewport index, and is controlled 52by the sname:VkPipelineViewportSwizzleStateCreateInfoNV pipeline state: 53 54include::../api/structs/VkPipelineViewportSwizzleStateCreateInfoNV.txt[] 55 56 * pname:sType is the type of this structure. 57 * pname:pNext is `NULL` or a pointer to an extension-specific structure. 58 * pname:flags is reserved for future use. 59 * pname:viewportCount is the number of viewport swizzles used by the 60 pipeline. 61 * pname:pViewportSwizzles is a pointer to an array of 62 slink:VkViewportSwizzleNV structures, defining the viewport swizzles. 63 64.Valid Usage 65**** 66 * [[VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215]] 67 pname:viewportCount must: match the pname:viewportCount set in 68 sname:VkPipelineViewportStateCreateInfo 69**** 70 71include::../validity/structs/VkPipelineViewportSwizzleStateCreateInfoNV.txt[] 72-- 73 74[open,refpage='VkPipelineViewportSwizzleStateCreateFlagsNV',desc='Reserved for future use',type='enums'] 75-- 76include::../api/flags/VkPipelineViewportSwizzleStateCreateFlagsNV.txt[] 77 78sname:VkPipelineViewportSwizzleStateCreateFlagsNV is a bitmask type for 79setting a mask, but is currently reserved for future use. 80-- 81 82The sname:VkPipelineViewportSwizzleStateCreateInfoNV state is set by adding 83an instance of this structure to the pname:pNext chain of an instance of the 84sname:VkPipelineViewportStateCreateInfo structure and setting the graphics 85pipeline state with flink:vkCreateGraphicsPipelines. 86 87Each viewport specified from 0 to pname:viewportCount - 1 has its x,y,z,w 88swizzle state set to the corresponding pname:x, pname:y, pname:z and pname:w 89in the slink:VkViewportSwizzleNV structure. 90Each component is of type elink:VkViewportCoordinateSwizzleNV, which 91determines the type of swizzle for that component. 92The value of pname:x computes the new x component of the position as: 93 94[source,c] 95--------------------------------------------------- 96if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV) x' = x; 97if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV) x' = -x; 98if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV) x' = y; 99if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV) x' = -y; 100if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV) x' = z; 101if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV) x' = -z; 102if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV) x' = w; 103if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV) x' = -w; 104--------------------------------------------------- 105 106Similar selections are performed for the pname:y, pname:z, and pname:w 107coordinates. 108This swizzling is applied before clipping and perspective divide. 109If the swizzle for an active viewport index is not specified, the swizzle 110for pname:x is ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, pname:y 111is ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, pname:z is 112ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV and pname:w is 113ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV. 114 115Viewport swizzle parameters are specified by setting the pname:pNext pointer 116of sname:VkGraphicsPipelineCreateInfo to point to an instance of 117sname:VkPipelineViewportSwizzleStateCreateInfoNV. 118slink:VkPipelineViewportSwizzleStateCreateInfoNV uses 119sname:VkViewportSwizzleNV to set the viewport swizzle parameters. 120 121[open,refpage='VkViewportSwizzleNV',desc='Structure specifying a viewport swizzle',type='structs'] 122-- 123 124The sname:VkViewportSwizzleNV structure is defined as: 125 126include::../api/structs/VkViewportSwizzleNV.txt[] 127 128 * pname:x is a elink:VkViewportCoordinateSwizzleNV value specifying the 129 swizzle operation to apply to the x component of the primitive 130 * pname:y is a elink:VkViewportCoordinateSwizzleNV value specifying the 131 swizzle operation to apply to the y component of the primitive 132 * pname:z is a elink:VkViewportCoordinateSwizzleNV value specifying the 133 swizzle operation to apply to the z component of the primitive 134 * pname:w is a elink:VkViewportCoordinateSwizzleNV value specifying the 135 swizzle operation to apply to the w component of the primitive 136 137include::../validity/structs/VkViewportSwizzleNV.txt[] 138-- 139 140[open,refpage='VkViewportCoordinateSwizzleNV',desc='Specify how a viewport coordinate is swizzled',type='enums'] 141-- 142 143Possible values of the elink:VkViewportSwizzleNV::pname:x, pname:y, pname:z, 144and pname:w members, specifying swizzling of the corresponding components of 145primitives, are: 146 147include::../api/enums/VkViewportCoordinateSwizzleNV.txt[] 148 149These values are described in detail in <<vertexpostproc-viewport-swizzle, 150Viewport Swizzle>>. 151 152-- 153 154endif::VK_NV_viewport_swizzle[] 155 156[[vertexpostproc-flatshading]] 157== Flat Shading 158 159_Flat shading_ a vertex output attribute means to assign all vertices of the 160primitive the same value for that output. 161 162The output values assigned are those of the _provoking vertex_ of the 163primitive. 164The provoking vertex depends on the primitive topology, and is generally the 165"`first`" vertex of the primitive. 166For primitives not processed by tessellation or geometry shaders, the 167provoking vertex is selected from the input vertices according to the 168following table. 169 170<<< 171 172[[provoking-vertex-selection]] 173.Provoking vertex selection 174[align="center",cols="75%,25%"] 175|==== 176| Primitive type of primitive [eq]#i# | Provoking vertex number 177| ename:VK_PRIMITIVE_TOPOLOGY_POINT_LIST | [eq]#i# 178| ename:VK_PRIMITIVE_TOPOLOGY_LINE_LIST | [eq]#2 i# 179| ename:VK_PRIMITIVE_TOPOLOGY_LINE_STRIP | [eq]#i# 180| ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST | [eq]#3 i# 181| ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP | [eq]#i# 182| ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN | [eq]#i {plus} 1# 183| ename:VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY | [eq]#4 i {plus} 1# 184| ename:VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY | [eq]#i {plus} 1# 185| ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY | [eq]#6 i# 186| ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY | [eq]#2 i# 187|==== 188 189.Caption 190**** 191The <<provoking-vertex-selection,Provoking vertex selection>> table defines 192the output values used for flat shading the i^th^ primitive generated by 193drawing commands with the indicated primitive type, derived from the 194corresponding values of the vertex whose index is shown in the table. 195Primitives and vertices are numbered starting from zero. 196**** 197 198Flat shading is applied to those vertex attributes that 199<<interfaces-iointerfaces-matching,match>> fragment input attributes which 200are decorated as code:Flat. 201 202If a geometry shader is active, the output primitive topology is either 203points, line strips, or triangle strips, and the selection of the provoking 204vertex behaves according to the corresponding row of the table. 205If a tessellation evaluation shader is active and a geometry shader is not 206active, the provoking vertex is undefined but must: be one of the vertices 207of the primitive. 208 209 210[[vertexpostproc-clipping]] 211== Primitive Clipping 212 213Primitives are culled against the _cull volume_ and then clipped to the 214_clip volume_. 215In clip coordinates, the _view volume_ is defined by: 216 217[latexmath] 218++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 219\begin{array}{c} 220-w_c \leq x_c \leq w_c \\ 221-w_c \leq y_c \leq w_c \\ 2220 \leq z_c \leq w_c 223\end{array} 224++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 225 226This view volume can: be further restricted by as many as 227sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined 228half-spaces. 229 230The cull volume is the intersection of up to 231sname:VkPhysicalDeviceLimits::pname:maxCullDistances client-defined 232half-spaces (if no client-defined cull half-spaces are enabled, culling 233against the cull volume is skipped). 234 235A shader must: write a single cull distance for each enabled cull half-space 236to elements of the code:CullDistance array. 237If the cull distance for any enabled cull half-space is negative for all of 238the vertices of the primitive under consideration, the primitive is 239discarded. 240Otherwise the primitive is clipped against the clip volume as defined below. 241 242The clip volume is the intersection of up to 243sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined 244half-spaces with the view volume (if no client-defined clip half-spaces are 245enabled, the clip volume is the view volume). 246 247A shader must: write a single clip distance for each enabled clip half-space 248to elements of the code:ClipDistance array. 249Clip half-space [eq]#i# is then given by the set of points satisfying the 250inequality 251 252 :: [eq]#c~i~(**P**) {geq} 0# 253 254where [eq]#c~i~(**P**)# is the clip distance [eq]#i# at point [eq]#**P**#. 255For point primitives, [eq]#c~i~(**P**)# is simply the clip distance for the 256vertex in question. 257For line and triangle primitives, per-vertex clip distances are interpolated 258using a weighted mean, with weights derived according to the algorithms 259described in sections <<primsrast-lines-basic,Basic Line Segment 260Rasterization>> and <<primsrast-polygons-basic,Basic Polygon 261Rasterization>>, using the perspective interpolation equations. 262 263The number of client-defined clip and cull half-spaces that are enabled is 264determined by the explicit size of the built-in arrays code:ClipDistance and 265code:CullDistance, respectively, declared as an output in the interface of 266the entry point of the final shader stage before clipping. 267 268Depth clamping is enabled or disabled via the pname:depthClampEnable enable 269of the sname:VkPipelineRasterizationStateCreateInfo structure. 270If depth clamping is enabled, the plane equation 271 272 :: [eq]#0 {leq} z~c~ {leq} w~c~# 273 274(see the clip volume definition above) is ignored by view volume clipping 275(effectively, there is no near or far plane clipping). 276 277If the primitive under consideration is a point or line segment, then 278clipping passes it unchanged if its vertices lie entirely within the clip 279volume. 280 281ifndef::VK_VERSION_1_1,VK_KHR_maintenance2[] 282If a point's vertex lies outside of the clip volume, the entire primitive 283may: be discarded. 284endif::VK_VERSION_1_1,VK_KHR_maintenance2[] 285 286ifdef::VK_VERSION_1_1,VK_KHR_maintenance2[] 287 288[open,refpage='VkPointClippingBehavior',desc='Enum specifying the point clipping behaviour',type='enums'] 289-- 290 291Possible values of 292slink:VkPhysicalDevicePointClippingProperties::pname:pointClippingBehavior, 293specifying clipping behavior of a point primitive whose vertex lies outside 294the clip volume, are: 295 296include::../api/enums/VkPointClippingBehavior.txt[] 297 298ifdef::VK_KHR_maintenance2[] 299or the equivalent 300 301include::../api/enums/VkPointClippingBehaviorKHR.txt[] 302endif::VK_KHR_maintenance2[] 303 304 * ename:VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES specifies that the 305 primitive is discarded if the vertex lies outside any clip plane, 306 including the planes bounding the view volume. 307 * ename:VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY specifies that 308 the primitive is discarded only if the vertex lies outside any user clip 309 plane. 310 311-- 312 313endif::VK_VERSION_1_1,VK_KHR_maintenance2[] 314 315If either of a line segment's vertices lie outside of the clip volume, the 316line segment may: be clipped, with new vertex coordinates computed for each 317vertex that lies outside the clip volume. 318A clipped line segment endpoint lies on both the original line segment and 319the boundary of the clip volume. 320 321This clipping produces a value, [eq]#0 {leq} t {leq} 1#, for each clipped 322vertex. 323If the coordinates of a clipped vertex are [eq]#**P**# and the original 324vertices`' coordinates are [eq]#**P**~1~# and [eq]#**P**~2~#, then [eq]#t# 325is given by 326 327 :: [eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#. 328 329ifdef::editing-notes[] 330[NOTE] 331.editing-note 332==== 333This is weird - it gives **P**, not t. 334==== 335endif::editing-notes[] 336 337[eq]#t# is used to clip vertex output attributes as described in 338<<vertexpostproc-clipping-shader-outputs,Clipping Shader Outputs>>. 339 340If the primitive is a polygon, it passes unchanged if every one of its edges 341lie entirely inside the clip volume, and it is discarded if every one of its 342edges lie entirely outside the clip volume. 343If the edges of the polygon intersect the boundary of the clip volume, the 344intersecting edges are reconnected by new edges that lie along the boundary 345of the clip volume - in some cases requiring the introduction of new 346vertices into a polygon. 347 348If a polygon intersects an edge of the clip volume's boundary, the clipped 349polygon must: include a point on this boundary edge. 350 351Primitives rendered with user-defined half-spaces must: satisfy a 352complementarity criterion. 353Suppose a series of primitives is drawn where each vertex [eq]#i# has a 354single specified clip distance [eq]#d~i~# (or a number of similarly 355specified clip distances, if multiple half-spaces are enabled). 356Next, suppose that the same series of primitives are drawn again with each 357such clip distance replaced by [eq]#-d~i~# (and the graphics pipeline is 358otherwise the same). 359In this case, primitives must: not be missing any pixels, and pixels must: 360not be drawn twice in regions where those primitives are cut by the clip 361planes. 362 363 364[[vertexpostproc-clipping-shader-outputs]] 365== Clipping Shader Outputs 366 367Next, vertex output attributes are clipped. 368The output values associated with a vertex that lies within the clip volume 369are unaffected by clipping. 370If a primitive is clipped, however, the output values assigned to vertices 371produced by clipping are clipped. 372 373Let the output values assigned to the two vertices [eq]#**P**~1~# and 374[eq]#**P**~2~# of an unclipped edge be [eq]#**c**~1~# and [eq]#**c**~2~#. 375The value of [eq]#t# (see <<vertexpostproc-clipping,Primitive Clipping>>) 376for a clipped point [eq]#**P**# is used to obtain the output value 377associated with [eq]#**P**# as 378 379 :: [eq]#**c** = t **c**~1~ {plus} (1-t) **c**~2~#. 380 381(Multiplying an output value by a scalar means multiplying each of _x_, _y_, 382_z_, and _w_ by the scalar.) 383 384Since this computation is performed in clip space before division by 385[eq]#w~c~#, clipped output values are perspective-correct. 386 387Polygon clipping creates a clipped vertex along an edge of the clip volume's 388boundary. 389This situation is handled by noting that polygon clipping proceeds by 390clipping against one half-space at a time. 391Output value clipping is done in the same way, so that clipped points always 392occur at the intersection of polygon edges (possibly already clipped) with 393the clip volume's boundary. 394 395For vertex output attributes whose matching fragment input attributes are 396decorated with code:NoPerspective, the value of [eq]#t# used to obtain the 397output value associated with [eq]#**P**# will be adjusted to produce results 398that vary linearly in framebuffer space. 399 400Output attributes of integer or unsigned integer type must: always be flat 401shaded. 402Flat shaded attributes are constant over the primitive being rasterized (see 403<<primsrast-lines-basic,Basic Line Segment Rasterization>> and 404<<primsrast-polygons-basic,Basic Polygon Rasterization>>), and no 405interpolation is performed. 406The output value [eq]#**c**# is taken from either [eq]#**c**~1~# or 407[eq]#**c**~2~#, since flat shading has already occurred and the two values 408are identical. 409 410ifdef::VK_NV_clip_space_w_scaling[] 411include::VK_NV_clip_space_w_scaling/vertexpostproc.txt[] 412endif::VK_NV_clip_space_w_scaling[] 413 414[[vertexpostproc-coord-transform]] 415== Coordinate Transformations 416 417_Clip coordinates_ for a vertex result from shader execution, which yields a 418vertex coordinate code:Position. 419 420Perspective division on clip coordinates yields _normalized device 421coordinates_, followed by a _viewport_ transformation (see 422<<vertexpostproc-viewport,Controlling the Viewport>>) to convert these 423coordinates into _framebuffer coordinates_. 424 425If a vertex in clip coordinates has a position given by 426 427[latexmath] 428++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 429\left(\begin{array}{c} 430x_c \\ 431y_c \\ 432z_c \\ 433w_c 434\end{array}\right) 435++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 436 437then the vertex's normalized device coordinates are 438[latexmath] 439++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 440\left( 441 \begin{array}{c} 442 x_d \\ 443 y_d \\ 444 z_d 445 \end{array} 446\right) = 447\left( 448 \begin{array}{c} 449 \frac{x_c}{w_c} \\ 450 \frac{y_c}{w_c} \\ 451 \frac{z_c}{w_c} 452 \end{array} 453\right) 454++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 455 456 457[[vertexpostproc-viewport]] 458== Controlling the Viewport 459 460The viewport transformation is determined by the selected viewport's width 461and height in pixels, [eq]#p~x~# and [eq]#p~y~#, respectively, and its 462center [eq]#(o~x~, o~y~)# (also in pixels), as well as its depth range min 463and max determining a depth range scale value [eq]#p~z~# and a depth range 464bias value [eq]#o~z~# (defined below). 465The vertex's framebuffer coordinates [eq]#(x~f~, y~f~, z~f~)# are given by 466 467 :: [eq]#x~f~ = (p~x~ / 2) x~d~ {plus} o~x~# 468 :: [eq]#y~f~ = (p~y~ / 2) y~d~ {plus} o~y~# 469 :: [eq]#z~f~ = p~z~ {times} z~d~ {plus} o~z~# 470 471Multiple viewports are available, numbered zero up to 472sname:VkPhysicalDeviceLimits::pname:maxViewports minus one. 473The number of viewports used by a pipeline is controlled by the 474pname:viewportCount member of the sname:VkPipelineViewportStateCreateInfo 475structure used in pipeline creation. 476 477[open,refpage='VkPipelineViewportStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline viewport state',type='structs'] 478-- 479 480The sname:VkPipelineViewportStateCreateInfo structure is defined as: 481 482include::../api/structs/VkPipelineViewportStateCreateInfo.txt[] 483 484 * pname:sType is the type of this structure. 485 * pname:pNext is `NULL` or a pointer to an extension-specific structure. 486 * pname:flags is reserved for future use. 487 * pname:viewportCount is the number of viewports used by the pipeline. 488 * pname:pViewports is a pointer to an array of slink:VkViewport 489 structures, defining the viewport transforms. 490 If the viewport state is dynamic, this member is ignored. 491 * pname:scissorCount is the number of <<fragops-scissor,scissors>> and 492 must: match the number of viewports. 493 * pname:pScissors is a pointer to an array of slink:VkRect2D structures 494 which define the rectangular bounds of the scissor for the corresponding 495 viewport. 496 If the scissor state is dynamic, this member is ignored. 497 498.Valid Usage 499**** 500 * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216]] 501 If the <<features-features-multiViewport,multiple viewports>> feature is 502 not enabled, pname:viewportCount must: be `1` 503 * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217]] 504 If the <<features-features-multiViewport,multiple viewports>> feature is 505 not enabled, pname:scissorCount must: be `1` 506 * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218]] 507 pname:viewportCount must: be between `1` and 508 sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive 509 * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219]] 510 pname:scissorCount must: be between `1` and 511 sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive 512 * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220]] 513 pname:scissorCount and pname:viewportCount must: be identical 514ifdef::VK_NV_clip_space_w_scaling[] 515 * [[VUID-VkPipelineViewportStateCreateInfo-viewportWScalingEnable-01726]] 516 If the pname:viewportWScalingEnable member of a 517 slink:VkPipelineViewportWScalingStateCreateInfoNV structure chained to 518 the pname:pNext chain is ename:VK_TRUE, the pname:viewportCount member 519 of the slink:VkPipelineViewportWScalingStateCreateInfoNV structure must: 520 be equal to pname:viewportCount 521endif::VK_NV_clip_space_w_scaling[] 522**** 523 524include::../validity/structs/VkPipelineViewportStateCreateInfo.txt[] 525-- 526 527[open,refpage='VkPipelineViewportStateCreateFlags',desc='Reserved for future use',type='enums'] 528-- 529include::../api/flags/VkPipelineViewportStateCreateFlags.txt[] 530 531sname:VkPipelineViewportStateCreateFlags is a bitmask type for setting a 532mask, but is currently reserved for future use. 533-- 534 535ifndef::VK_NV_viewport_array2+VK_EXT_shader_viewport_index_layer[] 536If a geometry shader is active and has an output variable decorated with 537code:ViewportIndex, the viewport transformation uses the viewport 538corresponding to the value assigned to code:ViewportIndex taken from an 539implementation-dependent vertex of each primitive. 540If code:ViewportIndex is outside the range zero to pname:viewportCount minus 541one for a primitive, or if the geometry shader did not assign a value to 542code:ViewportIndex for all vertices of a primitive due to flow control, the 543results of the viewport transformation of the vertices of such primitives 544are undefined. 545If no geometry shader is active, or if the geometry shader does not have an 546output decorated with code:ViewportIndex, the viewport numbered zero is used 547by the viewport transformation. 548endif::VK_NV_viewport_array2+VK_EXT_shader_viewport_index_layer[] 549 550ifdef::VK_NV_viewport_array2,VK_EXT_shader_viewport_index_layer[] 551ifdef::VK_NV_viewport_array2[] 552A _vertex processing stage_ may direct each primitive to zero or more 553viewports. 554The destination viewports for a primitive are selected by the last active 555vertex processing stage that has an output variable decorated with 556code:ViewportIndex (selecting a single viewport) or code:ViewportMaskNV 557(selecting multiple viewports). 558The viewport transform uses the viewport corresponding to either the value 559assigned to code:ViewportIndex or one of the bits set in 560code:ViewportMaskNV, and taken from an implementation-dependent vertex of 561each primitive. 562If code:ViewportIndex or any of the bits in code:ViewportMaskNV are outside 563the range zero to pname:viewportCount minus one for a primitive, or if the 564last active vertex processing stage did not assign a value to either 565code:ViewportIndex or code:ViewportMaskNV for all vertices of a primitive 566due to flow control, the results of the viewport transformation of the 567vertices of such primitives are undefined. 568If the last vertex processing stage does not have an output decorated with 569code:ViewportIndex or code:ViewportMaskNV, the viewport numbered zero is 570used by the viewport transformation. 571endif::VK_NV_viewport_array2[] 572ifndef::VK_NV_viewport_array2[] 573ifdef::VK_EXT_shader_viewport_index_layer[] 574A _vertex processing stage_ can: direct each primitive to one of several 575viewports. 576The destination viewport for a primitive is selected by the last active 577vertex processing stage that has an output variable decorated with 578code:ViewportIndex. 579The viewport transform uses the viewport corresponding to the value assigned 580to code:ViewportIndex taken from an implementation-dependent vertex of each 581primitive. 582If code:ViewportIndex is outside the range zero to pname:viewportCount minus 583one for a primitive, or if the last active vertex processing stage did not 584assign a value to code:ViewportIndex for all vertices of a primitive due to 585flow control, the results of the viewport transformation of the vertices of 586such primitives are undefined. 587If the last vertex processing stage does not have an output decorated with 588code:ViewportIndex, the viewport numbered zero is used by the viewport 589transformation. 590endif::VK_EXT_shader_viewport_index_layer[] 591endif::VK_NV_viewport_array2[] 592endif::VK_NV_viewport_array2,VK_EXT_shader_viewport_index_layer[] 593 594A single vertex can: be used in more than one individual primitive, in 595primitives such as ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP. 596In this case, the viewport transformation is applied separately for each 597primitive. 598 599[open,refpage='vkCmdSetViewport',desc='Set the viewport on a command buffer',type='protos'] 600-- 601 602If the bound pipeline state object was not created with the 603ename:VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled, viewport 604transformation parameters are specified using the pname:pViewports member of 605sname:VkPipelineViewportStateCreateInfo in the pipeline state object. 606If the pipeline state object was created with the 607ename:VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled, the viewport 608transformation parameters are dynamically set and changed with the command: 609 610include::../api/protos/vkCmdSetViewport.txt[] 611 612 * pname:commandBuffer is the command buffer into which the command will be 613 recorded. 614 * pname:firstViewport is the index of the first viewport whose parameters 615 are updated by the command. 616 * pname:viewportCount is the number of viewports whose parameters are 617 updated by the command. 618 * pname:pViewports is a pointer to an array of slink:VkViewport structures 619 specifying viewport parameters. 620 621The viewport parameters taken from element [eq]#i# of pname:pViewports 622replace the current state for the viewport index [eq]#pname:firstViewport 623{plus} i#, for [eq]#i# in [eq]#[0, pname:viewportCount)#. 624 625.Valid Usage 626**** 627 * [[VUID-vkCmdSetViewport-None-01221]] 628 The bound graphics pipeline must: have been created with the 629 ename:VK_DYNAMIC_STATE_VIEWPORT dynamic state enabled 630 * [[VUID-vkCmdSetViewport-firstViewport-01222]] 631 pname:firstViewport must: be less than 632 sname:VkPhysicalDeviceLimits::pname:maxViewports 633 * [[VUID-vkCmdSetViewport-firstViewport-01223]] 634 The sum of pname:firstViewport and pname:viewportCount must: be between 635 `1` and sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive 636 * [[VUID-vkCmdSetViewport-firstViewport-01224]] 637 If the <<features-features-multiViewport,multiple viewports>> feature is 638 not enabled, pname:firstViewport must: be `0` 639 * [[VUID-vkCmdSetViewport-viewportCount-01225]] 640 If the <<features-features-multiViewport,multiple viewports>> feature is 641 not enabled, pname:viewportCount must: be `1` 642**** 643 644include::../validity/protos/vkCmdSetViewport.txt[] 645-- 646 647Both slink:VkPipelineViewportStateCreateInfo and flink:vkCmdSetViewport use 648sname:VkViewport to set the viewport transformation parameters. 649 650[open,refpage='VkViewport',desc='Structure specifying a viewport',type='structs'] 651-- 652 653The sname:VkViewport structure is defined as: 654 655include::../api/structs/VkViewport.txt[] 656 657 * pname:x and pname:y are the viewport's upper left corner [eq]#(x,y)#. 658 * pname:width and pname:height are the viewport's width and height, 659 respectively. 660 * pname:minDepth and pname:maxDepth are the depth range for the viewport. 661 It is valid for pname:minDepth to be greater than or equal to 662 pname:maxDepth. 663 664The framebuffer depth coordinate [eq]#pname:z~f~# may: be represented using 665either a fixed-point or floating-point representation. 666However, a floating-point representation must: be used if the depth/stencil 667attachment has a floating-point depth component. 668If an [eq]#m#-bit fixed-point representation is used, we assume that it 669represents each value latexmath:[\frac{k}{2^m - 1}], where [eq]#k {elem} { 6700, 1, ..., 2^m^-1 }#, as [eq]#k# (e.g. 1.0 is represented in binary as a 671string of all ones). 672 673The viewport parameters shown in the above equations are found from these 674values as 675 676 :: [eq]#o~x~ = pname:x {plus} pname:width / 2# 677 :: [eq]#o~y~ = pname:y {plus} pname:height / 2# 678 :: [eq]#o~z~ = pname:minDepth# 679 :: [eq]#p~x~ = pname:width# 680 :: [eq]#p~y~ = pname:height# 681 :: [eq]#p~z~ = pname:maxDepth - pname:minDepth#. 682 683ifdef::VK_VERSION_1_1,VK_KHR_maintenance1[] 684The application can: specify a negative term for pname:height, which has the 685effect of negating the y coordinate in clip space before performing the 686transform. 687When using a negative pname:height, the application should: also adjust the 688pname:y value to point to the lower left corner of the viewport instead of 689the upper left corner. 690Using the negative pname:height allows the application to avoid having to 691negate the y component of the code:Position output from the last vertex 692processing stage in shaders that also target other graphics APIs. 693endif::VK_VERSION_1_1,VK_KHR_maintenance1[] 694 695The width and height of the <<features-limits-maxViewportDimensions, 696implementation-dependent maximum viewport dimensions>> must: be greater than 697or equal to the width and height of the largest image which can: be created 698and attached to a framebuffer. 699 700The floating-point viewport bounds are represented with an 701<<features-limits-viewportSubPixelBits,implementation-dependent precision>>. 702 703.Valid Usage 704**** 705 * [[VUID-VkViewport-width-01770]] 706 pname:width must: be greater than `0.0` 707 * [[VUID-VkViewport-width-01771]] 708 pname:width must: be less than or equal to 709 sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[0] 710ifndef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[] 711 * [[VUID-VkViewport-height-01772]] 712 pname:height must: be greater than `0.0` 713endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[] 714 * [[VUID-VkViewport-height-01773]] 715 The absolute value of pname:height must: be less than or equal to 716 sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[1] 717 * [[VUID-VkViewport-x-01774]] 718 pname:x must: be greater than or equal to pname:viewportBoundsRange[0] 719 * [[VUID-VkViewport-x-01232]] 720 [eq]#(pname:x {plus} pname:width)# must: be less than or equal to 721 pname:viewportBoundsRange[1] 722 * [[VUID-VkViewport-y-01775]] 723 pname:y must: be greater than or equal to pname:viewportBoundsRange[0] 724ifdef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[] 725 * [[VUID-VkViewport-y-01776]] 726 pname:y must: be less than or equal to pname:viewportBoundsRange[1] 727 * [[VUID-VkViewport-y-01777]] 728 [eq]#(pname:y {plus} pname:height)# must: be greater than or equal to 729 pname:viewportBoundsRange[0] 730endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[] 731 * [[VUID-VkViewport-y-01233]] 732 [eq]#(pname:y {plus} pname:height)# must: be less than or equal to 733 pname:viewportBoundsRange[1] 734ifdef::VK_EXT_depth_range_unrestricted[] 735 * [[VUID-VkViewport-minDepth-01234]] 736 Unless `<<VK_EXT_depth_range_unrestricted>>` extension is enabled 737 pname:minDepth must: be between `0.0` and `1.0`, inclusive 738endif::VK_EXT_depth_range_unrestricted[] 739ifndef::VK_EXT_depth_range_unrestricted[] 740 * [[VUID-VkViewport-minDepth-01234]] 741 pname:minDepth must: be between `0.0` and `1.0`, inclusive 742endif::VK_EXT_depth_range_unrestricted[] 743ifdef::VK_EXT_depth_range_unrestricted[] 744 * [[VUID-VkViewport-maxDepth-01235]] 745 Unless `<<VK_EXT_depth_range_unrestricted>>` extension is enabled 746 pname:maxDepth must: be between `0.0` and `1.0`, inclusive 747endif::VK_EXT_depth_range_unrestricted[] 748ifndef::VK_EXT_depth_range_unrestricted[] 749 * [[VUID-VkViewport-maxDepth-01235]] 750 pname:maxDepth must: be between `0.0` and `1.0`, inclusive 751endif::VK_EXT_depth_range_unrestricted[] 752**** 753 754include::../validity/structs/VkViewport.txt[] 755-- 756