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,
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.
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