VK_KHR_fragment_shader_barycentric.proposal
This document details the VK_KHR_fragment_shader_barcentric extension, which adds a cross-vendor way to access barycentric coordinates in a fragment shader.
Problem Statement
Barycentric coordinates are widely used in computer graphics, and are an important building block for various algorithms. By being able to access the location of a pixel within a primitive and the non-interpolated attributes at the vertices, pixel shaders are able to perform things such as custom attribute interpolation or effects based on the pixel’s location within a primitive.
Solution Space
Two options have been considered:
- Take VK_NV_fragment_shader_barycentric and add any new required properties and behaviors.
 - Start afresh
 
This proposal focuses on the first option.
Proposal
New SPIR-V decorations
A new SPIR-V extension SPV_KHR_fragment_shader_barycentric adds three fragment shader variable decorations:
PerVertexKHR, 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 fragmentBaryCoordKHR, which indicates that the variable is a three-component floating-point vector holding barycentric weights for the fragment produced using perspective interpolationBaryCoordNoPerspKHR, which indicates that the variable is a three-component floating-point vector holding barycentric weights for the fragment produced using linear interpolation
Barycentric weights
- For point primitives, 
BaryCoordKHRandBaryCoordNoPerspKHRare assigned the value (1,0,0). - For line primitives, 
BaryCoordKHRandBaryCoordNoPerspKHRare assigned the values (1,0,0) and (0,1,0) at the ends of the primitive. - For polygon primitives, 
BaryCoordKHRandBaryCoordNoPerspKHRare assigned the values (1,0,0), (0,1,0), and (0,0,1) at the three vertices. 
Per-vertex attributes
Per-vertex attributes for "missing" vertices, such as the third vertex of a line primitive, will return values from the valid vertex with the highest index.
Vertices are numbered as follows:
| Primitive Topology | Vertex 0 | Vertex 1 | Vertex 2 | 
|---|---|---|---|
i  | i  | i  | |
2i  | 2i+1  | 2i+1  | |
i  | i+1  | i+1  | |
3i  | 3i+1  | 3i+2  | |
i  | i+1  | i+2  | |
i  | i+2  | i+1  | |
i+1  | i+2  | 0  | |
4i+1  | 4i+2  | 4i+2  | |
i+1  | i+2  | i+2  | |
6i  | 6i+2  | 6i+4  | |
2i  | 2i+2  | 2i+4  | |
2i  | 2i+4  | 2i+2  | 
When the provoking vertex mode is VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the original vertex numbers used are the same as above except as indicated in the table below.
| Primitive Topology | Vertex 0 | Vertex 1 | Vertex 2 | 
|---|---|---|---|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP (odd, and   | i+1  | i  | i+2  | 
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN  | 0  | i+1  | i+2  | 
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY (odd)  | 2i+2  | 2i  | 2i+4  | 
Properties
A new property structure is added:
typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           triStripVertexOrderIndependentOfProvokingVertex;
} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR;
The triStripVertexOrderIndependentOfProvokingVertex property indicates that the implementation does not change its vertex numbering for triangle strip primitives
when the provoking vertex mode is VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT.
GLSL mapping
The following variables from GL_EXT_fragment_shader_barycentric
map to these SPIR-V built-in decorations:
- in vec3 gl_BaryCoordEXT; → BaryCoordKHR
 - in vec3 gl_BaryCoordNoPerspEXT; → BaryCoordNoPerspKHR
 
GLSL variables declared using the __pervertexEXT GLSL qualifier are expected to be decorated with PerVertexKHR in SPIR-V.
HLSL mapping
- in float3 barycentrics : SV_Barycentrics; → BaryCoordKHR
 - in noperspective float3 barycentrics : SV_Barycentrics; → BaryCoordNoPerspKHR
 
Values of per-vertex attributes provided by GetAttributeAtVertex are expected to be decorated with PerVertexKHR in SPIR-V.
Issues
None