## 23.5. Controlling the Viewport

The viewport transformation is determined by the selected viewport’s width and height in pixels, $p_x$ and $p_y$ , respectively, and its center $(o_x, o_y)$ (also in pixels), as well as its depth range min and max determining a depth range scale value $p_z$ and a depth range bias value $o_z$ (defined below). The vertex’s framebuffer coordinates, $\left(\begin{array}{c} x_f \\ y_f \\ z_f \end{array}\right),$ are given by

$ \left(\begin{array}{c} x_f \\ y_f \\ z_f \end{array}\right) = \left(\begin{array}{c} \frac{ p_x }{ 2 } x_d + o_x \\ \frac{ p_y }{ 2 } y_d + o_y \\ p_z \times z_d + o_z \end{array}\right). $

Multiple viewports are available, numbered zero up to `VkPhysicalDeviceLimits`::`maxViewports` minus one. The number of viewports used by a pipeline is controlled by the `viewportCount` member of the `VkPipelineViewportStateCreateInfo` structure used in pipeline creation.

The `VkPipelineViewportStateCreateInfo` structure is defined as:

    typedef struct VkPipelineViewportStateCreateInfo {
        VkStructureType                       sType;
        const void*                           pNext;
        VkPipelineViewportStateCreateFlags    flags;
        uint32_t                              viewportCount;
        const VkViewport*                     pViewports;
        uint32_t                              scissorCount;
        const VkRect2D*                       pScissors;
    } VkPipelineViewportStateCreateInfo;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `flags` is reserved for future use.
- `viewportCount` is the number of viewports used by the pipeline.
- `pViewports` is a pointer to an array of `VkViewport` structures, defining the viewport transforms. If the viewport state is dynamic, this member is ignored.
- `scissorCount` is the number of scissors and must match the number of viewports.
- `pScissors` is a pointer to an array of `VkRect2D` structures which define the rectangular bounds of the scissor for the corresponding viewport. If the scissor state is dynamic, this member is ignored.

If a geometry shader is active and has an output variable decorated with `ViewportIndex`, the viewport transformation uses the viewport corresponding to the value assigned to `ViewportIndex` taken from an implementation-dependent vertex of each primitive. If `ViewportIndex` is outside the range zero to `viewportCount` minus one for a primitive, or if the geometry shader did not assign a value to `ViewportIndex` for all vertices of a primitive due to flow control, the results of the viewport transformation of the vertices of such primitives are undefined. If no geometry shader is active, or if the geometry shader does not have an output decorated with `ViewportIndex`, the viewport numbered zero is used by the viewport transformation.

A single vertex can be used in more than one individual primitive, in primitives such as `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP`. In this case, the viewport transformation is applied separately for each primitive.

If the bound pipeline state object was not created with the `VK_DYNAMIC_STATE_VIEWPORT` dynamic state enabled, viewport transformation parameters are specified using the `pViewports` member of `VkPipelineViewportStateCreateInfo` in the pipeline state object. If the pipeline state object was created with the `VK_DYNAMIC_STATE_VIEWPORT` dynamic state enabled, the viewport transformation parameters are dynamically set and changed with the command:

    void vkCmdSetViewport(
        VkCommandBuffer                             commandBuffer,
        uint32_t                                    firstViewport,
        uint32_t                                    viewportCount,
        const VkViewport*                           pViewports);

- `commandBuffer` is the command buffer into which the command will be recorded.
- `firstViewport` is the index of the first viewport whose parameters are updated by the command.
- `viewportCount` is the number of viewports whose parameters are updated by the command.
- `pViewports` is a pointer to an array of `VkViewport` structures specifying viewport parameters.

The viewport parameters taken from element $i$ of `pViewports` replace the current state for the viewport index $\mathit{firstViewport}+i$ , for $i$ in $[0, viewportCount)$ .

Both `VkPipelineViewportStateCreateInfo` and `vkCmdSetViewport` use `VkViewport` to set the viewport transformation parameters.

The `VkViewport` structure is defined as:

    typedef struct VkViewport {
        float    x;
        float    y;
        float    width;
        float    height;
        float    minDepth;
        float    maxDepth;
    } VkViewport;

- `x` and `y` are the viewport’s upper left corner $(x,y)$ .
- `width` and `height` are the viewport’s width and height, respectively.
- `minDepth` and `maxDepth` are the depth range for the viewport. It is valid for `minDepth` to be greater than or equal to `maxDepth`.

The framebuffer depth coordinate $z_f$ may be represented using either a fixed-point or floating-point representation. However, a floating-point representation must be used if the depth/stencil attachment has a floating-point depth component. If an $m$ -bit fixed-point representation is used, we assume that it represents each value $\frac{k}{2^m - 1}$ , where $k \in \{ 0,1, \ldots, 2^m-1 \}$ , as $k$ (e.g. 1.0 is represented in binary as a string of all ones).

The viewport parameters shown in the above equations are found from these values as

\begin{align*} o_x & = x + \frac{width}{2} \\ o_y & = y + \frac{height}{2} \\ o_z & = minDepth \\ p_x & = width \\ p_y & = height \\ p_z & = maxDepth - minDepth. \end{align*}

The width and height of the implementation-dependent maximum viewport dimensions must be greater than or equal to the width and height of the largest image which can be created and attached to a framebuffer.

The floating-point viewport bounds are represented with an implementation-dependent precision.