VK_KHR_fragment_shader_barycentric
This document details the VK_KHR_fragment_shader_barcentric extension, which adds a cross-vendor way to access barycentric coordinates in a fragment shader.
1. 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.
2. 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.
3. Proposal
3.1. 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 fragment -
BaryCoordKHR
, which indicates that the variable is a three-component floating-point vector holding barycentric weights for the fragment produced using perspective interpolation -
BaryCoordNoPerspKHR
, which indicates that the variable is a three-component floating-point vector holding barycentric weights for the fragment produced using linear interpolation
3.2. Barycentric weights
-
For point primitives,
BaryCoordKHR
andBaryCoordNoPerspKHR
are assigned the value (1,0,0). -
For line primitives,
BaryCoordKHR
andBaryCoordNoPerspKHR
are assigned the values (1,0,0) and (0,1,0) at the ends of the primitive. -
For polygon primitives,
BaryCoordKHR
andBaryCoordNoPerspKHR
are assigned the values (1,0,0), (0,1,0), and (0,0,1) at the three vertices.
3.3. 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 |
3.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
.
3.5. 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.