1// Copyright 2021-2023 The Khronos Group Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5= VK_KHR_fragment_shader_barycentric
6:toc: left
7:refpage: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/
8:sectnums:
9
10This document details the VK_KHR_fragment_shader_barcentric extension, which adds a cross-vendor way to access barycentric coordinates in a fragment shader.
11
12== Problem Statement
13
14Barycentric 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
15the 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.
16
17== Solution Space
18
19Two options have been considered:
20
21- Take VK_NV_fragment_shader_barycentric and add any new required properties and behaviours.
22- Start afresh
23
24This proposal focuses on the first option.
25
26== Proposal
27
28=== New SPIR-V decorations
29
30A new SPIR-V extension https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_fragment_shader_barycentric.html[SPV_KHR_fragment_shader_barycentric]
31adds three fragment shader variable decorations:
32
33  * `PerVertexKHR`, which indicates that a fragment shader input will not
34    have interpolated values, but instead must be accessed with an extra
35    array index that identifies one of the vertices of the primitive
36    producing the fragment
37  * `BaryCoordKHR`, which indicates that the variable is a three-component
38    floating-point vector holding barycentric weights for the fragment
39    produced using perspective interpolation
40  * `BaryCoordNoPerspKHR`, which indicates that the variable is a
41    three-component floating-point vector holding barycentric weights for
42    the fragment produced using linear interpolation
43
44=== Barycentric weights
45
46- For point primitives, `BaryCoordKHR` and `BaryCoordNoPerspKHR` are assigned the value (1,0,0).
47- For line primitives, `BaryCoordKHR` and `BaryCoordNoPerspKHR` are assigned the values (1,0,0) and (0,1,0) at the ends of the primitive.
48- For polygon primitives, `BaryCoordKHR` and `BaryCoordNoPerspKHR` are assigned the values (1,0,0), (0,1,0), and (0,0,1) at the three vertices.
49
50=== Per-vertex attributes
51
52Per-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.
53
54Vertices are numbered as follows:
55
56[cols="10,10,10,10",options="header",width = "80%"]
57|====
58| Primitive Topology | Vertex 0 | Vertex 1 | Vertex 2
59| `VK_PRIMITIVE_TOPOLOGY_POINT_LIST`                           | i           | i           | i
60| `VK_PRIMITIVE_TOPOLOGY_LINE_LIST`                            | 2i          | 2i+1        | 2i+1
61| `VK_PRIMITIVE_TOPOLOGY_LINE_STRIP`                           | i           | i+1         | i+1
62| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST`                        | 3i          | 3i+1        | 3i+2
63| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP` (even)                | i           | i+1         | i+2
64| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP` (odd)                 | i           | i+2         | i+1
65| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN`                         | i+1         | i+2         | 0
66| `VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY`             | 4i+1        | 4i+2        | 4i+2
67| `VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY`            | i+1         | i+2         | i+2
68| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY`         | 6i          | 6i+2        | 6i+4
69| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY` (even) | 2i          | 2i+2        | 2i+4
70| `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY` (odd)  | 2i          | 2i+4        | 2i+2
71|====
72
73When 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.
74
75[cols="10,10,10,10",options="header",width = "80%"]
76|====
77| Primitive Topology | Vertex 0 | Vertex 1 | Vertex 2
78| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP (odd, and `triStripVertexOrderIndependentOfProvokingVertex`  is `VK_FALSE`)    | i+1         | i           | i+2
79| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                         | 0           | i+1         | i+2
80| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY (odd)  | 2i+2        | 2i          | 2i+4
81|====
82
83=== Properties
84
85A new property structure is added:
86
87[source,c]
88----
89typedef struct VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR {
90    VkStructureType    sType;
91    void*              pNext;
92    VkBool32           triStripVertexOrderIndependentOfProvokingVertex;
93} VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR;
94----
95
96The `triStripVertexOrderIndependentOfProvokingVertex` property indicates that the implementation does not change its vertex numbering for triangle strip primitives
97when the link:{refpage}VkProvokingVertexModeEXT.html[provoking vertex mode] is `VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT`.
98
99=== GLSL mapping
100
101The following variables from https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_fragment_shader_barycentric.txt[`GL_EXT_fragment_shader_barycentric`]
102map to these SPIR-V built-in decorations:
103
104- in vec3 gl_BaryCoordEXT; → BaryCoordKHR
105- in vec3 gl_BaryCoordNoPerspEXT; → BaryCoordNoPerspKHR
106
107GLSL variables declared using the `__pervertexEXT` GLSL qualifier are expected to be decorated with `PerVertexKHR` in SPIR-V.
108
109=== HLSL mapping
110
111- in float3 barycentrics : SV_Barycentrics; → BaryCoordKHR
112- in noperspective float3 barycentrics : SV_Barycentrics; → BaryCoordNoPerspKHR
113
114Values of per-vertex attributes provided by `GetAttributeAtVertex` are expected to be decorated with `PerVertexKHR` in SPIR-V.
115
116== Issues
117
118None
119
120