// Copyright (c) 2018-2020 NVIDIA Corporation
//
// SPDX-License-Identifier: CC-BY-4.0

include::{generated}/meta/{refprefix}VK_NV_fragment_shader_barycentric.adoc[]

=== Other Extension Metadata

*Last Modified Date*::
    2018-08-03
*IP Status*::
    No known IP claims.
*Interactions and External Dependencies*::
  - This extension provides API support for
    {GLSLregistry}/nv/GLSL_NV_fragment_shader_barycentric.txt[`GL_NV_fragment_shader_barycentric`]
*Contributors*::
  - Pat Brown, NVIDIA
  - Daniel Koch, NVIDIA

=== Description

This extension adds support for the following SPIR-V extension in Vulkan:

  * {spirv}/NV/SPV_NV_fragment_shader_barycentric.html[`SPV_NV_fragment_shader_barycentric`]

The extension provides access to three additional fragment shader variable
decorations in SPIR-V:

  * code:PerVertexNV, which indicates that a fragment shader input will not
    have interpolated values, but instead must be accessed with an extra
    array index that identifies one of the vertices of the primitive
    producing the fragment
  * code:BaryCoordNV, which indicates that the variable is a three-component
    floating-point vector holding barycentric weights for the fragment
    produced using perspective interpolation
  * code:BaryCoordNoPerspNV, which indicates that the variable is a
    three-component floating-point vector holding barycentric weights for
    the fragment produced using linear interpolation

When using GLSL source-based shader languages, the following variables from
`GL_NV_fragment_shader_barycentric` maps to these SPIR-V built-in
decorations:

  * `in vec3 gl_BaryCoordNV;` -> code:BaryCoordNV
  * `in vec3 gl_BaryCoordNoPerspNV;` -> code:BaryCoordNoPerspNV

GLSL variables declared using the code:__pervertexNV GLSL qualifier are
expected to be decorated with code:PerVertexNV in SPIR-V.

=== Promotion to `VK_KHR_fragment_shader_barycentric`

All functionality in this extension is included in
`apiext:VK_KHR_fragment_shader_barycentric`, with the suffix changed to KHR.

include::{generated}/interfaces/VK_NV_fragment_shader_barycentric.adoc[]

=== New Built-In Variables

  * <<interfaces-builtin-variables-barycoordkhr,code:BaryCoordNV>>
  * <<interfaces-builtin-variables-barycoordnoperspkhr,code:BaryCoordNoPerspNV>>

=== New SPIR-V Decorations

  * <<shaders-interpolation-decorations-pervertexkhr,code:PerVertexNV>>

=== New SPIR-V Capabilities

  * <<spirvenv-capabilities-table-FragmentBarycentricKHR,
    code:FragmentBarycentricNV>>

=== Issues

(1) The AMD_shader_explicit_vertex_parameter extension provides similar
    functionality.
    Why write a new extension, and how is this extension different?

*RESOLVED*: For the purposes of Vulkan/SPIR-V, we chose to implement a
separate extension due to several functional differences.

First, the hardware supporting this extension can provide a three-component
barycentric weight vector for variables decorated with code:BaryCoordNV,
while variables decorated with code:BaryCoordSmoothAMD provide only two
components.
In some cases, it may be more efficient to explicitly interpolate an
attribute via:

        float value = (baryCoordNV.x * v[0].attrib +
                       baryCoordNV.y * v[1].attrib +
                       baryCoordNV.z * v[2].attrib);

instead of

       float value = (baryCoordSmoothAMD.x * (v[0].attrib - v[2].attrib) +
                      baryCoordSmoothAMD.y * (v[1].attrib - v[2].attrib) +
                      v[2].attrib);

Additionally, the semantics of the decoration code:BaryCoordPullModelAMD do
not appear to map to anything supported by the initial hardware
implementation of this extension.

This extension provides a smaller number of decorations than the AMD
extension, as we expect that shaders could derive variables decorated with
things like code:BaryCoordNoPerspCentroidAMD with explicit attribute
interpolation instructions.
One other relevant difference is that explicit per-vertex attribute access
using this extension does not require a constant vertex number.

(2) Why do the built-in SPIR-V decorations for this extension include two
separate built-ins code:BaryCoordNV and code:BaryCoordNoPerspNV when a "`no
perspective`" variable could be decorated with code:BaryCoordNV and
code:NoPerspective?

*RESOLVED*: The SPIR-V extension for this feature chose to mirror the
behavior of the GLSL extension, which provides two built-in variables.
Additionally, it is not clear that its a good idea (or even legal) to have
two variables using the "`same attribute`", but with different interpolation
modifiers.

=== Version History

  * Revision 1, 2018-08-03 (Pat Brown)
  ** Internal revisions
