• 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 \\
6500 \leq z_c \leq w_c
651\end{array}
652++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
653
654This view volume can: be further restricted by as many as
655sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined
656half-spaces.
657
658The cull volume is the intersection of up to
659sname:VkPhysicalDeviceLimits::pname:maxCullDistances client-defined
660half-spaces (if no client-defined cull half-spaces are enabled, culling
661against the cull volume is skipped).
662
663A shader must: write a single cull distance for each enabled cull half-space
664to elements of the code:CullDistance array.
665If the cull distance for any enabled cull half-space is negative for all of
666the vertices of the primitive under consideration, the primitive is
667discarded.
668Otherwise the primitive is clipped against the clip volume as defined below.
669
670The clip volume is the intersection of up to
671sname:VkPhysicalDeviceLimits::pname:maxClipDistances client-defined
672half-spaces with the view volume (if no client-defined clip half-spaces are
673enabled, the clip volume is the view volume).
674
675A shader must: write a single clip distance for each enabled clip half-space
676to elements of the code:ClipDistance array.
677Clip half-space [eq]#i# is then given by the set of points satisfying the
678inequality
679
680  {empty}:: [eq]#c~i~(**P**) {geq} 0#
681
682where [eq]#c~i~(**P**)# is the clip distance [eq]#i# at point [eq]#**P**#.
683For point primitives, [eq]#c~i~(**P**)# is simply the clip distance for the
684vertex in question.
685For line and triangle primitives, per-vertex clip distances are interpolated
686using a weighted mean, with weights derived according to the algorithms
687described in sections <<primsrast-lines-basic,Basic Line Segment
688Rasterization>> and <<primsrast-polygons-basic,Basic Polygon
689Rasterization>>, using the perspective interpolation equations.
690
691The number of client-defined clip and cull half-spaces that are enabled is
692determined by the explicit size of the built-in arrays code:ClipDistance and
693code:CullDistance, respectively, declared as an output in the interface of
694the entry point of the final shader stage before clipping.
695
696ifdef::VK_EXT_depth_clip_enable[]
697If slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT is present in
698the graphics pipeline state then depth clipping is disabled if
699slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT::pname:depthClipEnable
700is ename:VK_FALSE.
701Otherwise, if slink:VkPipelineRasterizationDepthClipStateCreateInfoEXT is
702not present, depth clipping is disabled when
703slink:VkPipelineRasterizationStateCreateInfo::pname:depthClampEnable is
704ename:VK_TRUE.
705endif::VK_EXT_depth_clip_enable[]
706ifndef::VK_EXT_depth_clip_enable[]
707Depth clamping is enabled or disabled via the pname:depthClampEnable enable
708of the slink:VkPipelineRasterizationStateCreateInfo structure.
709Depth clipping is disabled when pname:depthClampEnable is ename:VK_TRUE.
710endif::VK_EXT_depth_clip_enable[]
711When depth clipping is disabled, the plane equation
712
713  {empty}:: [eq]#0 {leq} z~c~ {leq} w~c~#
714
715(see the clip volume definition above) is ignored by view volume clipping
716(effectively, there is no near or far plane clipping).
717
718If the primitive under consideration is a point or line segment, then
719clipping passes it unchanged if its vertices lie entirely within the clip
720volume.
721
722ifndef::VK_VERSION_1_1,VK_KHR_maintenance2[]
723If a point's vertex lies outside of the clip volume, the entire primitive
724may: be discarded.
725endif::VK_VERSION_1_1,VK_KHR_maintenance2[]
726
727ifdef::VK_VERSION_1_1,VK_KHR_maintenance2[]
728[open,refpage='VkPointClippingBehavior',desc='Enum specifying the point clipping behavior',type='enums']
729--
730Possible values of
731slink:VkPhysicalDevicePointClippingProperties::pname:pointClippingBehavior,
732specifying clipping behavior of a point primitive whose vertex lies outside
733the clip volume, are:
734
735include::{generated}/api/enums/VkPointClippingBehavior.txt[]
736
737ifdef::VK_KHR_maintenance2[]
738or the equivalent
739
740include::{generated}/api/enums/VkPointClippingBehaviorKHR.txt[]
741endif::VK_KHR_maintenance2[]
742
743  * ename:VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES specifies that the
744    primitive is discarded if the vertex lies outside any clip plane,
745    including the planes bounding the view volume.
746  * ename:VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY specifies that
747    the primitive is discarded only if the vertex lies outside any user clip
748    plane.
749--
750endif::VK_VERSION_1_1,VK_KHR_maintenance2[]
751
752If either of a line segment's vertices lie outside of the clip volume, the
753line segment may: be clipped, with new vertex coordinates computed for each
754vertex that lies outside the clip volume.
755A clipped line segment endpoint lies on both the original line segment and
756the boundary of the clip volume.
757
758This clipping produces a value, [eq]#0 {leq} t {leq} 1#, for each clipped
759vertex.
760If the coordinates of a clipped vertex are [eq]#**P**# and the unclipped
761line segment's vertex coordinates are [eq]#**P**~1~# and [eq]#**P**~2~#,
762then [eq]#t# satisfies the following equation
763
764  {empty}:: [eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#.
765
766[eq]#t# is used to clip vertex output attributes as described in
767<<vertexpostproc-clipping-shader-outputs,Clipping Shader Outputs>>.
768
769If the primitive is a polygon, it passes unchanged if every one of its edges
770lies entirely inside the clip volume, and is either clipped or discarded
771otherwise.
772If the edges of the polygon intersect the boundary of the clip volume, the
773intersecting edges are reconnected by new edges that lie along the boundary
774of the clip volume - in some cases requiring the introduction of new
775vertices into a polygon.
776
777If a polygon intersects an edge of the clip volume's boundary, the clipped
778polygon must: include a point on this boundary edge.
779
780Primitives rendered with user-defined half-spaces must: satisfy a
781complementarity criterion.
782Suppose a series of primitives is drawn where each vertex [eq]#i# has a
783single specified clip distance [eq]#d~i~# (or a number of similarly
784specified clip distances, if multiple half-spaces are enabled).
785Next, suppose that the same series of primitives are drawn again with each
786such clip distance replaced by [eq]#-d~i~# (and the graphics pipeline is
787otherwise the same).
788In this case, primitives must: not be missing any pixels, and pixels must:
789not be drawn twice in regions where those primitives are cut by the clip
790planes.
791
792
793[[vertexpostproc-clipping-shader-outputs]]
794== Clipping Shader Outputs
795
796Next, vertex output attributes are clipped.
797The output values associated with a vertex that lies within the clip volume
798are unaffected by clipping.
799If a primitive is clipped, however, the output values assigned to vertices
800produced by clipping are clipped.
801
802Let the output values assigned to the two vertices [eq]#**P**~1~# and
803[eq]#**P**~2~# of an unclipped edge be [eq]#**c**~1~# and [eq]#**c**~2~#.
804The value of [eq]#t# (see <<vertexpostproc-clipping,Primitive Clipping>>)
805for a clipped point [eq]#**P**# is used to obtain the output value
806associated with [eq]#**P**# as
807
808  {empty}:: [eq]#**c** = t **c**~1~ {plus} (1-t) **c**~2~#.
809
810(Multiplying an output value by a scalar means multiplying each of _x_, _y_,
811_z_, and _w_ by the scalar.)
812
813Since this computation is performed in clip space before division by
814[eq]#w~c~#, clipped output values are perspective-correct.
815
816Polygon clipping creates a clipped vertex along an edge of the clip volume's
817boundary.
818This situation is handled by noting that polygon clipping proceeds by
819clipping against one half-space at a time.
820Output value clipping is done in the same way, so that clipped points always
821occur at the intersection of polygon edges (possibly already clipped) with
822the clip volume's boundary.
823
824For vertex output attributes whose matching fragment input attributes are
825decorated with code:NoPerspective, the value of [eq]#t# used to obtain the
826output value associated with [eq]#**P**# will be adjusted to produce results
827that vary linearly in framebuffer space.
828
829Output attributes of integer or unsigned integer type must: always be flat
830shaded.
831Flat shaded attributes are constant over the primitive being rasterized (see
832<<primsrast-lines-basic,Basic Line Segment Rasterization>> and
833<<primsrast-polygons-basic,Basic Polygon Rasterization>>), and no
834interpolation is performed.
835The output value [eq]#**c**# is taken from either [eq]#**c**~1~# or
836[eq]#**c**~2~#, since flat shading has already occurred and the two values
837are identical.
838
839ifdef::VK_NV_clip_space_w_scaling[]
840include::VK_NV_clip_space_w_scaling/vertexpostproc.txt[]
841endif::VK_NV_clip_space_w_scaling[]
842
843
844[[vertexpostproc-coord-transform]]
845== Coordinate Transformations
846
847_Clip coordinates_ for a vertex result from shader execution, which yields a
848vertex coordinate code:Position.
849
850Perspective division on clip coordinates yields _normalized device
851coordinates_, followed by a _viewport_ transformation (see
852<<vertexpostproc-viewport,Controlling the Viewport>>) to convert these
853coordinates into _framebuffer coordinates_.
854
855If a vertex in clip coordinates has a position given by
856
857[latexmath]
858++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
859\left(\begin{array}{c}
860x_c \\
861y_c \\
862z_c \\
863w_c
864\end{array}\right)
865++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
866
867then the vertex's normalized device coordinates are
868[latexmath]
869++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
870\left(
871        \begin{array}{c}
872                x_d \\
873                y_d \\
874                z_d
875        \end{array}
876\right) =
877\left(
878        \begin{array}{c}
879                \frac{x_c}{w_c} \\
880                \frac{y_c}{w_c} \\
881                \frac{z_c}{w_c}
882        \end{array}
883\right)
884++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
885
886
887ifdef::VK_QCOM_render_pass_transform[]
888[[vertexpostproc-renderpass-transform]]
889== Render Pass Transform
890
891A _render pass transform_ can: be enabled for render pass instances.
892The clip coordinates [eq]#(x~c~, y~c~)# that result from vertex shader
893execution are transformed by a rotation of 0, 90, 180, or 270 degrees in the
894XY plane, centered at the origin.
895
896When _Render pass transform_ is enabled, the transform applies to all
897primitives for all subpasses of the render pass.
898The transformed vertex in clip coordinates has a position given by
899
900[latexmath]
901++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
902\left(
903        \begin{array}{c}
904                x_{c_{trans}} \\
905                y_{c_{trans}} \\
906                z_{c_{trans}}
907        \end{array}
908\right) =
909\left(
910        \begin{array}{c}
911                x_{c} \cos \theta - y_{c} \sin \theta \\
912                x_{c} \sin \theta + y_{c} \cos \theta \\
913                z_c
914        \end{array}
915\right)
916++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
917
918where
919
920  * _[eq]#{theta}#_ is 0 degrees for
921    ename:VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
922  * _[eq]#{theta}#_ is 90 degrees for
923    ename:VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR
924  * _[eq]#{theta}#_ is 180 degrees for
925    ename:VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR
926  * _[eq]#{theta}#_ is 270 degrees for
927    ename:VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR
928
929
930The transformed vertex's normalized device coordinates are
931[latexmath]
932++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
933\left(
934        \begin{array}{c}
935                x_d \\
936                y_d \\
937                z_d
938        \end{array}
939\right) =
940\left(
941        \begin{array}{c}
942                \frac{x_{c_{trans}}}{w_c} \\
943                \frac{y_{c_{trans}}}{w_c} \\
944                \frac{z_{c_{trans}}}{w_c}
945        \end{array}
946\right)
947++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
948
949
950When render pass transform is enabled for a render pass instance, the
951following additional features are enabled:
952
953  * Each slink:VkViewport specified by either
954    slink:VkPipelineViewportStateCreateInfo::pname:pViewports or
955    flink:vkCmdSetViewport will have its width/height [eq]#(p~x~, p~y~)# and
956    its center [eq]#(o~x~, o~y~)# similarly transformed by the
957    implementation.
958  * Each scissor specified by
959    slink:VkPipelineViewportStateCreateInfo::pname:pScissors or
960    flink:vkCmdSetScissor will have its [eq]#(offset~x~, offset~y~)# and
961    [eq]#(extent~x~, extent~y~)# similarly transformed by the
962    implementation.
963  * The pname:renderArea specified in
964    slink:VkCommandBufferInheritanceRenderPassTransformInfoQCOM and
965    slink:VkRenderPassBeginInfo will be similarly transformed by the
966    implementation.
967  * The [eq]#(x, y)# components of shader variables with built-in
968    decorations code:FragCoord, code:SamplePosition, or code:PointCoord will
969    be similarly transformed by the implementation.
970  * The [eq]#(x,y)# components of the code:offset operand of the
971    code:InterpolateAtOffset extended instruction will be similarly
972    transformed by the implementation.
973  * The values returned by SPIR-V <<shaders-derivative-operations,
974    derivative instructions>> code:OpDPdx, code:OpDPdy, code:OpDPdxCourse,
975    code:OpDPdyCourse, code:OpDPdxFine, code:OpDPdyFine will be similarly
976    transformed by the implementation.
977
978
979The net result of the above, is that applications can: act as if rendering
980to a framebuffer oriented with the
981slink:VkSurfaceCapabilitiesKHR::pname:currentTransform.
982In other words, applications can: act as if the presentation engine will be
983performing the transformation of the swapchain image after rendering and
984prior to presentation to the user.
985In fact, the transformation of the various items cited above are being
986handled by the implementation as the rendering takes place.
987
988endif::VK_QCOM_render_pass_transform[]
989
990
991[[vertexpostproc-viewport]]
992== Controlling the Viewport
993
994The viewport transformation is determined by the selected viewport's width
995and height in pixels, [eq]#p~x~# and [eq]#p~y~#, respectively, and its
996center [eq]#(o~x~, o~y~)# (also in pixels), as well as its depth range min
997and max determining a depth range scale value [eq]#p~z~# and a depth range
998bias value [eq]#o~z~# (defined below).
999The vertex's framebuffer coordinates [eq]#(x~f~, y~f~, z~f~)# are given by
1000
1001  {empty}:: [eq]#x~f~ = (p~x~ / 2) x~d~ {plus} o~x~#
1002  {empty}:: [eq]#y~f~ = (p~y~ / 2) y~d~ {plus} o~y~#
1003  {empty}:: [eq]#z~f~ = p~z~ {times} z~d~ {plus} o~z~#
1004
1005Multiple viewports are available, numbered zero up to
1006sname:VkPhysicalDeviceLimits::pname:maxViewports minus one.
1007The number of viewports used by a pipeline is controlled by the
1008pname:viewportCount member of the sname:VkPipelineViewportStateCreateInfo
1009structure used in pipeline creation.
1010
1011[eq]#x~f~# and [eq]#y~f~# have limited precision, where the number of
1012fractional bits retained is specified by
1013sname:VkPhysicalDeviceLimits::pname:subPixelPrecisionBits.
1014ifdef::VK_EXT_line_rasterization[]
1015When rasterizing <<primsrast-lines,line segments>>, the number of fractional
1016bits is specified by
1017sname:VkPhysicalDeviceLineRasterizationPropertiesEXT::pname:lineSubPixelPrecisionBits.
1018endif::VK_EXT_line_rasterization[]
1019
1020[open,refpage='VkPipelineViewportStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline viewport state',type='structs']
1021--
1022The sname:VkPipelineViewportStateCreateInfo structure is defined as:
1023
1024include::{generated}/api/structs/VkPipelineViewportStateCreateInfo.txt[]
1025
1026  * pname:sType is the type of this structure.
1027  * pname:pNext is `NULL` or a pointer to a structure extending this
1028    structure.
1029  * pname:flags is reserved for future use.
1030  * pname:viewportCount is the number of viewports used by the pipeline.
1031  * pname:pViewports is a pointer to an array of slink:VkViewport
1032    structures, defining the viewport transforms.
1033    If the viewport state is dynamic, this member is ignored.
1034  * pname:scissorCount is the number of <<fragops-scissor,scissors>> and
1035    must: match the number of viewports.
1036  * pname:pScissors is a pointer to an array of slink:VkRect2D structures
1037    defining the rectangular bounds of the scissor for the corresponding
1038    viewport.
1039    If the scissor state is dynamic, this member is ignored.
1040
1041.Valid Usage
1042****
1043  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216]]
1044    If the <<features-multiViewport,multiple viewports>> feature is not
1045    enabled, pname:viewportCount must: not be greater than `1`
1046  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217]]
1047    If the <<features-multiViewport,multiple viewports>> feature is not
1048    enabled, pname:scissorCount must: not be greater than `1`
1049  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218]]
1050    pname:viewportCount must: be less than or equal to
1051    sname:VkPhysicalDeviceLimits::pname:maxViewports
1052  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219]]
1053    pname:scissorCount must: be less than or equal to
1054    sname:VkPhysicalDeviceLimits::pname:maxViewports
1055ifndef::VK_EXT_extended_dynamic_state[]
1056  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220]]
1057    pname:scissorCount and pname:viewportCount must: be identical
1058endif::VK_EXT_extended_dynamic_state[]
1059  * [[VUID-VkPipelineViewportStateCreateInfo-x-02821]]
1060    The pname:x and pname:y members of pname:offset member of any element of
1061    pname:pScissors must: be greater than or equal to `0`
1062  * [[VUID-VkPipelineViewportStateCreateInfo-offset-02822]]
1063    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# must: not
1064    cause a signed integer addition overflow for any element of
1065    pname:pScissors
1066  * [[VUID-VkPipelineViewportStateCreateInfo-offset-02823]]
1067    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# must:
1068    not cause a signed integer addition overflow for any element of
1069    pname:pScissors
1070ifndef::VK_EXT_extended_dynamic_state[]
1071  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength]]
1072    pname:viewportCount must: be greater than `0`
1073  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength]]
1074    pname:scissorCount must: be greater than `0`
1075endif::VK_EXT_extended_dynamic_state[]
1076ifdef::VK_EXT_extended_dynamic_state[]
1077  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134]]
1078    If the graphics pipeline is being created without
1079    ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT and
1080    ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set then
1081    pname:scissorCount and pname:viewportCount must: be identical
1082  * [[VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135]]
1083    If the graphics pipeline is being created with
1084    ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT set then
1085    pname:viewportCount must: be `0`, otherwise it must: be greater than `0`
1086  * [[VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136]]
1087    If the graphics pipeline is being created with
1088    ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set then
1089    pname:scissorCount must: be `0`, otherwise it must: be greater than `0`
1090endif::VK_EXT_extended_dynamic_state[]
1091ifdef::VK_NV_clip_space_w_scaling[]
1092  * [[VUID-VkPipelineViewportStateCreateInfo-viewportWScalingEnable-01726]]
1093    If the pname:viewportWScalingEnable member of a
1094    slink:VkPipelineViewportWScalingStateCreateInfoNV structure included in
1095    the pname:pNext chain is ename:VK_TRUE, the pname:viewportCount member
1096    of the slink:VkPipelineViewportWScalingStateCreateInfoNV structure must:
1097    be greater than or equal to
1098    slink:VkPipelineViewportStateCreateInfo::pname:viewportCount
1099endif::VK_NV_clip_space_w_scaling[]
1100****
1101
1102include::{generated}/validity/structs/VkPipelineViewportStateCreateInfo.txt[]
1103--
1104
1105ifdef::VK_EXT_extended_dynamic_state[]
1106[open,refpage='vkCmdSetViewportWithCountEXT',desc='Set the viewport count and viewports dynamically for a command buffer',type='protos']
1107--
1108To <<pipelines-dynamic-state, dynamically set>> the viewport count and
1109viewports, call:
1110
1111include::{generated}/api/protos/vkCmdSetViewportWithCountEXT.txt[]
1112
1113  * pname:commandBuffer is the command buffer into which the command will be
1114    recorded.
1115  * pname:viewportCount specifies the viewport count.
1116  * pname:pViewports specifies the viewports to use for drawing.
1117
1118This command sets the viewport count and viewports state for subsequent
1119drawing commands when the graphics pipeline is created with
1120ename:VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT set in
1121slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1122Otherwise, this state is specified by the corresponding
1123slink:VkPipelineViewportStateCreateInfo::pname:viewportCount and
1124pname:pViewports values used to create the currently active pipeline.
1125
1126.Valid Usage
1127****
1128  * [[VUID-vkCmdSetViewportWithCountEXT-None-03393]]
1129    The <<features-extendedDynamicState, extendedDynamicState>> feature
1130    must: be enabled
1131  * [[VUID-vkCmdSetViewportWithCountEXT-viewportCount-03394]]
1132    pname:viewportCount must: be between `1` and
1133    sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1134  * [[VUID-vkCmdSetViewportWithCountEXT-viewportCount-03395]]
1135    If the <<features-multiViewport,multiple viewports>> feature is not
1136    enabled, pname:viewportCount must: be `1`
1137ifdef::VK_NV_inherited_viewport_scissor[]
1138  * [[VUID-vkCmdSetViewportWithCountEXT-commandBuffer-04819]]
1139    pname:commandBuffer must: not have
1140    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1141    enabled
1142endif::VK_NV_inherited_viewport_scissor[]
1143****
1144
1145include::{generated}/validity/protos/vkCmdSetViewportWithCountEXT.txt[]
1146--
1147
1148[open,refpage='vkCmdSetScissorWithCountEXT',desc='Set the scissor count and scissor rectangular bounds dynamically for a command buffer',type='protos']
1149--
1150To <<pipelines-dynamic-state, dynamically set>> the scissor count and
1151scissor rectangular bounds, call:
1152
1153include::{generated}/api/protos/vkCmdSetScissorWithCountEXT.txt[]
1154
1155  * pname:commandBuffer is the command buffer into which the command will be
1156    recorded.
1157  * pname:scissorCount specifies the scissor count.
1158  * pname:pScissors specifies the scissors to use for drawing.
1159
1160This command sets the scissor count and scissor rectangular bounds state for
1161subsequence drawing commands when the graphics pipeline is created with
1162ename:VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT set in
1163slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1164Otherwise, this state is specified by the corresponding
1165slink:VkPipelineViewportStateCreateInfo::pname:scissorCount and
1166pname:pScissors values used to create the currently active pipeline.
1167
1168.Valid Usage
1169****
1170  * [[VUID-vkCmdSetScissorWithCountEXT-None-03396]]
1171    The <<features-extendedDynamicState, extendedDynamicState>> feature
1172    must: be enabled
1173  * [[VUID-vkCmdSetScissorWithCountEXT-scissorCount-03397]]
1174    pname:scissorCount must: be between `1` and
1175    sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1176  * [[VUID-vkCmdSetScissorWithCountEXT-scissorCount-03398]]
1177    If the <<features-multiViewport,multiple viewports>> feature is not
1178    enabled, pname:scissorCount must: be `1`
1179  * [[VUID-vkCmdSetScissorWithCountEXT-x-03399]]
1180    The pname:x and pname:y members of pname:offset member of any element of
1181    pname:pScissors must: be greater than or equal to `0`
1182  * [[VUID-vkCmdSetScissorWithCountEXT-offset-03400]]
1183    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# must: not
1184    cause a signed integer addition overflow for any element of
1185    pname:pScissors
1186  * [[VUID-vkCmdSetScissorWithCountEXT-offset-03401]]
1187    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# must:
1188    not cause a signed integer addition overflow for any element of
1189    pname:pScissors
1190ifdef::VK_NV_inherited_viewport_scissor[]
1191  * [[VUID-vkCmdSetScissorWithCountEXT-commandBuffer-04820]]
1192    pname:commandBuffer must: not have
1193    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1194    enabled
1195endif::VK_NV_inherited_viewport_scissor[]
1196****
1197
1198include::{generated}/validity/protos/vkCmdSetScissorWithCountEXT.txt[]
1199--
1200endif::VK_EXT_extended_dynamic_state[]
1201
1202[open,refpage='VkPipelineViewportStateCreateFlags',desc='Reserved for future use',type='flags']
1203--
1204include::{generated}/api/flags/VkPipelineViewportStateCreateFlags.txt[]
1205
1206tname:VkPipelineViewportStateCreateFlags is a bitmask type for setting a
1207mask, but is currently reserved for future use.
1208--
1209
1210ifndef::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1211If a geometry shader is active and has an output variable decorated with
1212code:ViewportIndex, the viewport transformation uses the viewport
1213corresponding to the value assigned to code:ViewportIndex taken from an
1214implementation-dependent vertex of each primitive.
1215If code:ViewportIndex is outside the range zero to pname:viewportCount minus
1216one for a primitive, or if the geometry shader did not assign a value to
1217code:ViewportIndex for all vertices of a primitive due to flow control, the
1218values resulting from the viewport transformation of the vertices of such
1219primitives are undefined:.
1220If no geometry shader is active, or if the geometry shader does not have an
1221output decorated with code:ViewportIndex, the viewport numbered zero is used
1222by the viewport transformation.
1223endif::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1224
1225ifdef::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1226ifdef::VK_NV_viewport_array2[]
1227A _<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1228stage>>_ can: direct each primitive to zero or more viewports.
1229The destination viewports for a primitive are selected by the last active
1230<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1231stage>> that has an output variable decorated with code:ViewportIndex
1232(selecting a single viewport) or code:ViewportMaskNV (selecting multiple
1233viewports).
1234The viewport transform uses the viewport corresponding to either the value
1235assigned to code:ViewportIndex or one of the bits set in
1236code:ViewportMaskNV, and taken from an implementation-dependent vertex of
1237each primitive.
1238If code:ViewportIndex or any of the bits in code:ViewportMaskNV are outside
1239the range zero to pname:viewportCount minus one for a primitive, or if the
1240last active <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1241shader stage>> did not assign a value to either code:ViewportIndex or
1242code:ViewportMaskNV for all vertices of a primitive due to flow control, the
1243values resulting from the viewport transformation of the vertices of such
1244primitives are undefined:.
1245If the last <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1246shader stage>> does not have an output decorated with code:ViewportIndex or
1247code:ViewportMaskNV, the viewport numbered zero is used by the viewport
1248transformation.
1249endif::VK_NV_viewport_array2[]
1250ifndef::VK_NV_viewport_array2[]
1251A _<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1252stage>>_ can: direct each primitive to one of several viewports.
1253The destination viewport for a primitive is selected by the last active
1254<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1255stage>> that has an output variable decorated with code:ViewportIndex.
1256The viewport transform uses the viewport corresponding to the value assigned
1257to code:ViewportIndex, and taken from an implementation-dependent vertex of
1258each primitive.
1259If code:ViewportIndex is outside the range zero to pname:viewportCount minus
1260one for a primitive, or if the last active
1261<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1262stage>> did not assign a value to code:ViewportIndex for all vertices of a
1263primitive due to flow control, the values resulting from the viewport
1264transformation of the vertices of such primitives are undefined:.
1265If the last <<pipeline-graphics-subsets-pre-rasterization,pre-rasterization
1266shader stage>> does not have an output decorated with code:ViewportIndex,
1267the viewport numbered zero is used by the viewport transformation.
1268endif::VK_NV_viewport_array2[]
1269endif::VK_VERSION_1_2,VK_EXT_shader_viewport_index_layer,VK_NV_viewport_array2[]
1270
1271A single vertex can: be used in more than one individual primitive, in
1272primitives such as ename:VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP.
1273In this case, the viewport transformation is applied separately for each
1274primitive.
1275
1276[open,refpage='vkCmdSetViewport',desc='Set the viewport dynamically for a command buffer',type='protos']
1277--
1278To <<pipelines-dynamic-state, dynamically set>> the viewport transformation
1279parameters, call:
1280
1281include::{generated}/api/protos/vkCmdSetViewport.txt[]
1282
1283  * pname:commandBuffer is the command buffer into which the command will be
1284    recorded.
1285  * pname:firstViewport is the index of the first viewport whose parameters
1286    are updated by the command.
1287  * pname:viewportCount is the number of viewports whose parameters are
1288    updated by the command.
1289  * pname:pViewports is a pointer to an array of slink:VkViewport structures
1290    specifying viewport parameters.
1291
1292This command sets the viewport transformation parameters state for
1293subsequent drawing commands when the graphics pipeline is created with
1294ename:VK_DYNAMIC_STATE_VIEWPORT set in
1295slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.
1296Otherwise, this state is specified by the
1297sname:VkPipelineViewportStateCreateInfo::pname:pViewports values used to
1298create the currently active pipeline.
1299
1300The viewport parameters taken from element [eq]#i# of pname:pViewports
1301replace the current state for the viewport index [eq]#pname:firstViewport
1302{plus} i#, for [eq]#i# in [eq]#[0, pname:viewportCount)#.
1303
1304.Valid Usage
1305****
1306  * [[VUID-vkCmdSetViewport-firstViewport-01223]]
1307    The sum of pname:firstViewport and pname:viewportCount must: be between
1308    `1` and sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
1309  * [[VUID-vkCmdSetViewport-firstViewport-01224]]
1310    If the <<features-multiViewport,multiple viewports>> feature is not
1311    enabled, pname:firstViewport must: be `0`
1312  * [[VUID-vkCmdSetViewport-viewportCount-01225]]
1313    If the <<features-multiViewport,multiple viewports>> feature is not
1314    enabled, pname:viewportCount must: be `1`
1315ifdef::VK_NV_inherited_viewport_scissor[]
1316  * [[VUID-vkCmdSetViewport-commandBuffer-04821]]
1317    pname:commandBuffer must: not have
1318    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
1319    enabled
1320endif::VK_NV_inherited_viewport_scissor[]
1321****
1322
1323include::{generated}/validity/protos/vkCmdSetViewport.txt[]
1324--
1325
1326Both slink:VkPipelineViewportStateCreateInfo and flink:vkCmdSetViewport use
1327sname:VkViewport to set the viewport transformation parameters.
1328
1329[open,refpage='VkViewport',desc='Structure specifying a viewport',type='structs']
1330--
1331The sname:VkViewport structure is defined as:
1332
1333include::{generated}/api/structs/VkViewport.txt[]
1334
1335  * pname:x and pname:y are the viewport's upper left corner [eq]#(x,y)#.
1336  * pname:width and pname:height are the viewport's width and height,
1337    respectively.
1338  * pname:minDepth and pname:maxDepth are the depth range for the viewport.
1339
1340[NOTE]
1341.Note
1342====
1343Despite their names, pname:minDepth can: be less than, equal to, or greater
1344than pname:maxDepth.
1345====
1346
1347The framebuffer depth coordinate [eq]#pname:z~f~# may: be represented using
1348either a fixed-point or floating-point representation.
1349However, a floating-point representation must: be used if the depth/stencil
1350attachment has a floating-point depth component.
1351If an [eq]#m#-bit fixed-point representation is used, we assume that it
1352represents each value latexmath:[\frac{k}{2^m - 1}], where [eq]#k {elem} {
13530, 1, ..., 2^m^-1 }#, as [eq]#k# (e.g. 1.0 is represented in binary as a
1354string of all ones).
1355
1356The viewport parameters shown in the above equations are found from these
1357values as
1358
1359  {empty}:: [eq]#o~x~ = pname:x {plus} pname:width / 2#
1360  {empty}:: [eq]#o~y~ = pname:y {plus} pname:height / 2#
1361  {empty}:: [eq]#o~z~ = pname:minDepth#
1362  {empty}:: [eq]#p~x~ = pname:width#
1363  {empty}:: [eq]#p~y~ = pname:height#
1364  {empty}:: [eq]#p~z~ = pname:maxDepth - pname:minDepth#.
1365
1366ifdef::VK_QCOM_render_pass_transform[]
1367If a render pass transform is enabled, the values [eq]#(p~x~,p~y~)# and
1368[eq]#(o~x~, o~y~)# defining the viewport are transformed as described in
1369<<vertexpostproc-renderpass-transform, render pass transform>> before
1370participating in the viewport transform.
1371endif::VK_QCOM_render_pass_transform[]
1372
1373ifdef::VK_VERSION_1_1,VK_KHR_maintenance1[]
1374The application can: specify a negative term for pname:height, which has the
1375effect of negating the y coordinate in clip space before performing the
1376transform.
1377When using a negative pname:height, the application should: also adjust the
1378pname:y value to point to the lower left corner of the viewport instead of
1379the upper left corner.
1380Using the negative pname:height allows the application to avoid having to
1381negate the y component of the code:Position output from the last
1382<<pipeline-graphics-subsets-pre-rasterization,pre-rasterization shader
1383stage>>.
1384endif::VK_VERSION_1_1,VK_KHR_maintenance1[]
1385
1386The width and height of the <<limits-maxViewportDimensions,
1387implementation-dependent maximum viewport dimensions>> must: be greater than
1388or equal to the width and height of the largest image which can: be created
1389and attached to a framebuffer.
1390
1391The floating-point viewport bounds are represented with an
1392<<limits-viewportSubPixelBits,implementation-dependent precision>>.
1393
1394.Valid Usage
1395****
1396  * [[VUID-VkViewport-width-01770]]
1397    pname:width must: be greater than `0.0`
1398  * [[VUID-VkViewport-width-01771]]
1399    pname:width must: be less than or equal to
1400    sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[0]
1401ifndef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1402  * [[VUID-VkViewport-height-01772]]
1403    pname:height must: be greater than `0.0`
1404endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1405  * [[VUID-VkViewport-height-01773]]
1406    The absolute value of pname:height must: be less than or equal to
1407    sname:VkPhysicalDeviceLimits::pname:maxViewportDimensions[1]
1408  * [[VUID-VkViewport-x-01774]]
1409    pname:x must: be greater than or equal to pname:viewportBoundsRange[0]
1410  * [[VUID-VkViewport-x-01232]]
1411    [eq]#(pname:x {plus} pname:width)# must: be less than or equal to
1412    pname:viewportBoundsRange[1]
1413  * [[VUID-VkViewport-y-01775]]
1414    pname:y must: be greater than or equal to pname:viewportBoundsRange[0]
1415ifdef::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1416  * [[VUID-VkViewport-y-01776]]
1417    pname:y must: be less than or equal to pname:viewportBoundsRange[1]
1418  * [[VUID-VkViewport-y-01777]]
1419    [eq]#(pname:y {plus} pname:height)# must: be greater than or equal to
1420    pname:viewportBoundsRange[0]
1421endif::VK_VERSION_1_1,VK_KHR_maintenance1,VK_AMD_negative_viewport_height[]
1422  * [[VUID-VkViewport-y-01233]]
1423    [eq]#(pname:y {plus} pname:height)# must: be less than or equal to
1424    pname:viewportBoundsRange[1]
1425ifdef::VK_EXT_depth_range_unrestricted[]
1426  * [[VUID-VkViewport-minDepth-01234]]
1427    Unless `apiext:VK_EXT_depth_range_unrestricted` extension is enabled
1428    pname:minDepth must: be between `0.0` and `1.0`, inclusive
1429endif::VK_EXT_depth_range_unrestricted[]
1430ifndef::VK_EXT_depth_range_unrestricted[]
1431  * [[VUID-VkViewport-minDepth-02540]]
1432    pname:minDepth must: be between `0.0` and `1.0`, inclusive
1433endif::VK_EXT_depth_range_unrestricted[]
1434ifdef::VK_EXT_depth_range_unrestricted[]
1435  * [[VUID-VkViewport-maxDepth-01235]]
1436    Unless `apiext:VK_EXT_depth_range_unrestricted` extension is enabled
1437    pname:maxDepth must: be between `0.0` and `1.0`, inclusive
1438endif::VK_EXT_depth_range_unrestricted[]
1439ifndef::VK_EXT_depth_range_unrestricted[]
1440  * [[VUID-VkViewport-maxDepth-02541]]
1441    pname:maxDepth must: be between `0.0` and `1.0`, inclusive
1442endif::VK_EXT_depth_range_unrestricted[]
1443****
1444
1445include::{generated}/validity/structs/VkViewport.txt[]
1446--
1447