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