1// Copyright (c) 2017-2020 NVIDIA Corporation 2// 3// SPDX-License-Identifier: CC-BY-4.0 4 5include::{generated}/meta/{refprefix}VK_NV_geometry_shader_passthrough.adoc[] 6 7=== Other Extension Metadata 8 9*Last Modified Date*:: 10 2017-02-15 11*Interactions and External Dependencies*:: 12 - This extension requires 13 {spirv}/NV/SPV_NV_geometry_shader_passthrough.html[`SPV_NV_geometry_shader_passthrough`] 14 - This extension provides API support for 15 {GLregistry}/NV/NV_geometry_shader_passthrough.txt[`GL_NV_geometry_shader_passthrough`] 16 - This extension requires the pname:geometryShader feature. 17*Contributors*:: 18 - Piers Daniell, NVIDIA 19 - Jeff Bolz, NVIDIA 20 21=== Description 22 23This extension adds support for the following SPIR-V extension in Vulkan: 24 25 * `SPV_NV_geometry_shader_passthrough` 26 27Geometry shaders provide the ability for applications to process each 28primitive sent through the graphics pipeline using a programmable shader. 29However, one common use case treats them largely as a "`passthrough`". 30In this use case, the bulk of the geometry shader code simply copies inputs 31from each vertex of the input primitive to corresponding outputs in the 32vertices of the output primitive. 33Such shaders might also compute values for additional built-in or 34user-defined per-primitive attributes (e.g., code:Layer) to be assigned to 35all the vertices of the output primitive. 36 37This extension provides access to the code:PassthroughNV decoration under 38the code:GeometryShaderPassthroughNV capability. 39Adding this to a geometry shader input variable specifies that the values of 40this input are copied to the corresponding vertex of the output primitive. 41 42When using GLSL source-based shading languages, the code:passthrough layout 43qualifier from `GL_NV_geometry_shader_passthrough` maps to the 44code:PassthroughNV decoration. 45To use the code:passthrough layout, in GLSL the 46`GL_NV_geometry_shader_passthrough` extension must be enabled. 47Behaviour is described in the `GL_NV_geometry_shader_passthrough` extension 48specification. 49 50include::{generated}/interfaces/VK_NV_geometry_shader_passthrough.adoc[] 51 52=== New Variable Decoration 53 54 * <<geometry-passthrough-passthrough,code:PassthroughNV>> in 55 <<geometry-passthrough,Geometry Shader Passthrough>> 56 57=== New SPIR-V Capabilities 58 59 * <<spirvenv-capabilities-table-GeometryShaderPassthroughNV, 60 code:GeometryShaderPassthroughNV>> 61 62=== Issues 63 641) Should we require or allow a passthrough geometry shader to specify the 65output layout qualifiers for the output primitive type and maximum vertex 66count in the SPIR-V? 67 68*RESOLVED*: Yes they should be required in the SPIR-V. 69Per GL_NV_geometry_shader_passthrough they are not permitted in the GLSL 70source shader, but SPIR-V is lower-level. 71It is straightforward for the GLSL compiler to infer them from the input 72primitive type and to explicitly emit them in the SPIR-V according to the 73following table. 74 75[options="header"] 76|==== 77| Input Layout | Implied Output Layout 78| points | `layout(points, max_vertices=1)` 79| lines | `layout(line_strip, max_vertices=2)` 80| triangles | `layout(triangle_strip, max_vertices=3)` 81|==== 82 832) How does interface matching work with passthrough geometry shaders? 84 85*RESOLVED*: This is described in <<geometry-passthrough-interface, 86Passthrough Interface Matching>>. 87In GL when using passthough geometry shaders in separable mode, all inputs 88must also be explicitly assigned location layout qualifiers. 89In Vulkan all SPIR-V shader inputs (except built-ins) must also have 90location decorations specified. 91Redeclarations of built-in variables that add the passthrough layout 92qualifier are exempted from the rule requiring location assignment because 93built-in variables do not have locations and are matched by code:BuiltIn 94decoration. 95 96 97=== Sample Code 98 99Consider the following simple geometry shader in unextended GLSL: 100 101[source,c] 102--------------------------------------------------- 103layout(triangles) in; 104layout(triangle_strip) out; 105layout(max_vertices=3) out; 106 107in Inputs { 108 vec2 texcoord; 109 vec4 baseColor; 110} v_in[]; 111out Outputs { 112 vec2 texcoord; 113 vec4 baseColor; 114}; 115 116void main() 117{ 118 int layer = compute_layer(); 119 for (int i = 0; i < 3; i++) { 120 gl_Position = gl_in[i].gl_Position; 121 texcoord = v_in[i].texcoord; 122 baseColor = v_in[i].baseColor; 123 gl_Layer = layer; 124 EmitVertex(); 125 } 126} 127--------------------------------------------------- 128 129In this shader, the inputs code:gl_Position, code:Inputs.texcoord, and 130code:Inputs.baseColor are simply copied from the input vertex to the 131corresponding output vertex. 132The only "`interesting`" work done by the geometry shader is computing and 133emitting a code:gl_Layer value for the primitive. 134 135The following geometry shader, using this extension, is equivalent: 136 137[source,c] 138--------------------------------------------------- 139#extension GL_NV_geometry_shader_passthrough : require 140 141layout(triangles) in; 142// No output primitive layout qualifiers required. 143 144// Redeclare gl_PerVertex to pass through "gl_Position". 145layout(passthrough) in gl_PerVertex { 146 vec4 gl_Position; 147} gl_in[]; 148 149// Declare "Inputs" with "passthrough" to automatically copy members. 150layout(passthrough) in Inputs { 151 vec2 texcoord; 152 vec4 baseColor; 153} v_in[]; 154 155// No output block declaration required. 156 157void main() 158{ 159 // The shader simply computes and writes gl_Layer. We do not 160 // loop over three vertices or call EmitVertex(). 161 gl_Layer = compute_layer(); 162} 163--------------------------------------------------- 164 165 166=== Version History 167 168 * Revision 1, 2017-02-15 (Daniel Koch) 169 ** Internal revisions 170