• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015-2021 The Khronos Group, Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5[[vertexpostproc]]
6= Fixed-Function Vertex Post-Processing
7
8After <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
9stages>>, the following fixed-function operations are applied to vertices of
10the resulting primitives:
11
12ifdef::VK_EXT_transform_feedback[]
13  * Transform feedback (see <<vertexpostproc-transform-feedback,Transform
14    Feedback>>)
15endif::VK_EXT_transform_feedback[]
16ifdef::VK_NV_viewport_swizzle[]
17  * Viewport swizzle (see <<vertexpostproc-viewport-swizzle,Viewport
18    Swizzle>>)
19endif::VK_NV_viewport_swizzle[]
20  * Flat shading (see <<vertexpostproc-flatshading>>).
21  * Primitive clipping, including client-defined half-spaces (see
22    <<vertexpostproc-clipping,Primitive Clipping>>).
23  * Shader output attribute clipping (see
24    <<vertexpostproc-clipping-shader-outputs,Clipping Shader Outputs>>).
25ifdef::VK_NV_clip_space_w_scaling[]
26  * Clip space W scaling (see <<vertexpostproc-viewportwscaling,Controlling
27    Viewport W Scaling>>).
28endif::VK_NV_clip_space_w_scaling[]
29  * Perspective division on clip coordinates (see
30    <<vertexpostproc-coord-transform,Coordinate Transformations>>).
31  * Viewport mapping, including depth range scaling (see
32    <<vertexpostproc-viewport,Controlling the Viewport>>).
33  * Front face determination for polygon primitives (see
34    <<primsrast-polygons-basic,Basic Polygon Rasterization>>).
35
36ifdef::editing-notes[]
37[NOTE]
38.editing-note
39====
40TODO:Odd that this one link to a different chapter is in this list.
41====
42endif::editing-notes[]
43
44Next, rasterization is performed on primitives as described in chapter
45<<primsrast,Rasterization>>.
46
47
48ifdef::VK_EXT_transform_feedback[]
49[[vertexpostproc-transform-feedback]]
50== Transform Feedback
51
52Before any other fixed-function vertex post-processing, vertex outputs from
53the last shader in the
54<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
55stage>> can: be written out to one or more transform feedback buffers bound
56to the command buffer.
57To capture vertex outputs the last
58<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
59stage>> shader must: be declared with the code:Xfb execution mode.
60Outputs decorated with code:XfbBuffer will be written out to the
61corresponding transform feedback buffers bound to the command buffer when
62transform feedback is active.
63Transform feedback buffers are bound to the command buffer by using
64flink:vkCmdBindTransformFeedbackBuffersEXT.
65Transform feedback is made active by calling
66flink:vkCmdBeginTransformFeedbackEXT and made inactive by calling
67flink:vkCmdEndTransformFeedbackEXT.
68After vertex data is written it is possible to use
69flink:vkCmdDrawIndirectByteCountEXT to start a new draw where the
70pname:vertexCount is derived from the number of bytes written by a previous
71transform feedback.
72
73When an individual point, line, or triangle primitive reaches the transform
74feedback stage while transform feedback is active, the values of the
75specified output variables are assembled into primitives and appended to the
76bound transform feedback buffers.
77After activating transform feedback, the values of the first assembled
78primitive are written at the starting offsets of the bound transform
79feedback buffers, and subsequent primitives are appended to the buffer.
80If the optional pname:pCounterBuffers and pname:pCounterBufferOffsets
81parameters are specified, the starting points within the transform feedback
82buffers are adjusted so data is appended to the previously written values
83indicated by the value stored by the implementation in the counter buffer.
84
85For multi-vertex primitives, all values for a given vertex are written
86before writing values for any other vertex.
87ifdef::VK_EXT_provoking_vertex[]
88When
89<<features-transformFeedbackPreservesProvokingVertex,transformFeedbackPreservesProvokingVertex>>
90is not enabled, implementations
91endif::VK_EXT_provoking_vertex[]
92ifndef::VK_EXT_provoking_vertex[]
93Implementations
94endif::VK_EXT_provoking_vertex[]
95may: write out any vertex within the primitive first, but all subsequent
96vertices for that primitive must: be written out in a consistent winding
97order defined as follows:
98
99  * If neither <<geometry,geometry>> or <<tessellation,tessellation
100    shading>> is active, vertices within a primitive are appended according
101    to the winding order described by the <<drawing-primitive-topologies,
102    primitive topology>> defined by the
103    slink:VkPipelineInputAssemblyStateCreateInfo:pname:topology used to
104    execute the <<drawing,drawing command>>.
105  * If <<geometry,geometry shading>> is active, vertices within a primitive
106    are appended according to the winding order described by the
107    <<drawing-primitive-topologies, primitive topology>> defined by the
108    <<drawing-point-lists, code:OutputPoints>>, <<drawing-line-strips,
109    code:OutputLineStrips>>, or <<drawing-triangle-strips,
110    code:OutputTriangleStrips>> execution mode.
111  * If <<tessellation,tessellation shading>> is active but
112    <<geometry,geometry shading>> is not, vertices within a primitive are
113    appended according to the winding order defined by
114    <<tessellation-triangle-tessellation, triangle tessellation>>,
115    <<tessellation-quad-tessellation, quad tessellation>>, and
116    <<tessellation-isoline-tessellation, isoline tessellation>>.
117
118ifdef::VK_EXT_provoking_vertex[]
119When
120<<features-transformFeedbackPreservesProvokingVertex,transformFeedbackPreservesProvokingVertex>>
121is enabled, then in addition to writing vertices with a consistent winding
122order, the vertex order must: preserve the <<vertexpostproc-flatshading,
123provoking vertex>> of each primitive:
124
125  * When the
126    <<VkPipelineRasterizationProvokingVertexStateCreateInfoEXT,pipeline's
127    provoking vertex mode>> is
128    ename:VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the primitive's
129    provoking vertex must be the first vertex written.
130  * When the
131    <<VkPipelineRasterizationProvokingVertexStateCreateInfoEXT,pipeline's
132    provoking vertex mode>> is
133    ename:VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the primitive's
134    provoking vertex must be the last vertex written.
135
136If
137<<limits-transformFeedbackPreservesTriangleFanProvokingVertex,pname:transformFeedbackPreservesTriangleFanProvokingVertex>>
138is ename:VK_FALSE, neither <<geometry,geometry>> nor
139<<tessellation,tessellation>> shading is active, and the
140<<drawing-primitive-topologies,primitive topology>> is
141ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, then the first vertex written from
142each primitive is implementation-defined even when
143<<features-transformFeedbackPreservesProvokingVertex,transformFeedbackPreservesProvokingVertex>>
144is enabled.
145
146endif::VK_EXT_provoking_vertex[]
147
148When capturing vertices, the stride associated with each transform feedback
149buffer, as indicated by the code:XfbStride decoration, indicates the number
150of bytes of storage reserved for each vertex in the transform feedback
151buffer.
152For every vertex captured, each output attribute with a code:Offset
153decoration will be written to the storage reserved for the vertex at the
154associated transform feedback buffer.
155When writing output variables that are arrays or structures, individual
156array elements or structure members are written tightly packed in order.
157For vector types, individual components are written in order.
158For matrix types, outputs are written as an array of column vectors.
159
160If any component of an output with an assigned transform feedback offset was
161not written to by its shader, the value recorded for that component is
162undefined:.
163All components of an output variable must: be written at an offset aligned
164to the size of the component.
165The size of each component of an output variable must: be at least 32-bits.
166When capturing a vertex, any portion of the reserved storage not associated
167with an output variable with an assigned transform feedback offset will be
168unmodified.
169
170When transform feedback is inactive, no vertices are recorded.
171If there is a valid counter buffer handle and counter buffer offset in the
172pname:pCounterBuffers and pname:pCounterBufferOffsets arrays, writes to the
173corresponding transform feedback buffer will start at the byte offset
174represented by the value stored in the counter buffer location.
175
176Individual lines or triangles of a strip or fan primitive will be extracted
177and recorded separately.
178Incomplete primitives are not recorded.
179
180When using a geometry shader that emits vertices to multiple vertex streams,
181a primitive will be assembled and output for each stream when there are
182enough vertices emitted for the output primitive type.
183All outputs assigned to a given transform feedback buffer are required to
184come from a single vertex stream.
185
186The sizes of the transform feedback buffers are defined by the
187flink:vkCmdBindTransformFeedbackBuffersEXT pname:pSizes parameter for each
188of the bound buffers, or the size of the bound buffer, whichever is the
189lesser.
190If there is less space remaining in any of the transform feedback buffers
191than the size of all of the vertex data for that primitive based on the
192code:XfbStride for that code:XfbBuffer then no vertex data of that primitive
193is recorded in any transform feedback buffer, and the value for the number
194of primitives written in the corresponding
195ename:VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT query for all transform
196feedback buffers is no longer incremented.
197
198Any outputs made to a code:XfbBuffer that is not bound to a transform
199feedback buffer is ignored.
200
201[open,refpage='vkCmdBindTransformFeedbackBuffersEXT',desc='Bind transform feedback buffers to a command buffer',type='protos']
202--
203To bind transform feedback buffers to a command buffer for use in subsequent
204drawing commands, call:
205
206include::{generated}/api/protos/vkCmdBindTransformFeedbackBuffersEXT.txt[]
207
208  * pname:commandBuffer is the command buffer into which the command is
209    recorded.
210  * pname:firstBinding is the index of the first transform feedback binding
211    whose state is updated by the command.
212  * pname:bindingCount is the number of transform feedback bindings whose
213    state is updated by the command.
214  * pname:pBuffers is a pointer to an array of buffer handles.
215  * pname:pOffsets is a pointer to an array of buffer offsets.
216  * pname:pSizes is `NULL` or a pointer to an array of basetype:VkDeviceSize
217    buffer sizes, specifying the maximum number of bytes to capture to the
218    corresponding transform feedback buffer.
219    If pname:pSizes is `NULL`, or the value of the pname:pSizes array
220    element is ename:VK_WHOLE_SIZE, then the maximum number of bytes
221    captured will be the size of the corresponding buffer minus the buffer
222    offset.
223
224The values taken from elements [eq]#i# of pname:pBuffers, pname:pOffsets and
225pname:pSizes replace the current state for the transform feedback binding
226[eq]#pname:firstBinding {plus} i#, for [eq]#i# in [eq]#[0,
227pname:bindingCount)#.
228The transform feedback binding is updated to start at the offset indicated
229by pname:pOffsets[i] from the start of the buffer pname:pBuffers[i].
230
231.Valid Usage
232****
233  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-transformFeedback-02355]]
234    sname:VkPhysicalDeviceTransformFeedbackFeaturesEXT::pname:transformFeedback
235    must: be enabled
236  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-firstBinding-02356]]
237    pname:firstBinding must: be less than
238    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
239  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-firstBinding-02357]]
240    The sum of pname:firstBinding and pname:bindingCount must: be less than
241    or equal to
242    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
243  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pOffsets-02358]]
244    All elements of pname:pOffsets must: be less than the size of the
245    corresponding element in pname:pBuffers
246  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pOffsets-02359]]
247    All elements of pname:pOffsets must: be a multiple of 4
248  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pBuffers-02360]]
249    All elements of pname:pBuffers must: have been created with the
250    ename:VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT flag
251  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pSize-02361]]
252    If the optional pname:pSize array is specified, each element of
253    pname:pSizes must: either be ename:VK_WHOLE_SIZE, or be less than or
254    equal to
255    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBufferSize
256  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pSizes-02362]]
257    All elements of pname:pSizes must: be either ename:VK_WHOLE_SIZE, or
258    less than or equal to the size of the corresponding buffer in
259    pname:pBuffers
260  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pOffsets-02363]]
261    All elements of pname:pOffsets plus pname:pSizes, where the
262    pname:pSizes, element is not ename:VK_WHOLE_SIZE, must: be less than or
263    equal to the size of the corresponding buffer in pname:pBuffers
264  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-pBuffers-02364]]
265    Each element of pname:pBuffers that is non-sparse must: be bound
266    completely and contiguously to a single sname:VkDeviceMemory object
267  * [[VUID-vkCmdBindTransformFeedbackBuffersEXT-None-02365]]
268    Transform feedback must: not be active when the
269    fname:vkCmdBindTransformFeedbackBuffersEXT command is recorded
270****
271
272include::{generated}/validity/protos/vkCmdBindTransformFeedbackBuffersEXT.txt[]
273--
274
275[open,refpage='vkCmdBeginTransformFeedbackEXT',desc='Make transform feedback active in the command buffer',type='protos']
276--
277Transform feedback for specific transform feedback buffers is made active by
278calling:
279
280include::{generated}/api/protos/vkCmdBeginTransformFeedbackEXT.txt[]
281
282  * pname:commandBuffer is the command buffer into which the command is
283    recorded.
284  * pname:firstCounterBuffer is the index of the first transform feedback
285    buffer corresponding to pname:pCounterBuffers[0] and
286    pname:pCounterBufferOffsets[0].
287  * pname:counterBufferCount is the size of the pname:pCounterBuffers and
288    pname:pCounterBufferOffsets arrays.
289  * pname:pCounterBuffers is `NULL` or a pointer to an array of
290    slink:VkBuffer handles to counter buffers.
291    Each buffer contains a 4 byte integer value representing the byte offset
292    from the start of the corresponding transform feedback buffer from where
293    to start capturing vertex data.
294    If the byte offset stored to the counter buffer location was done using
295    flink:vkCmdEndTransformFeedbackEXT it can be used to resume transform
296    feedback from the previous location.
297    If pname:pCounterBuffers is `NULL`, then transform feedback will start
298    capturing vertex data to byte offset zero in all bound transform
299    feedback buffers.
300    For each element of pname:pCounterBuffers that is dlink:VK_NULL_HANDLE,
301    transform feedback will start capturing vertex data to byte zero in the
302    corresponding bound transform feedback buffer.
303  * pname:pCounterBufferOffsets is `NULL` or a pointer to an array of
304    basetype:VkDeviceSize values specifying offsets within each of the
305    pname:pCounterBuffers where the counter values were previously written.
306    The location in each counter buffer at these offsets must: be large
307    enough to contain 4 bytes of data.
308    This data is the number of bytes captured by the previous transform
309    feedback to this buffer.
310    If pname:pCounterBufferOffsets is `NULL`, then it is assumed the offsets
311    are zero.
312
313The active transform feedback buffers will capture primitives emitted from
314the corresponding code:XfbBuffer in the bound graphics pipeline.
315Any code:XfbBuffer emitted that does not output to an active transform
316feedback buffer will not be captured.
317
318.Valid Usage
319****
320  * [[VUID-vkCmdBeginTransformFeedbackEXT-transformFeedback-02366]]
321    sname:VkPhysicalDeviceTransformFeedbackFeaturesEXT::pname:transformFeedback
322    must: be enabled
323  * [[VUID-vkCmdBeginTransformFeedbackEXT-None-02367]]
324    Transform feedback must: not be active
325  * [[VUID-vkCmdBeginTransformFeedbackEXT-firstCounterBuffer-02368]]
326    pname:firstCounterBuffer must: be less than
327    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
328  * [[VUID-vkCmdBeginTransformFeedbackEXT-firstCounterBuffer-02369]]
329    The sum of pname:firstCounterBuffer and pname:counterBufferCount must:
330    be less than or equal to
331    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
332  * [[VUID-vkCmdBeginTransformFeedbackEXT-counterBufferCount-02607]]
333    If pname:counterBufferCount is not `0`, and pname:pCounterBuffers is not
334    `NULL`, pname:pCounterBuffers must: be a valid pointer to an array of
335    pname:counterBufferCount sname:VkBuffer handles that are either valid or
336    dlink:VK_NULL_HANDLE
337  * [[VUID-vkCmdBeginTransformFeedbackEXT-pCounterBufferOffsets-02370]]
338    For each buffer handle in the array, if it is not dlink:VK_NULL_HANDLE
339    it must: reference a buffer large enough to hold 4 bytes at the
340    corresponding offset from the pname:pCounterBufferOffsets array
341  * [[VUID-vkCmdBeginTransformFeedbackEXT-pCounterBuffer-02371]]
342    If pname:pCounterBuffer is `NULL`, then pname:pCounterBufferOffsets
343    must: also be `NULL`
344  * [[VUID-vkCmdBeginTransformFeedbackEXT-pCounterBuffers-02372]]
345    For each buffer handle in the pname:pCounterBuffers array that is not
346    dlink:VK_NULL_HANDLE it must: have been created with a pname:usage value
347    containing
348    ename:VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
349  * [[VUID-vkCmdBeginTransformFeedbackEXT-None-06233]]
350    A valid graphics pipeline must: be bound to
351    ename:VK_PIPELINE_BIND_POINT_GRAPHICS
352  * [[VUID-vkCmdBeginTransformFeedbackEXT-None-04128]]
353    The last <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
354    shader stage>> of the bound graphics pipeline must: have been declared
355    with the code:Xfb execution mode
356ifdef::VK_VERSION_1_1,VK_KHR_multiview[]
357  * [[VUID-vkCmdBeginTransformFeedbackEXT-None-02373]]
358    Transform feedback must: not be made active in a render pass instance
359    with multiview enabled
360endif::VK_VERSION_1_1,VK_KHR_multiview[]
361****
362
363include::{generated}/validity/protos/vkCmdBeginTransformFeedbackEXT.txt[]
364--
365
366[open,refpage='vkCmdEndTransformFeedbackEXT',desc='Make transform feedback inactive in the command buffer',type='protos']
367--
368Transform feedback for specific transform feedback buffers is made inactive
369by calling:
370
371include::{generated}/api/protos/vkCmdEndTransformFeedbackEXT.txt[]
372
373  * pname:commandBuffer is the command buffer into which the command is
374    recorded.
375  * pname:firstCounterBuffer is the index of the first transform feedback
376    buffer corresponding to pname:pCounterBuffers[0] and
377    pname:pCounterBufferOffsets[0].
378  * pname:counterBufferCount is the size of the pname:pCounterBuffers and
379    pname:pCounterBufferOffsets arrays.
380  * pname:pCounterBuffers is `NULL` or a pointer to an array of
381    slink:VkBuffer handles to counter buffers.
382    The counter buffers are used to record the current byte positions of
383    each transform feedback buffer where the next vertex output data would
384    be captured.
385    This can: be used by a subsequent flink:vkCmdBeginTransformFeedbackEXT
386    call to resume transform feedback capture from this position.
387    It can also be used by flink:vkCmdDrawIndirectByteCountEXT to determine
388    the vertex count of the draw call.
389  * pname:pCounterBufferOffsets is `NULL` or a pointer to an array of
390    basetype:VkDeviceSize values specifying offsets within each of the
391    pname:pCounterBuffers where the counter values can be written.
392    The location in each counter buffer at these offsets must: be large
393    enough to contain 4 bytes of data.
394    The data stored at this location is the byte offset from the start of
395    the transform feedback buffer binding where the next vertex data would
396    be written.
397    If pname:pCounterBufferOffsets is `NULL`, then it is assumed the offsets
398    are zero.
399
400.Valid Usage
401****
402  * [[VUID-vkCmdEndTransformFeedbackEXT-transformFeedback-02374]]
403    sname:VkPhysicalDeviceTransformFeedbackFeaturesEXT::pname:transformFeedback
404    must: be enabled
405  * [[VUID-vkCmdEndTransformFeedbackEXT-None-02375]]
406    Transform feedback must: be active
407  * [[VUID-vkCmdEndTransformFeedbackEXT-firstCounterBuffer-02376]]
408    pname:firstCounterBuffer must: be less than
409    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
410  * [[VUID-vkCmdEndTransformFeedbackEXT-firstCounterBuffer-02377]]
411    The sum of pname:firstCounterBuffer and pname:counterBufferCount must:
412    be less than or equal to
413    sname:VkPhysicalDeviceTransformFeedbackPropertiesEXT::pname:maxTransformFeedbackBuffers
414  * [[VUID-vkCmdEndTransformFeedbackEXT-counterBufferCount-02608]]
415    If pname:counterBufferCount is not `0`, and pname:pCounterBuffers is not
416    `NULL`, pname:pCounterBuffers must: be a valid pointer to an array of
417    pname:counterBufferCount sname:VkBuffer handles that are either valid or
418    dlink:VK_NULL_HANDLE
419  * [[VUID-vkCmdEndTransformFeedbackEXT-pCounterBufferOffsets-02378]]
420    For each buffer handle in the array, if it is not dlink:VK_NULL_HANDLE
421    it must: reference a buffer large enough to hold 4 bytes at the
422    corresponding offset from the pname:pCounterBufferOffsets array
423  * [[VUID-vkCmdEndTransformFeedbackEXT-pCounterBuffer-02379]]
424    If pname:pCounterBuffer is `NULL`, then pname:pCounterBufferOffsets
425    must: also be `NULL`
426  * [[VUID-vkCmdEndTransformFeedbackEXT-pCounterBuffers-02380]]
427    For each buffer handle in the pname:pCounterBuffers array that is not
428    dlink:VK_NULL_HANDLE it must: have been created with a pname:usage value
429    containing
430    ename:VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
431****
432
433include::{generated}/validity/protos/vkCmdEndTransformFeedbackEXT.txt[]
434--
435endif::VK_EXT_transform_feedback[]
436
437
438ifdef::VK_NV_viewport_swizzle[]
439[[vertexpostproc-viewport-swizzle]]
440== Viewport Swizzle
441
442[open,refpage='VkPipelineViewportSwizzleStateCreateInfoNV',desc='Structure specifying swizzle applied to primitive clip coordinates',type='structs']
443--
444Each primitive sent to a given viewport has a swizzle and optional: negation
445applied to its clip coordinates.
446The swizzle that is applied depends on the viewport index, and is controlled
447by the sname:VkPipelineViewportSwizzleStateCreateInfoNV pipeline state:
448
449include::{generated}/api/structs/VkPipelineViewportSwizzleStateCreateInfoNV.txt[]
450
451  * pname:sType is the type of this structure.
452  * pname:pNext is `NULL` or a pointer to a structure extending this
453    structure.
454  * pname:flags is reserved for future use.
455  * pname:viewportCount is the number of viewport swizzles used by the
456    pipeline.
457  * pname:pViewportSwizzles is a pointer to an array of
458    slink:VkViewportSwizzleNV structures, defining the viewport swizzles.
459
460.Valid Usage
461****
462  * [[VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215]]
463    pname:viewportCount must: be greater than or equal to the
464    pname:viewportCount set in sname:VkPipelineViewportStateCreateInfo
465****
466
467include::{generated}/validity/structs/VkPipelineViewportSwizzleStateCreateInfoNV.txt[]
468--
469
470[open,refpage='VkPipelineViewportSwizzleStateCreateFlagsNV',desc='Reserved for future use',type='flags']
471--
472include::{generated}/api/flags/VkPipelineViewportSwizzleStateCreateFlagsNV.txt[]
473
474tname:VkPipelineViewportSwizzleStateCreateFlagsNV is a bitmask type for
475setting a mask, but is currently reserved for future use.
476--
477
478The sname:VkPipelineViewportSwizzleStateCreateInfoNV state is set by adding
479this structure to the pname:pNext chain of a
480sname:VkPipelineViewportStateCreateInfo structure and setting the graphics
481pipeline state with flink:vkCreateGraphicsPipelines.
482
483Each viewport specified from 0 to pname:viewportCount - 1 has its x,y,z,w
484swizzle state set to the corresponding pname:x, pname:y, pname:z and pname:w
485in the slink:VkViewportSwizzleNV structure.
486Each component is of type elink:VkViewportCoordinateSwizzleNV, which
487determines the type of swizzle for that component.
488The value of pname:x computes the new x component of the position as:
489
490[source,c]
491---------------------------------------------------
492if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV) x' = x;
493if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV) x' = -x;
494if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV) x' = y;
495if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV) x' = -y;
496if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV) x' = z;
497if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV) x' = -z;
498if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV) x' = w;
499if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV) x' = -w;
500---------------------------------------------------
501
502Similar selections are performed for the pname:y, pname:z, and pname:w
503coordinates.
504This swizzling is applied before clipping and perspective divide.
505If the swizzle for an active viewport index is not specified, the swizzle
506for pname:x is ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, pname:y
507is ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV, pname:z is
508ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV and pname:w is
509ename:VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV.
510
511Viewport swizzle parameters are specified by setting the pname:pNext pointer
512of sname:VkGraphicsPipelineCreateInfo to point to a
513sname:VkPipelineViewportSwizzleStateCreateInfoNV structure.
514slink:VkPipelineViewportSwizzleStateCreateInfoNV uses
515sname:VkViewportSwizzleNV to set the viewport swizzle parameters.
516
517[open,refpage='VkViewportSwizzleNV',desc='Structure specifying a viewport swizzle',type='structs']
518--
519The sname:VkViewportSwizzleNV structure is defined as:
520
521include::{generated}/api/structs/VkViewportSwizzleNV.txt[]
522
523  * pname:x is a elink:VkViewportCoordinateSwizzleNV value specifying the
524    swizzle operation to apply to the x component of the primitive
525  * pname:y is a elink:VkViewportCoordinateSwizzleNV value specifying the
526    swizzle operation to apply to the y component of the primitive
527  * pname:z is a elink:VkViewportCoordinateSwizzleNV value specifying the
528    swizzle operation to apply to the z component of the primitive
529  * pname:w is a elink:VkViewportCoordinateSwizzleNV value specifying the
530    swizzle operation to apply to the w component of the primitive
531
532include::{generated}/validity/structs/VkViewportSwizzleNV.txt[]
533--
534
535[open,refpage='VkViewportCoordinateSwizzleNV',desc='Specify how a viewport coordinate is swizzled',type='enums']
536--
537Possible values of the slink:VkViewportSwizzleNV::pname:x, pname:y, pname:z,
538and pname:w members, specifying swizzling of the corresponding components of
539primitives, are:
540
541include::{generated}/api/enums/VkViewportCoordinateSwizzleNV.txt[]
542
543These values are described in detail in <<vertexpostproc-viewport-swizzle,
544Viewport Swizzle>>.
545--
546endif::VK_NV_viewport_swizzle[]
547
548
549[[vertexpostproc-flatshading]]
550== Flat Shading
551
552_Flat shading_ a vertex output attribute means to assign all vertices of the
553primitive the same value for that output.
554The output values assigned are those of the _provoking vertex_ of the
555primitive.
556Flat shading is applied to those vertex attributes that
557<<interfaces-iointerfaces-matching,match>> fragment input attributes which
558are decorated as code:Flat.
559
560If neither <<geometry,geometry>> nor <<tessellation,tessellation shading>>
561is active, the provoking vertex is determined by the
562<<drawing-primitive-topologies, primitive topology>> defined by
563slink:VkPipelineInputAssemblyStateCreateInfo:pname:topology used to execute
564the <<drawing,drawing command>>.
565
566If <<geometry,geometry shading>> is active, the provoking vertex is
567determined by the <<drawing-primitive-topologies, primitive topology>>
568defined by the <<drawing-point-lists, code:OutputPoints>>,
569<<drawing-line-strips, code:OutputLineStrips>>, or
570<<drawing-triangle-strips, code:OutputTriangleStrips>> execution mode.
571
572If <<tessellation,tessellation shading>> is active but <<geometry,geometry
573shading>> is not, the provoking vertex may: be any of the vertices in each
574primitive.
575
576ifdef::VK_EXT_provoking_vertex[]
577[open,refpage='VkPipelineRasterizationProvokingVertexStateCreateInfoEXT',desc='Structure specifying provoking vertex mode used by a graphics pipeline',type='structs']
578--
579For a given primitive topology, the pipeline's provoking vertex mode
580determines which vertex is the provoking vertex.
581To specify the provoking vertex mode, include a
582sname:VkPipelineRasterizationProvokingVertexStateCreateInfoEXT structure in
583the slink:VkPipelineRasterizationStateCreateInfo::pname:pNext chain when
584creating the pipeline.
585
586The sname:VkPipelineRasterizationProvokingVertexStateCreateInfoEXT structure
587is defined as:
588
589include::{generated}/api/structs/VkPipelineRasterizationProvokingVertexStateCreateInfoEXT.txt[]
590
591  * pname:sType is the type of this structure.
592  * pname:pNext is `NULL` or a pointer to a structure extending this
593    structure.
594  * pname:provokingVertexMode is a elink:VkProvokingVertexModeEXT value
595    selecting the provoking vertex mode.
596
597If this struct is not provided when creating the pipeline, the pipeline will
598use the ename:VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT mode.
599
600If the
601<<limits-provokingVertexModePerPipeline,provokingVertexModePerPipeline>>
602limit is ename:VK_FALSE, then all pipelines bound within a render pass
603instance must: have the same pname:provokingVertexMode.
604
605.Valid Usage
606****
607  * [[VUID-VkPipelineRasterizationProvokingVertexStateCreateInfoEXT-provokingVertexMode-04883]]
608    If pname:provokingVertexMode is
609    ename:VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, then the
610    <<features-provokingVertexLast,provokingVertexLast>> feature must: be
611    enabled
612****
613
614include::{generated}/validity/structs/VkPipelineRasterizationProvokingVertexStateCreateInfoEXT.txt[]
615--
616
617[open,refpage='VkProvokingVertexModeEXT',desc='Specify which vertex in a primitive is the provoking vertex',type='enums']
618--
619Possible values of
620slink:VkPipelineRasterizationProvokingVertexStateCreateInfoEXT::pname:provokingVertexMode
621are:
622
623include::{generated}/api/enums/VkProvokingVertexModeEXT.txt[]
624
625  * ename:VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT specifies that the
626    provoking vertex is the first non-adjacency vertex in the list of
627    vertices used by a primitive.
628  * ename:VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT specifies that the
629    provoking vertex is the last non-adjacency vertex in the list of
630    vertices used by a primitive.
631
632These modes are described more precisely in
633<<drawing-primitive-topologies,Primitive Topologies>>.
634--
635endif::VK_EXT_provoking_vertex[]
636
637
638[[vertexpostproc-clipping]]
639== Primitive Clipping
640
641Primitives are culled against the _cull volume_ and then clipped to the
642_clip volume_.
643In clip coordinates, the _view volume_ is defined by:
644
645[latexmath]
646++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
647\begin{array}{c}
648-w_c \leq x_c \leq w_c \\
649-w_c \leq y_c \leq w_c \\
650z_m \leq z_c \leq w_c
651\end{array}
652++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
653
654where
655ifdef::VK_EXT_depth_clip_control[]
656if
657slink:VkPipelineViewportDepthClipControlCreateInfoEXT::pname:negativeOneToOne
658is ename:VK_TRUE [eq]#z~m~# is equal to [eq]#-w~c~# otherwise
659endif::VK_EXT_depth_clip_control[]
660[eq]#z~m~# is equal to zero.
661
662This view volume can: be further restricted by as many as
663sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined
664half-spaces.
665
666The cull volume is the intersection of up to
667sname:VkPhysicalDeviceLimits::pname:maxCullDistances client-defined
668half-spaces (if no client-defined cull half-spaces are enabled, culling
669against the cull volume is skipped).
670
671A shader must: write a single cull distance for each enabled cull half-space
672to elements of the code:CullDistance array.
673If the cull distance for any enabled cull half-space is negative for all of
674the vertices of the primitive under consideration, the primitive is
675discarded.
676Otherwise the primitive is clipped against the clip volume as defined below.
677
678The clip volume is the intersection of up to
679sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined
680half-spaces with the view volume (if no client-defined clip half-spaces are
681enabled, the clip volume is the view volume).
682
683A shader must: write a single clip distance for each enabled clip half-space
684to elements of the code:ClipDistance array.
685Clip half-space [eq]#i# is then given by the set of points satisfying the
686inequality
687
688  {empty}:: [eq]#c~i~(**P**) {geq} 0#
689
690where [eq]#c~i~(**P**)# is the clip distance [eq]#i# at point [eq]#**P**#.
691For point primitives, [eq]#c~i~(**P**)# is simply the clip distance for the
692vertex in question.
693For line and triangle primitives, per-vertex clip distances are interpolated
694using a weighted mean, with weights derived according to the algorithms
695described in sections <<primsrast-lines-basic,Basic Line Segment
696Rasterization>> and <<primsrast-polygons-basic,Basic Polygon
697Rasterization>>, using the perspective interpolation equations.
698
699The number of client-defined clip and cull half-spaces that are enabled is
700determined by the explicit size of the built-in arrays code:ClipDistance and
701code:CullDistance, respectively, declared as an output in the interface of
702the entry point of the final shader stage before clipping.
703
704ifdef::VK_EXT_depth_clip_enable[]
705If slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT is present in
706the graphics pipeline state then depth clipping is disabled if
707slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT::pname:depthClipEnable
708is ename:VK_FALSE.
709Otherwise, if slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT is
710not present, depth clipping is disabled when
711slink:VkPipelineRasterizationStateCreateInfo::pname:depthClampEnable is
712ename:VK_TRUE.
713endif::VK_EXT_depth_clip_enable[]
714ifndef::VK_EXT_depth_clip_enable[]
715Depth clamping is enabled or disabled via the pname:depthClampEnable enable
716of the slink:VkPipelineRasterizationStateCreateInfo structure.
717Depth clipping is disabled when pname:depthClampEnable is ename:VK_TRUE.
718endif::VK_EXT_depth_clip_enable[]
719When depth clipping is disabled, the plane equation
720
721  {empty}:: [eq]#z~m~ {leq} z~c~ {leq} w~c~#
722
723(see the clip volume definition above) is ignored by view volume clipping
724(effectively, there is no near or far plane clipping).
725
726If the primitive under consideration is a point or line segment, then
727clipping passes it unchanged if its vertices lie entirely within the clip
728volume.
729
730ifndef::VK_VERSION_1_1,VK_KHR_maintenance2[]
731If a point's vertex lies outside of the clip volume, the entire primitive
732may: be discarded.
733endif::VK_VERSION_1_1,VK_KHR_maintenance2[]
734
735ifdef::VK_VERSION_1_1,VK_KHR_maintenance2[]
736[open,refpage='VkPointClippingBehavior',desc='Enum specifying the point clipping behavior',type='enums']
737--
738Possible values of
739slink:VkPhysicalDevicePointClippingProperties::pname:pointClippingBehavior,
740specifying clipping behavior of a point primitive whose vertex lies outside
741the clip volume, are:
742
743include::{generated}/api/enums/VkPointClippingBehavior.txt[]
744
745ifdef::VK_KHR_maintenance2[]
746or the equivalent
747
748include::{generated}/api/enums/VkPointClippingBehaviorKHR.txt[]
749endif::VK_KHR_maintenance2[]
750
751  * ename:VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES specifies that the
752    primitive is discarded if the vertex lies outside any clip plane,
753    including the planes bounding the view volume.
754  * ename:VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY specifies that
755    the primitive is discarded only if the vertex lies outside any user clip
756    plane.
757--
758endif::VK_VERSION_1_1,VK_KHR_maintenance2[]
759
760If either of a line segment's vertices lie outside of the clip volume, the
761line segment may: be clipped, with new vertex coordinates computed for each
762vertex that lies outside the clip volume.
763A clipped line segment endpoint lies on both the original line segment and
764the boundary of the clip volume.
765
766This clipping produces a value, [eq]#0 {leq} t {leq} 1#, for each clipped
767vertex.
768If the coordinates of a clipped vertex are [eq]#**P**# and the unclipped
769line segment's vertex coordinates are [eq]#**P**~1~# and [eq]#**P**~2~#,
770then [eq]#t# satisfies the following equation
771
772  {empty}:: [eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#.
773
774[eq]#t# is used to clip vertex output attributes as described in
775<<vertexpostproc-clipping-shader-outputs,Clipping Shader Outputs>>.
776
777If the primitive is a polygon, it passes unchanged if every one of its edges
778lies entirely inside the clip volume, and is either clipped or discarded
779otherwise.
780If the edges of the polygon intersect the boundary of the clip volume, the
781intersecting edges are reconnected by new edges that lie along the boundary
782of the clip volume - in some cases requiring the introduction of new
783vertices into a polygon.
784
785If a polygon intersects an edge of the clip volume's boundary, the clipped
786polygon must: include a point on this boundary edge.
787
788Primitives rendered with user-defined half-spaces must: satisfy a
789complementarity criterion.
790Suppose a series of primitives is drawn where each vertex [eq]#i# has a
791single specified clip distance [eq]#d~i~# (or a number of similarly
792specified clip distances, if multiple half-spaces are enabled).
793Next, suppose that the same series of primitives are drawn again with each
794such clip distance replaced by [eq]#-d~i~# (and the graphics pipeline is
795otherwise the same).
796In this case, primitives must: not be missing any pixels, and pixels must:
797not be drawn twice in regions where those primitives are cut by the clip
798planes.
799
800ifdef::VK_EXT_depth_clip_control[]
801
802[open,refpage='VkPipelineViewportDepthClipControlCreateInfoEXT',desc='Structure specifying parameters of a newly created pipeline depth clip control state',type='structs']
803--
804
805The sname:VkPipelineViewportDepthClipControlCreateInfoEXT structure is
806defined as:
807
808include::{generated}/api/structs/VkPipelineViewportDepthClipControlCreateInfoEXT.txt[]
809
810  * pname:sType is the type of this structure.
811  * pname:pNext is `NULL` or a pointer to a structure extending this
812    structure.
813  * pname:negativeOneToOne sets the [eq]#z~m~# in the _view volume_ to
814    [eq]#-w~c~#
815
816.Valid Usage
817****
818  * [[VUID-VkPipelineViewportDepthClipControlCreateInfoEXT-negativeOneToOne-06470]]
819    If <<features-depthClipControl,depthClipControl>> is not enabled,
820    pname:negativeOneToOne must: be ename:VK_FALSE
821****
822
823include::{generated}/validity/structs/VkPipelineViewportDepthClipControlCreateInfoEXT.txt[]
824--
825
826endif::VK_EXT_depth_clip_control[]
827
828[[vertexpostproc-clipping-shader-outputs]]
829== Clipping Shader Outputs
830
831Next, vertex output attributes are clipped.
832The output values associated with a vertex that lies within the clip volume
833are unaffected by clipping.
834If a primitive is clipped, however, the output values assigned to vertices
835produced by clipping are clipped.
836
837Let the output values assigned to the two vertices [eq]#**P**~1~# and
838[eq]#**P**~2~# of an unclipped edge be [eq]#**c**~1~# and [eq]#**c**~2~#.
839The value of [eq]#t# (see <<vertexpostproc-clipping,Primitive Clipping>>)
840for a clipped point [eq]#**P**# is used to obtain the output value
841associated with [eq]#**P**# as
842
843  {empty}:: [eq]#**c** = t **c**~1~ {plus} (1-t) **c**~2~#.
844
845(Multiplying an output value by a scalar means multiplying each of _x_, _y_,
846_z_, and _w_ by the scalar.)
847
848Since this computation is performed in clip space before division by
849[eq]#w~c~#, clipped output values are perspective-correct.
850
851Polygon clipping creates a clipped vertex along an edge of the clip volume's
852boundary.
853This situation is handled by noting that polygon clipping proceeds by
854clipping against one half-space at a time.
855Output value clipping is done in the same way, so that clipped points always
856occur at the intersection of polygon edges (possibly already clipped) with
857the clip volume's boundary.
858
859For vertex output attributes whose matching fragment input attributes are
860decorated with code:NoPerspective, the value of [eq]#t# used to obtain the
861output value associated with [eq]#**P**# will be adjusted to produce results
862that vary linearly in framebuffer space.
863
864Output attributes of integer or unsigned integer type must: always be flat
865shaded.
866Flat shaded attributes are constant over the primitive being rasterized (see
867<<primsrast-lines-basic,Basic Line Segment Rasterization>> and
868<<primsrast-polygons-basic,Basic Polygon Rasterization>>), and no
869interpolation is performed.
870The output value [eq]#**c**# is taken from either [eq]#**c**~1~# or
871[eq]#**c**~2~#, since flat shading has already occurred and the two values
872are identical.
873
874ifdef::VK_NV_clip_space_w_scaling[]
875include::{chapters}/VK_NV_clip_space_w_scaling/vertexpostproc.txt[]
876endif::VK_NV_clip_space_w_scaling[]
877
878
879[[vertexpostproc-coord-transform]]
880== Coordinate Transformations
881
882_Clip coordinates_ for a vertex result from shader execution, which yields a
883vertex coordinate code:Position.
884
885Perspective division on clip coordinates yields _normalized device
886coordinates_, followed by a _viewport_ transformation (see
887<<vertexpostproc-viewport,Controlling the Viewport>>) to convert these
888coordinates into _framebuffer coordinates_.
889
890If a vertex in clip coordinates has a position given by
891
892[latexmath]
893++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
894\left(\begin{array}{c}
895x_c \\
896y_c \\
897z_c \\
898w_c
899\end{array}\right)
900++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
901
902then the vertex's normalized device coordinates are
903[latexmath]
904++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
905\left(
906        \begin{array}{c}
907                x_d \\
908                y_d \\
909                z_d
910        \end{array}
911\right) =
912\left(
913        \begin{array}{c}
914                \frac{x_c}{w_c} \\
915                \frac{y_c}{w_c} \\
916                \frac{z_c}{w_c}
917        \end{array}
918\right)
919++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
920
921
922ifdef::VK_QCOM_render_pass_transform[]
923[[vertexpostproc-renderpass-transform]]
924== Render Pass Transform
925
926A _render pass transform_ can: be enabled for render pass instances.
927The clip coordinates [eq]#(x~c~, y~c~)# that result from vertex shader
928execution are transformed by a rotation of 0, 90, 180, or 270 degrees in the
929XY plane, centered at the origin.
930
931When _Render pass transform_ is enabled, the transform applies to all
932primitives for all subpasses of the render pass.
933The transformed vertex in clip coordinates has a position given by
934
935[latexmath]
936++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
937\left(
938        \begin{array}{c}
939                x_{c_{trans}} \\
940                y_{c_{trans}} \\
941                z_{c_{trans}}
942        \end{array}
943\right) =
944\left(
945        \begin{array}{c}
946                x_{c} \cos \theta - y_{c} \sin \theta \\
947                x_{c} \sin \theta + y_{c} \cos \theta \\
948                z_c
949        \end{array}
950\right)
951++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
952
953where
954
955  * _[eq]#{theta}#_ is 0 degrees for
956    ename:VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
957  * _[eq]#{theta}#_ is 90 degrees for
958    ename:VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR
959  * _[eq]#{theta}#_ is 180 degrees for
960    ename:VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR
961  * _[eq]#{theta}#_ is 270 degrees for
962    ename:VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR
963
964
965The transformed vertex's normalized device coordinates are
966[latexmath]
967++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
968\left(
969        \begin{array}{c}
970                x_d \\
971                y_d \\
972                z_d
973        \end{array}
974\right) =
975\left(
976        \begin{array}{c}
977                \frac{x_{c_{trans}}}{w_c} \\
978                \frac{y_{c_{trans}}}{w_c} \\
979                \frac{z_{c_{trans}}}{w_c}
980        \end{array}
981\right)
982++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
983
984
985When render pass transform is enabled for a render pass instance, the
986following additional features are enabled:
987
988  * Each slink:VkViewport specified by either
989    slink:VkPipelineViewportStateCreateInfo::pname:pViewports or
990    flink:vkCmdSetViewport will have its width/height [eq]#(p~x~, p~y~)# and
991    its center [eq]#(o~x~, o~y~)# similarly transformed by the
992    implementation.
993  * Each scissor specified by
994    slink:VkPipelineViewportStateCreateInfo::pname:pScissors or
995    flink:vkCmdSetScissor will have its [eq]#(offset~x~, offset~y~)# and
996    [eq]#(extent~x~, extent~y~)# similarly transformed by the
997    implementation.
998  * The pname:renderArea specified in
999    slink:VkCommandBufferInheritanceRenderPassTransformInfoQCOM and
1000    slink:VkRenderPassBeginInfo will be similarly transformed by the
1001    implementation.
1002  * The [eq]#(x, y)# components of shader variables with built-in
1003    decorations code:FragCoord, code:SamplePosition, or code:PointCoord will
1004    be similarly transformed by the implementation.
1005  * The [eq]#(x,y)# components of the code:offset operand of the
1006    code:InterpolateAtOffset extended instruction will be similarly
1007    transformed by the implementation.
1008  * The values returned by SPIR-V <<shaders-derivative-operations,
1009    derivative instructions>> code:OpDPdx, code:OpDPdy, code:OpDPdxCourse,
1010    code:OpDPdyCourse, code:OpDPdxFine, code:OpDPdyFine will be similarly
1011    transformed by the implementation.
1012
1013
1014The net result of the above, is that applications can: act as if rendering
1015to a framebuffer oriented with the
1016slink:VkSurfaceCapabilitiesKHR::pname:currentTransform.
1017In other words, applications can: act as if the presentation engine will be
1018performing the transformation of the swapchain image after rendering and
1019prior to presentation to the user.
1020In fact, the transformation of the various items cited above are being
1021handled by the implementation as the rendering takes place.
1022
1023endif::VK_QCOM_render_pass_transform[]
1024
1025
1026[[vertexpostproc-viewport]]
1027== Controlling the Viewport
1028
1029The viewport transformation is determined by the selected viewport's width
1030and height in pixels, [eq]#p~x~# and [eq]#p~y~#, respectively, and its
1031center [eq]#(o~x~, o~y~)# (also in pixels), as well as its depth range min
1032and max determining a depth range scale value [eq]#p~z~# and a depth range
1033bias value [eq]#o~z~# (defined below).
1034The vertex's framebuffer coordinates [eq]#(x~f~, y~f~, z~f~)# are given by
1035
1036  {empty}:: [eq]#x~f~ = (p~x~ / 2) x~d~ {plus} o~x~#
1037  {empty}:: [eq]#y~f~ = (p~y~ / 2) y~d~ {plus} o~y~#
1038  {empty}:: [eq]#z~f~ = p~z~ {times} z~d~ {plus} o~z~#
1039
1040Multiple viewports are available, numbered zero up to
1041sname:VkPhysicalDeviceLimits::pname:maxViewports minus one.
1042The number of viewports used by a pipeline is controlled by the
1043pname:viewportCount member of the sname:VkPipelineViewportStateCreateInfo
1044structure used in pipeline creation.
1045
1046[eq]#x~f~# and [eq]#y~f~# have limited precision, where the number of
1047fractional bits retained is specified by
1048sname:VkPhysicalDeviceLimits::pname:subPixelPrecisionBits.
1049ifdef::VK_EXT_line_rasterization[]
1050When rasterizing <<primsrast-lines,line segments>>, the number of fractional
1051bits is specified by
1052sname:VkPhysicalDeviceLineRasterizationPropertiesEXT::pname:lineSubPixelPrecisionBits.
1053endif::VK_EXT_line_rasterization[]
1054
1055[open,refpage='VkPipelineViewportStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline viewport state',type='structs']
1056--
1057The sname:VkPipelineViewportStateCreateInfo structure is defined as:
1058
1059include::{generated}/api/structs/VkPipelineViewportStateCreateInfo.txt[]
1060
1061  * pname:sType is the type of this structure.
1062  * pname:pNext is `NULL` or a pointer to a structure extending this
1063    structure.
1064  * pname:flags is reserved for future use.
1065  * pname:viewportCount is the number of viewports used by the pipeline.
1066  * pname:pViewports is a pointer to an array of slink:VkViewport
1067    structures, defining the viewport transforms.
1068    If the viewport state is dynamic, this member is ignored.
1069  * pname:scissorCount is the number of <<fragops-scissor,scissors>> and
1070    must: match the number of viewports.
1071  * pname:pScissors is a pointer to an array of slink:VkRect2D structures
1072    defining the rectangular bounds of the scissor for the corresponding
1073    viewport.
1074    If the scissor state is dynamic, this member is ignored.
1075
1076.Valid Usage
1077****
1078  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216]]
1079    If the <<features-multiViewport,multiple viewports>> feature is not
1080    enabled, pname:viewportCount must: not be greater than `1`
1081  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217]]
1082    If the <<features-multiViewport,multiple viewports>> feature is not
1083    enabled, pname:scissorCount must: not be greater than `1`
1084  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218]]
1085    pname:viewportCount must: be less than or equal to
1086    sname:VkPhysicalDeviceLimits::pname:maxViewports
1087  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219]]
1088    pname:scissorCount must: be less than or equal to
1089    sname:VkPhysicalDeviceLimits::pname:maxViewports
1090ifndef::VK_EXT_extended_dynamic_state[]
1091  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220]]
1092    pname:scissorCount and pname:viewportCount must: be identical
1093endif::VK_EXT_extended_dynamic_state[]
1094  * [[VUID-VkPipelineViewportStateCreateInfo-x-02821]]
1095    The pname:x and pname:y members of pname:offset member of any element of
1096    pname:pScissors must: be greater than or equal to `0`
1097  * [[VUID-VkPipelineViewportStateCreateInfo-offset-02822]]
1098    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# must: not
1099    cause a signed integer addition overflow for any element of
1100    pname:pScissors
1101  * [[VUID-VkPipelineViewportStateCreateInfo-offset-02823]]
1102    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# must:
1103    not cause a signed integer addition overflow for any element of
1104    pname:pScissors
1105ifndef::VK_EXT_extended_dynamic_state[]
1106  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength]]
1107    pname:viewportCount must: be greater than `0`
1108  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength]]
1109    pname:scissorCount must: be greater than `0`
1110endif::VK_EXT_extended_dynamic_state[]
1111ifdef::VK_EXT_extended_dynamic_state[]
1112  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134]]
1113    If the graphics pipeline is being created without
1114    ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT and
1115    ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set then
1116    pname:scissorCount and pname:viewportCount must: be identical
1117  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135]]
1118    If the graphics pipeline is being created with
1119    ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT set then
1120    pname:viewportCount must: be `0`, otherwise it must: be greater than `0`
1121  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136]]
1122    If the graphics pipeline is being created with
1123    ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set then
1124    pname:scissorCount must: be `0`, otherwise it must: be greater than `0`
1125endif::VK_EXT_extended_dynamic_state[]
1126ifdef::VK_NV_clip_space_w_scaling[]
1127  * [[VUID-VkPipelineViewportStateCreateInfo-viewportWScalingEnable-01726]]
1128    If the pname:viewportWScalingEnable member of a
1129    slink:VkPipelineViewportWScalingStateCreateInfoNV structure included in
1130    the pname:pNext chain is ename:VK_TRUE, the pname:viewportCount member
1131    of the slink:VkPipelineViewportWScalingStateCreateInfoNV structure must:
1132    be greater than or equal to
1133    slink:VkPipelineViewportStateCreateInfo::pname:viewportCount
1134endif::VK_NV_clip_space_w_scaling[]
1135****
1136
1137include::{generated}/validity/structs/VkPipelineViewportStateCreateInfo.txt[]
1138--
1139
1140ifdef::VK_EXT_extended_dynamic_state[]
1141[open,refpage='vkCmdSetViewportWithCountEXT',desc='Set the viewport count and viewports dynamically for a command buffer',type='protos']
1142--
1143To <<pipelines-dynamic-state, dynamically set>> the viewport count and
1144viewports, call:
1145
1146include::{generated}/api/protos/vkCmdSetViewportWithCountEXT.txt[]
1147
1148  * pname:commandBuffer is the command buffer into which the command will be
1149    recorded.
1150  * pname:viewportCount specifies the viewport count.
1151  * pname:pViewports specifies the viewports to use for drawing.
1152
1153This command sets the viewport count and viewports state for subsequent
1154drawing commands when the graphics pipeline is created with
1155ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT set in
1156slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1157Otherwise, this state is specified by the corresponding
1158slink:VkPipelineViewportStateCreateInfo::pname:viewportCount and
1159pname:pViewports values used to create the currently active pipeline.
1160
1161.Valid Usage
1162****
1163  * [[VUID-vkCmdSetViewportWithCountEXT-None-03393]]
1164    The <<features-extendedDynamicState, extendedDynamicState>> feature
1165    must: be enabled
1166  * [[VUID-vkCmdSetViewportWithCountEXT-viewportCount-03394]]
1167    pname:viewportCount must: be between `1` and
1168    sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1169  * [[VUID-vkCmdSetViewportWithCountEXT-viewportCount-03395]]
1170    If the <<features-multiViewport,multiple viewports>> feature is not
1171    enabled, pname:viewportCount must: be `1`
1172ifdef::VK_NV_inherited_viewport_scissor[]
1173  * [[VUID-vkCmdSetViewportWithCountEXT-commandBuffer-04819]]
1174    pname:commandBuffer must: not have
1175    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1176    enabled
1177endif::VK_NV_inherited_viewport_scissor[]
1178****
1179
1180include::{generated}/validity/protos/vkCmdSetViewportWithCountEXT.txt[]
1181--
1182
1183[open,refpage='vkCmdSetScissorWithCountEXT',desc='Set the scissor count and scissor rectangular bounds dynamically for a command buffer',type='protos']
1184--
1185To <<pipelines-dynamic-state, dynamically set>> the scissor count and
1186scissor rectangular bounds, call:
1187
1188include::{generated}/api/protos/vkCmdSetScissorWithCountEXT.txt[]
1189
1190  * pname:commandBuffer is the command buffer into which the command will be
1191    recorded.
1192  * pname:scissorCount specifies the scissor count.
1193  * pname:pScissors specifies the scissors to use for drawing.
1194
1195This command sets the scissor count and scissor rectangular bounds state for
1196subsequence drawing commands when the graphics pipeline is created with
1197ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set in
1198slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1199Otherwise, this state is specified by the corresponding
1200slink:VkPipelineViewportStateCreateInfo::pname:scissorCount and
1201pname:pScissors values used to create the currently active pipeline.
1202
1203.Valid Usage
1204****
1205  * [[VUID-vkCmdSetScissorWithCountEXT-None-03396]]
1206    The <<features-extendedDynamicState, extendedDynamicState>> feature
1207    must: be enabled
1208  * [[VUID-vkCmdSetScissorWithCountEXT-scissorCount-03397]]
1209    pname:scissorCount must: be between `1` and
1210    sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1211  * [[VUID-vkCmdSetScissorWithCountEXT-scissorCount-03398]]
1212    If the <<features-multiViewport,multiple viewports>> feature is not
1213    enabled, pname:scissorCount must: be `1`
1214  * [[VUID-vkCmdSetScissorWithCountEXT-x-03399]]
1215    The pname:x and pname:y members of pname:offset member of any element of
1216    pname:pScissors must: be greater than or equal to `0`
1217  * [[VUID-vkCmdSetScissorWithCountEXT-offset-03400]]
1218    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# must: not
1219    cause a signed integer addition overflow for any element of
1220    pname:pScissors
1221  * [[VUID-vkCmdSetScissorWithCountEXT-offset-03401]]
1222    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# must:
1223    not cause a signed integer addition overflow for any element of
1224    pname:pScissors
1225ifdef::VK_NV_inherited_viewport_scissor[]
1226  * [[VUID-vkCmdSetScissorWithCountEXT-commandBuffer-04820]]
1227    pname:commandBuffer must: not have
1228    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1229    enabled
1230endif::VK_NV_inherited_viewport_scissor[]
1231****
1232
1233include::{generated}/validity/protos/vkCmdSetScissorWithCountEXT.txt[]
1234--
1235endif::VK_EXT_extended_dynamic_state[]
1236
1237[open,refpage='VkPipelineViewportStateCreateFlags',desc='Reserved for future use',type='flags']
1238--
1239include::{generated}/api/flags/VkPipelineViewportStateCreateFlags.txt[]
1240
1241tname:VkPipelineViewportStateCreateFlags is a bitmask type for setting a
1242mask, but is currently reserved for future use.
1243--
1244
1245ifndef::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1246If a geometry shader is active and has an output variable decorated with
1247code:ViewportIndex, the viewport transformation uses the viewport
1248corresponding to the value assigned to code:ViewportIndex taken from an
1249implementation-dependent vertex of each primitive.
1250If code:ViewportIndex is outside the range zero to pname:viewportCount minus
1251one for a primitive, or if the geometry shader did not assign a value to
1252code:ViewportIndex for all vertices of a primitive due to flow control, the
1253values resulting from the viewport transformation of the vertices of such
1254primitives are undefined:.
1255If no geometry shader is active, or if the geometry shader does not have an
1256output decorated with code:ViewportIndex, the viewport numbered zero is used
1257by the viewport transformation.
1258endif::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1259
1260ifdef::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1261ifdef::VK_NV_viewport_array2[]
1262A _<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1263stage>>_ can: direct each primitive to zero or more viewports.
1264The destination viewports for a primitive are selected by the last active
1265<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1266stage>> that has an output variable decorated with code:ViewportIndex
1267(selecting a single viewport) or code:ViewportMaskNV (selecting multiple
1268viewports).
1269The viewport transform uses the viewport corresponding to either the value
1270assigned to code:ViewportIndex or one of the bits set in
1271code:ViewportMaskNV, and taken from an implementation-dependent vertex of
1272each primitive.
1273If code:ViewportIndex or any of the bits in code:ViewportMaskNV are outside
1274the range zero to pname:viewportCount minus one for a primitive, or if the
1275last active <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1276shader stage>> did not assign a value to either code:ViewportIndex or
1277code:ViewportMaskNV for all vertices of a primitive due to flow control, the
1278values resulting from the viewport transformation of the vertices of such
1279primitives are undefined:.
1280If the last <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1281shader stage>> does not have an output decorated with code:ViewportIndex or
1282code:ViewportMaskNV, the viewport numbered zero is used by the viewport
1283transformation.
1284endif::VK_NV_viewport_array2[]
1285ifndef::VK_NV_viewport_array2[]
1286A _<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1287stage>>_ can: direct each primitive to one of several viewports.
1288The destination viewport for a primitive is selected by the last active
1289<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1290stage>> that has an output variable decorated with code:ViewportIndex.
1291The viewport transform uses the viewport corresponding to the value assigned
1292to code:ViewportIndex, and taken from an implementation-dependent vertex of
1293each primitive.
1294If code:ViewportIndex is outside the range zero to pname:viewportCount minus
1295one for a primitive, or if the last active
1296<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1297stage>> did not assign a value to code:ViewportIndex for all vertices of a
1298primitive due to flow control, the values resulting from the viewport
1299transformation of the vertices of such primitives are undefined:.
1300If the last <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1301shader stage>> does not have an output decorated with code:ViewportIndex,
1302the viewport numbered zero is used by the viewport transformation.
1303endif::VK_NV_viewport_array2[]
1304endif::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1305
1306A single vertex can: be used in more than one individual primitive, in
1307primitives such as ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP.
1308In this case, the viewport transformation is applied separately for each
1309primitive.
1310
1311[open,refpage='vkCmdSetViewport',desc='Set the viewport dynamically for a command buffer',type='protos']
1312--
1313To <<pipelines-dynamic-state, dynamically set>> the viewport transformation
1314parameters, call:
1315
1316include::{generated}/api/protos/vkCmdSetViewport.txt[]
1317
1318  * pname:commandBuffer is the command buffer into which the command will be
1319    recorded.
1320  * pname:firstViewport is the index of the first viewport whose parameters
1321    are updated by the command.
1322  * pname:viewportCount is the number of viewports whose parameters are
1323    updated by the command.
1324  * pname:pViewports is a pointer to an array of slink:VkViewport structures
1325    specifying viewport parameters.
1326
1327This command sets the viewport transformation parameters state for
1328subsequent drawing commands when the graphics pipeline is created with
1329ename:VK_DYNAMIC_STATE_VIEWPORT set in
1330slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1331Otherwise, this state is specified by the
1332sname:VkPipelineViewportStateCreateInfo::pname:pViewports values used to
1333create the currently active pipeline.
1334
1335The viewport parameters taken from element [eq]#i# of pname:pViewports
1336replace the current state for the viewport index [eq]#pname:firstViewport
1337{plus} i#, for [eq]#i# in [eq]#[0, pname:viewportCount)#.
1338
1339.Valid Usage
1340****
1341  * [[VUID-vkCmdSetViewport-firstViewport-01223]]
1342    The sum of pname:firstViewport and pname:viewportCount must: be between
1343    `1` and sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1344  * [[VUID-vkCmdSetViewport-firstViewport-01224]]
1345    If the <<features-multiViewport,multiple viewports>> feature is not
1346    enabled, pname:firstViewport must: be `0`
1347  * [[VUID-vkCmdSetViewport-viewportCount-01225]]
1348    If the <<features-multiViewport,multiple viewports>> feature is not
1349    enabled, pname:viewportCount must: be `1`
1350ifdef::VK_NV_inherited_viewport_scissor[]
1351  * [[VUID-vkCmdSetViewport-commandBuffer-04821]]
1352    pname:commandBuffer must: not have
1353    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1354    enabled
1355endif::VK_NV_inherited_viewport_scissor[]
1356****
1357
1358include::{generated}/validity/protos/vkCmdSetViewport.txt[]
1359--
1360
1361Both slink:VkPipelineViewportStateCreateInfo and flink:vkCmdSetViewport use
1362sname:VkViewport to set the viewport transformation parameters.
1363
1364[open,refpage='VkViewport',desc='Structure specifying a viewport',type='structs']
1365--
1366The sname:VkViewport structure is defined as:
1367
1368include::{generated}/api/structs/VkViewport.txt[]
1369
1370  * pname:x and pname:y are the viewport's upper left corner [eq]#(x,y)#.
1371  * pname:width and pname:height are the viewport's width and height,
1372    respectively.
1373  * pname:minDepth and pname:maxDepth are the depth range for the viewport.
1374
1375[NOTE]
1376.Note
1377====
1378Despite their names, pname:minDepth can: be less than, equal to, or greater
1379than pname:maxDepth.
1380====
1381
1382The framebuffer depth coordinate [eq]#pname:z~f~# may: be represented using
1383either a fixed-point or floating-point representation.
1384However, a floating-point representation must: be used if the depth/stencil
1385attachment has a floating-point depth component.
1386If an [eq]#m#-bit fixed-point representation is used, we assume that it
1387represents each value latexmath:[\frac{k}{2^m - 1}], where [eq]#k {elem} {
13880, 1, ..., 2^m^-1 }#, as [eq]#k# (e.g. 1.0 is represented in binary as a
1389string of all ones).
1390
1391The viewport parameters shown in the above equations are found from these
1392values as
1393
1394  {empty}:: [eq]#o~x~ = pname:x {plus} pname:width / 2#
1395  {empty}:: [eq]#o~y~ = pname:y {plus} pname:height / 2#
1396  {empty}:: [eq]#o~z~ = pname:minDepth#
1397  {empty}:: [eq]#p~x~ = pname:width#
1398  {empty}:: [eq]#p~y~ = pname:height#
1399  {empty}:: [eq]#p~z~ = pname:maxDepth - pname:minDepth#.
1400
1401ifdef::VK_QCOM_render_pass_transform[]
1402If a render pass transform is enabled, the values [eq]#(p~x~,p~y~)# and
1403[eq]#(o~x~, o~y~)# defining the viewport are transformed as described in
1404<<vertexpostproc-renderpass-transform, render pass transform>> before
1405participating in the viewport transform.
1406endif::VK_QCOM_render_pass_transform[]
1407
1408ifdef::VK_VERSION_1_1,VK_KHR_maintenance1[]
1409The application can: specify a negative term for pname:height, which has the
1410effect of negating the y coordinate in clip space before performing the
1411transform.
1412When using a negative pname:height, the application should: also adjust the
1413pname:y value to point to the lower left corner of the viewport instead of
1414the upper left corner.
1415Using the negative pname:height allows the application to avoid having to
1416negate the y component of the code:Position output from the last
1417<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1418stage>>.
1419endif::VK_VERSION_1_1,VK_KHR_maintenance1[]
1420
1421The width and height of the <<limits-maxViewportDimensions,
1422implementation-dependent maximum viewport dimensions>> must: be greater than
1423or equal to the width and height of the largest image which can: be created
1424and attached to a framebuffer.
1425
1426The floating-point viewport bounds are represented with an
1427<<limits-viewportSubPixelBits,implementation-dependent precision>>.
1428
1429.Valid Usage
1430****
1431  * [[VUID-VkViewport-width-01770]]
1432    pname:width must: be greater than `0.0`
1433  * [[VUID-VkViewport-width-01771]]
1434    pname:width must: be less than or equal to
1435    sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[0]
1436ifndef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1437  * [[VUID-VkViewport-height-01772]]
1438    pname:height must: be greater than `0.0`
1439endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1440  * [[VUID-VkViewport-height-01773]]
1441    The absolute value of pname:height must: be less than or equal to
1442    sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[1]
1443  * [[VUID-VkViewport-x-01774]]
1444    pname:x must: be greater than or equal to pname:viewportBoundsRange[0]
1445  * [[VUID-VkViewport-x-01232]]
1446    [eq]#(pname:x {plus} pname:width)# must: be less than or equal to
1447    pname:viewportBoundsRange[1]
1448  * [[VUID-VkViewport-y-01775]]
1449    pname:y must: be greater than or equal to pname:viewportBoundsRange[0]
1450ifdef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1451  * [[VUID-VkViewport-y-01776]]
1452    pname:y must: be less than or equal to pname:viewportBoundsRange[1]
1453  * [[VUID-VkViewport-y-01777]]
1454    [eq]#(pname:y {plus} pname:height)# must: be greater than or equal to
1455    pname:viewportBoundsRange[0]
1456endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1457  * [[VUID-VkViewport-y-01233]]
1458    [eq]#(pname:y {plus} pname:height)# must: be less than or equal to
1459    pname:viewportBoundsRange[1]
1460ifdef::VK_EXT_depth_range_unrestricted[]
1461  * [[VUID-VkViewport-minDepth-01234]]
1462    Unless `apiext:VK_EXT_depth_range_unrestricted` extension is enabled
1463    pname:minDepth must: be between `0.0` and `1.0`, inclusive
1464endif::VK_EXT_depth_range_unrestricted[]
1465ifndef::VK_EXT_depth_range_unrestricted[]
1466  * [[VUID-VkViewport-minDepth-02540]]
1467    pname:minDepth must: be between `0.0` and `1.0`, inclusive
1468endif::VK_EXT_depth_range_unrestricted[]
1469ifdef::VK_EXT_depth_range_unrestricted[]
1470  * [[VUID-VkViewport-maxDepth-01235]]
1471    Unless `apiext:VK_EXT_depth_range_unrestricted` extension is enabled
1472    pname:maxDepth must: be between `0.0` and `1.0`, inclusive
1473endif::VK_EXT_depth_range_unrestricted[]
1474ifndef::VK_EXT_depth_range_unrestricted[]
1475  * [[VUID-VkViewport-maxDepth-02541]]
1476    pname:maxDepth must: be between `0.0` and `1.0`, inclusive
1477endif::VK_EXT_depth_range_unrestricted[]
1478****
1479
1480include::{generated}/validity/structs/VkViewport.txt[]
1481--
1482