blob: 236d893577cfa1f33f90c23bfc37b74930b3cdf7 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<meta name="author" content="John Kessenich, Google (Editor and Author) ; Dave Baldwin and Randi Rost (Version 1.1 Authors)">
<title>The OpenGL&#174; Shading Language, Version 4.60.7</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Uncomment @import statement below to use as custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite::before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
*:not(pre)>code.nobreak{word-wrap:normal}
*:not(pre)>code.nowrap{white-space:nowrap}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote::before{display:none}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6}
.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
/*pre.CodeRay {background-color:#f7f7f8;}*/
.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
table.CodeRay td{vertical-align: top;line-height:1.45}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
table.CodeRay td.code{padding:0 0 0 .5em}
table.CodeRay td.code>pre{padding:0}
.CodeRay .debug{color:#fff !important;background:#000080 !important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:#000080}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:#008080}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:#008080}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:#008080}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
</style>
<link rel="stylesheet" href="../katex/katex.min.css">
<script src="../katex/katex.min.js"></script>
<script src="../katex/contrib/auto-render.min.js"></script>
<!-- Use KaTeX to render math once document is loaded, see
https://github.com/Khan/KaTeX/tree/master/contrib/auto-render -->
<script>
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(
document.body,
{
delimiters: [
{ left: "$$", right: "$$", display: true},
{ left: "\\[", right: "\\]", display: true},
{ left: "$", right: "$", display: false},
{ left: "\\(", right: "\\)", display: false}
]
}
);
});
</script></head>
<body class="book toc2 toc-left" style="max-width: 100;">
<div id="header">
<h1>The OpenGL<sup>&#174;</sup> Shading Language, Version 4.60.7</h1>
<div class="details">
<span id="author" class="author">John Kessenich, Google (Editor and Author) ; Dave Baldwin and Randi Rost (Version 1.1 Authors)</span><br>
<span id="revnumber">version 4.60.7,</span>
<span id="revdate">Wed, 10 Jul 2019 20:42:58 +0000</span>
<br><span id="revremark">Git branch information not available</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#introduction">1. Introduction</a>
<ul class="sectlevel2">
<li><a href="#changes">1.1. Changes</a></li>
<li><a href="#overview">1.2. Overview</a></li>
<li><a href="#error-handling">1.3. Error Handling</a></li>
<li><a href="#typographical-conventions">1.4. Typographical Conventions</a></li>
<li><a href="#deprecation">1.5. Deprecation</a></li>
</ul>
</li>
<li><a href="#overview-of-opengl-shading">2. Overview of Shading</a>
<ul class="sectlevel2">
<li><a href="#vertex-processor">2.1. Vertex Processor</a></li>
<li><a href="#tessellation-control-processor">2.2. Tessellation Control Processor</a></li>
<li><a href="#tessellation-evaluation-processor">2.3. Tessellation Evaluation Processor</a></li>
<li><a href="#geometry-processor">2.4. Geometry Processor</a></li>
<li><a href="#fragment-processor">2.5. Fragment Processor</a></li>
<li><a href="#compute-processor">2.6. Compute Processor</a></li>
</ul>
</li>
<li><a href="#basics">3. Basics</a>
<ul class="sectlevel2">
<li><a href="#character-set">3.1. Character Set and Phases of Compilation</a></li>
<li><a href="#source-strings">3.2. Source Strings</a></li>
<li><a href="#preprocessor">3.3. Preprocessor</a></li>
<li><a href="#comments">3.4. Comments</a></li>
<li><a href="#tokens">3.5. Tokens</a></li>
<li><a href="#keywords">3.6. Keywords</a></li>
<li><a href="#identifiers">3.7. Identifiers</a></li>
<li><a href="#definitions">3.8. Definitions</a></li>
</ul>
</li>
<li><a href="#variables-and-types">4. Variables and Types</a>
<ul class="sectlevel2">
<li><a href="#basic-types">4.1. Basic Types</a></li>
<li><a href="#scoping">4.2. Scoping</a></li>
<li><a href="#storage-qualifiers">4.3. Storage Qualifiers</a></li>
<li><a href="#layout-qualifiers">4.4. Layout Qualifiers</a></li>
<li><a href="#interpolation-qualifiers">4.5. Interpolation Qualifiers</a></li>
<li><a href="#parameter-qualifiers">4.6. Parameter Qualifiers</a></li>
<li><a href="#precision-and-precision-qualifiers">4.7. Precision and Precision Qualifiers</a></li>
<li><a href="#variance-and-the-invariant-qualifier">4.8. Variance and the Invariant Qualifier</a></li>
<li><a href="#the-precise-qualifier">4.9. The Precise Qualifier</a></li>
<li><a href="#memory-qualifiers">4.10. Memory Qualifiers</a></li>
<li><a href="#specialization-constant-qualifier">4.11. Specialization-Constant Qualifier</a></li>
<li><a href="#order-of-qualification">4.12. Order and Repetition of Qualification</a></li>
<li><a href="#empty-declarations">4.13. Empty Declarations</a></li>
</ul>
</li>
<li><a href="#operators-and-expressions">5. Operators and Expressions</a>
<ul class="sectlevel2">
<li><a href="#operators">5.1. Operators</a></li>
<li><a href="#array-operations">5.2. Array Operations</a></li>
<li><a href="#function-calls">5.3. Function Calls</a></li>
<li><a href="#constructors">5.4. Constructors</a></li>
<li><a href="#vector-components">5.5. Vector and Scalar Components and Length</a></li>
<li><a href="#matrix-components">5.6. Matrix Components</a></li>
<li><a href="#structure-and-array-operations">5.7. Structure and Array Operations</a></li>
<li><a href="#assignments">5.8. Assignments</a></li>
<li><a href="#expressions">5.9. Expressions</a></li>
<li><a href="#vector-and-matrix-operations">5.10. Vector and Matrix Operations</a></li>
<li><a href="#out-of-bounds-accesses">5.11. Out-of-Bounds Accesses</a></li>
<li><a href="#specialization-constant-operations">5.12. Specialization-Constant Operations</a></li>
</ul>
</li>
<li><a href="#statements-and-structure">6. Statements and Structure</a>
<ul class="sectlevel2">
<li><a href="#function-definitions">6.1. Function Definitions</a></li>
<li><a href="#selection">6.2. Selection</a></li>
<li><a href="#iteration">6.3. Iteration</a></li>
<li><a href="#jumps">6.4. Jumps</a></li>
</ul>
</li>
<li><a href="#built-in-variables">7. Built-In Variables</a>
<ul class="sectlevel2">
<li><a href="#built-in-language-variables">7.1. Built-In Language Variables</a></li>
<li><a href="#compatibility-profile-vertex-shader-built-in-inputs">7.2. Compatibility Profile Vertex Shader Built-In Inputs</a></li>
<li><a href="#built-in-constants">7.3. Built-In Constants</a></li>
<li><a href="#built-in-uniform-state">7.4. Built-In Uniform State</a></li>
<li><a href="#redeclaring-built-in-blocks">7.5. Redeclaring Built-In Blocks</a></li>
</ul>
</li>
<li><a href="#built-in-functions">8. Built-In Functions</a>
<ul class="sectlevel2">
<li><a href="#angle-and-trigonometry-functions">8.1. Angle and Trigonometry Functions</a></li>
<li><a href="#exponential-functions">8.2. Exponential Functions</a></li>
<li><a href="#common-functions">8.3. Common Functions</a></li>
<li><a href="#floating-point-pack-and-unpack-functions">8.4. Floating-Point Pack and Unpack Functions</a></li>
<li><a href="#geometric-functions">8.5. Geometric Functions</a></li>
<li><a href="#matrix-functions">8.6. Matrix Functions</a></li>
<li><a href="#vector-relational-functions">8.7. Vector Relational Functions</a></li>
<li><a href="#integer-functions">8.8. Integer Functions</a></li>
<li><a href="#texture-functions">8.9. Texture Functions</a></li>
<li><a href="#atomic-counter-functions">8.10. Atomic Counter Functions</a></li>
<li><a href="#atomic-memory-functions">8.11. Atomic Memory Functions</a></li>
<li><a href="#image-functions">8.12. Image Functions</a></li>
<li><a href="#geometry-shader-functions">8.13. Geometry Shader Functions</a></li>
<li><a href="#fragment-processing-functions">8.14. Fragment Processing Functions</a></li>
<li><a href="#noise-functions">8.15. Noise Functions</a></li>
<li><a href="#shader-invocation-control-functions">8.16. Shader Invocation Control Functions</a></li>
<li><a href="#shader-memory-control-functions">8.17. Shader Memory Control Functions</a></li>
<li><a href="#_subpass_input_functions">8.18. Subpass-Input Functions</a></li>
<li><a href="#shader-invocation-group-functions">8.19. Shader Invocation Group Functions</a></li>
</ul>
</li>
<li><a href="#shading-language-grammar">9. Shading Language Grammar</a></li>
<li><a href="#acknowledgments">10. Acknowledgments</a></li>
<li><a href="#references">11. Normative References</a></li>
<li><a href="#_non_normative_spir_v_mappings">12. Non-Normative SPIR-V Mappings</a>
<ul class="sectlevel2">
<li><a href="#_feature_comparisons">12.1. Feature Comparisons</a></li>
<li><a href="#_mapping_from_glsl_to_spir_v">12.2. Mapping from GLSL to SPIR-V</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div style="page-break-after: always;"></div>
<div class="paragraph">
<p>Copyright &#169; 2008-2018 The Khronos Group Inc. All Rights Reserved.</p>
</div>
<div class="paragraph">
<p>This specification is protected by copyright laws and contains material
proprietary to the Khronos Group, Inc. It or any components may not be
reproduced, republished, distributed, transmitted, displayed, broadcast,
or otherwise exploited in any manner without the express prior written
permission of Khronos Group. You may use this specification for
implementing the functionality therein, without altering or removing any
trademark, copyright or other notice from the specification, but the
receipt or possession of this specification does not convey any rights
to reproduce, disclose, or distribute its contents, or to manufacture,
use, or sell anything that it may describe, in whole or in part.</p>
</div>
<div class="paragraph">
<p>Khronos Group grants express permission to any current Promoter,
Contributor or Adopter member of Khronos to copy and redistribute
UNMODIFIED versions of this specification in any fashion, provided that
NO CHARGE is made for the specification and the latest available update
of the specification for any version of the API is used whenever
possible. Such distributed specification may be reformatted AS LONG AS
the contents of the specification are not changed in any way. The
specification may be incorporated into a product that is sold as long as
such product includes significant independent work developed by the
seller. A link to the current version of this specification on the
Khronos Group website should be included whenever possible with
specification distributions.</p>
</div>
<div class="paragraph">
<p>Khronos Group makes no, and expressly disclaims any, representations or
warranties, express or implied, regarding this specification, including,
without limitation, any implied warranties of merchantability or fitness
for a particular purpose or noninfringement of any intellectual
property. Khronos Group makes no, and expressly disclaims any,
warranties, express or implied, regarding the correctness, accuracy,
completeness, timeliness, and reliability of the specification. Under no
circumstances will the Khronos Group, or any of its Promoters,
Contributors or Members or their respective partners, officers,
directors, employees, agents, or representatives be liable for any
damages, whether direct, indirect, special or consequential damages for
lost revenues, lost profits, or otherwise, arising from or in connection
with these materials.</p>
</div>
<div class="paragraph">
<p>Khronos, Vulkan, SYCL, SPIR, WebGL, EGL, COLLADA, StreamInput, OpenVX,
OpenKCam, glTF, OpenKODE, OpenVG, OpenWF, OpenSL ES, OpenMAX, OpenMAX
AL, OpenMAX IL and OpenMAX DL are trademarks and WebCL is a
certification mark of the Khronos Group Inc. OpenCL is a trademark of
Apple Inc. and OpenGL and OpenML are registered trademarks and the
OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics
International used under license by Khronos. All other product names,
trademarks, and/or company names are used solely for identification and
belong to their respective owners.</p>
</div>
<div style="page-break-after: always;"></div>
<!-- toc disabled -->
</div>
</div>
<div class="sect1">
<h2 id="introduction">1. Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This document specifies only version 4.60 of the OpenGL Shading Language (GLSL).
It requires __VERSION__ to substitute 460, and requires
<strong>#version</strong> to accept only
<code>460</code>.
If <strong>#version</strong> is declared with a smaller number, the language accepted is a
previous version of the shading language, which will be supported depending
on the version and type of context in the API.
See the <a href="#references">normative references</a> for details on what language
versions are supported.</p>
</div>
<div class="paragraph">
<p>Previous versions of the OpenGL Shading Language, as well as the OpenGL ES Shading Language,
are not strict subsets of the version specified here, particularly with
respect to precision, name-hiding rules, and treatment of interface
variables.
See the specification corresponding to a particular language version for
details specific to that version of the language.</p>
</div>
<div class="paragraph">
<p>Throughout, when generating SPIR-V for consumption by the Vulkan API
(see <a href="#references">normative references</a>), this will be said to be
<em>targeting Vulkan</em>.</p>
</div>
<div class="paragraph">
<p>While this specification and the OpenGL Specification are normative for OpenGL Shading Language, for
SPIR-V generation it is still the SPIR-V specification and the SPIR-V client
API specification that are normative for the generated SPIR-V.
See the <a href="#references">normative references</a> for further detail.</p>
</div>
<div class="paragraph">
<p>For SPIR-V generation, the SPIR-V client API specifies the commands used to
manipulate SPIR-V shaders.</p>
</div>
<div class="paragraph">
<p>Independent offline tool chains will compile GLSL down to the SPIR-V
intermediate language.
SPIR-V generation is not enabled with a <strong>#extension</strong>, <strong>#version</strong>, or a
profile.
Instead, use of GLSL for SPIR-V is determined by offline tool-chain use.
See the documentation of such tools to see how to request generation of
SPIR-V for its client API.</p>
</div>
<div class="paragraph">
<p>GLSL &#8594; SPIR-V compilers must be directed as to what SPIR-V <strong>Capabilities</strong>
are legal at run-time and give errors for GLSL feature use outside those
capabilities.
This is also true for implementation-dependent limits that can be error
checked by the front-end against built-in constants present in the GLSL
source: the front-end can be informed of such limits, and report errors when
they are exceeded.</p>
</div>
<div class="paragraph">
<p>SPIR-V features that are not controlled by a SPIR-V capability, but do have an
equivalent GLSL counterpart (stages, built-in functions, types, limits, etc.)
are only expected to work on OpenGL drivers that support the GLSL counterpart.</p>
</div>
<div class="paragraph">
<p>All references in this specification to the <a href="#references">OpenGL Specification</a> are to
the Core profile of version 4.6, unless a different profile is
specified.</p>
</div>
<div class="sect2">
<h3 id="changes">1.1. Changes</h3>
<div class="sect3">
<h4 id="_changes_from_revision_6_of_glsl_4_6">1.1.1. Changes from Revision 6 of GLSL 4.6</h4>
<div class="ulist">
<ul>
<li>
<p>Incorporated the GL_KHR_vulkan_glsl specification.</p>
</li>
<li>
<p>Add note in the introduction about presence in drivers of SPIR-V features,
as they relate to GLSL features.</p>
</li>
<li>
<p>Clarify it is same location that triggers default-uniform block matching
rules.
See <a href="#uniform-variable-layout-qualifiers">Uniform Variable Layout Qualifiers</a>.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_changes_from_revision_5_of_glsl_4_6">1.1.2. Changes from Revision 5 of GLSL 4.6</h4>
<div class="ulist">
<ul>
<li>
<p>Private GLSL issue #34: Clarify/consolidate implicit conversion rules from int &#8594; uint
to be the same as explicit construction.</p>
</li>
<li>
<p>Private GLSL issue #24: Clarify that <strong>barrier</strong>() by itself is enough to synchronize
both control flow and memory accesses to <strong>shared</strong> variables and tessellation
control output variables. For other memory accesses an additional memory
barrier is still required.</p>
</li>
<li>
<p>Normatively reference IEEE-754 for definitions of floating-point formats.</p>
</li>
<li>
<p>Private GLSL issue 36: <strong>refract</strong> function on <strong>double</strong> types requires eta
argument to have type <strong>double</strong>.</p>
</li>
<li>
<p>Clarify restrictions on input variables in tessellation and geometry stages.</p>
</li>
<li>
<p>Private GLSL issue 15: Clarify the ordering of bindings for arrays of arrays.</p>
</li>
<li>
<p>Private GLSL issue 14: Uniform variables need only match at link time if they
are statically used.</p>
</li>
<li>
<p>For <strong>precise</strong> computations, the controlling expressions for
control flow and ternary operators (<strong>?:</strong>) are not included.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_changes_from_revision_4_of_glsl_4_6">1.1.3. Changes from Revision 4 of GLSL 4.6</h4>
<div class="ulist">
<ul>
<li>
<p>Private bug 13012: Clarified that builtin uniform variables might only
be available in the fragment stage.</p>
</li>
<li>
<p>Private bug 13837: Ternary and sequence operators may operate on <strong>void</strong> types.</p>
</li>
<li>
<p>Clarified that errors arising from preprocessing must be returned at compile time.</p>
</li>
<li>
<p>Clarified that access to any part of a variable constitutes a static use.</p>
</li>
<li>
<p>Private GLSL issue 19: A statement is required following any label at the end of a <strong>switch</strong>.</p>
</li>
<li>
<p>Private GLSL issue 26: <strong>noise</strong> is not valid when compiling for SPIR-V.</p>
</li>
<li>
<p>Private GLSL issue 20: <strong>length</strong>() expressions returning a constant value may not
contain side effects.</p>
</li>
<li>
<p>Public OpenGL-API issue 7: Variables can be declared as both <strong>readonly</strong>
and <strong>writeonly</strong>.</p>
</li>
<li>
<p>Private GLSL issue 16: Use of constant expressions within <strong>#line</strong> directives is undefined.</p>
</li>
<li>
<p>Corrected return type of <strong>imageAtomicExchange</strong> on <strong>float</strong> images.</p>
</li>
<li>
<p>Private GLSL issue 32: Remove <strong>length</strong>() method contradiction:
Non runtime-sized arrays only support <strong>length</strong>() on explicitly
sized arrays.</p>
</li>
<li>
<p>Private GLSL issue 21: Clarified the l-value restriction on <strong>interpolateAt</strong>.</p>
</li>
<li>
<p>Private OpenGL-API issue 53: Clarified bit-width requirements for location aliasing.</p>
</li>
<li>
<p>Public GLSL issue 15: <strong>gl_in</strong> can be redeclared using unsized-array syntax.</p>
</li>
<li>
<p>Clarification of the formats needed for DEPTH_COMPONENT and
STENCIL_COMPONENT for depth/stencil textures.</p>
</li>
<li>
<p>Added image formats to the layout-qualifier table in the
<a href="#layout-qualifiers">Layout Qualifiers</a> section.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_changes_from_revision_3_of_glsl_4_6">1.1.4. Changes from Revision 3 of GLSL 4.6</h4>
<div class="ulist">
<ul>
<li>
<p>Private GLSL issue 13: Fix misspelling of <strong>allInvocationsEqual</strong>().
(The one in the table was incorrectly listed as <strong>anyInvocationsEqual</strong>(),
other spellings were correct.)</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_summary_of_changes_from_revision_7_of_glsl_version_4_50">1.1.5. Summary of Changes from Revision 7 of GLSL Version 4.50</h4>
<div class="ulist">
<ul>
<li>
<p>Incorporated the GL_ARB_shader_atomic_counter_ops extension.</p>
</li>
<li>
<p>Incorporated the GL_ARB_shader_draw_parameters extension.</p>
</li>
<li>
<p>Incorporated the GL_ARB_shader_group_vote extension.</p>
</li>
<li>
<p>Incorporated the GL_ARB_gl_spirv extension.</p>
</li>
<li>
<p>Private Bug 16070: Allow extra semi-colons at global scope.</p>
</li>
<li>
<p>Private GLSL Issue 5: Be explicit that &#8220;fail to link&#8221; is really
&#8220;compile-time or link-time error&#8221;, for some forms of error.</p>
</li>
<li>
<p>Private GLSL Issue 7: Change <em>gl_MaxComputeUniformComponents</em> to 1024.</p>
</li>
<li>
<p>Private OpenGL API Issue 35: Require location on transparent individual
uniform variables for SPIR-V.</p>
</li>
<li>
<p>Private GLSL Issue 8: Be more clear an <strong>interpolateAt</strong>() interpolant can
be a structure member.</p>
</li>
<li>
<p>Private GLSL Issue 9: Specify how <strong>xfb_buffer</strong> interacts with a block
array: the capturing buffer increments for each block array element.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="overview">1.2. Overview</h3>
<div class="paragraph">
<p>This document describes <em>The OpenGL Shading Language, version 4.60</em>.</p>
</div>
<div class="paragraph">
<p>Independent compilation units written in this language are called <em>shaders</em>.
A <em>program</em> is a set of shaders that are compiled and linked
together,
completely creating one or more of the programmable stages of the
API pipeline.
All the shaders for a single programmable stage must be within the same
program.
A complete set of programmable stages can be put into a single program or
the stages can be partitioned across multiple programs.
The aim of this document is to thoroughly specify the programming language.
The <a href="#references">normative references</a> will specify the API entry points
used to manipulate and communicate with programs and shaders.</p>
</div>
</div>
<div class="sect2">
<h3 id="error-handling">1.3. Error Handling</h3>
<div class="paragraph">
<p>Compilers, in general, accept programs that are ill-formed, due to the
impossibility of detecting all ill-formed programs.
Portability is only ensured for well-formed programs, which this
specification describes.
Compilers are encouraged to detect ill-formed programs and issue diagnostic
messages, but are not required to do so for all cases.
Compile-time errors must be returned for lexically or grammatically
incorrect shaders.
Other errors are reported at compile time or link time as indicated.
Code that is &#8220;dead&#8221; must still be error checked.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">if</span> (<span class="predefined-constant">false</span>) <span class="comment">// changing false to true cannot uncover additional errors</span>
statement; <span class="comment">// statement must be error checked regardless</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="typographical-conventions">1.4. Typographical Conventions</h3>
<div class="paragraph">
<p>Italic, bold, and font choices have been used in this specification
primarily to improve readability.
Code fragments use a fixed width font.
Identifiers embedded in text are italicized.
Keywords embedded in text are bold.
Operators are called by their name, followed by their symbol in bold in
parentheses.
The clarifying grammar fragments in the text use bold for literals and
italics for non-terminals.
The official grammar in &#8220;<a href="#shading-language-grammar">Shading Language
Grammar</a>&#8221; uses all capitals for terminals and lower case for
non-terminals.</p>
</div>
</div>
<div class="sect2">
<h3 id="deprecation">1.5. Deprecation</h3>
<div class="paragraph">
<p>The OpenGL Shading Language has deprecated some features.
These are clearly called out in this specification as &#8220;deprecated&#8221;.
They are still present in this version of the language, but are targeted for
potential removal in a future version of the shading language.
The OpenGL API has a forward compatibility mode that will disallow use of
deprecated features.
If compiling in a mode where use of deprecated features is disallowed, their
use causes compile-time or link-time errors.
See the <a href="#references">OpenGL Specification</a> for details on what causes deprecated
language features to be accepted or to return an error.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="overview-of-opengl-shading">2. Overview of Shading</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The OpenGL Shading Language is actually several closely related languages.
These languages are used to create shaders for each of the programmable
processors contained in the API&#8217;s processing pipeline.
Currently, these processors are the vertex, tessellation control,
tessellation evaluation, geometry, fragment, and compute processors.</p>
</div>
<div class="paragraph">
<p>Unless otherwise noted in this paper, a language feature applies to all
languages, and common usage will refer to these languages as a single
language.
The specific languages will be referred to by the name of the processor they
target: vertex, tessellation control, tessellation evaluation, geometry,
fragment, or compute.</p>
</div>
<div class="paragraph">
<p>Most API state is not tracked or made available to shaders.
Typically, user-defined variables will be used for communicating between
different stages of the API pipeline.
However, a small amount of state is still tracked and automatically made
available to shaders, and there are a few built-in variables for interfaces
between different stages of the API pipeline.</p>
</div>
<div class="sect2">
<h3 id="vertex-processor">2.1. Vertex Processor</h3>
<div class="paragraph">
<p>The <em>vertex processor</em> is a programmable unit that operates on incoming
vertices and their associated data.
Compilation units written in the OpenGL Shading Language to run on this processor are called
<em>vertex shaders</em>.
When a set of vertex shaders are successfully compiled and linked, they
result in a <em>vertex shader executable</em> that runs on the vertex processor.</p>
</div>
<div class="paragraph">
<p>The vertex processor operates on one vertex at a time.
It does not replace graphics operations that require knowledge of several
vertices at a time.</p>
</div>
</div>
<div class="sect2">
<h3 id="tessellation-control-processor">2.2. Tessellation Control Processor</h3>
<div class="paragraph">
<p>The <em>tessellation control processor</em> is a programmable unit that operates on
a patch of incoming vertices and their associated data, emitting a new
output patch.
Compilation units written in the OpenGL Shading Language to run on this processor are called
tessellation control shaders.
When a set of tessellation control shaders are successfully compiled and
linked, they result in a <em>tessellation control shader executable</em> that runs
on the tessellation control processor.</p>
</div>
<div class="paragraph">
<p>The tessellation control shader is invoked for each vertex of the output
patch.
Each invocation can read the attributes of any vertex in the input or output
patches, but can only write per-vertex attributes for the corresponding
output patch vertex.
The shader invocations collectively produce a set of per-patch attributes
for the output patch.</p>
</div>
<div class="paragraph">
<p>After all tessellation control shader invocations have completed, the output
vertices and per-patch attributes are assembled to form a patch to be used
by subsequent pipeline stages.</p>
</div>
<div class="paragraph">
<p>Tessellation control shader invocations run mostly independently, with
undefined relative execution order.
However, the built-in function <strong>barrier</strong>() can be used to control execution
order by synchronizing invocations, effectively dividing tessellation
control shader execution into a set of phases.
Tessellation control shaders will get undefined results if one invocation
reads from a per-vertex or per-patch attribute written by another invocation
at any point during the same phase, or if two invocations attempt to write
different values to the same per-patch output
32-bit component
in a single phase.</p>
</div>
</div>
<div class="sect2">
<h3 id="tessellation-evaluation-processor">2.3. Tessellation Evaluation Processor</h3>
<div class="paragraph">
<p>The <em>tessellation evaluation processor</em> is a programmable unit that
evaluates the position and other attributes of a vertex generated by the
tessellation primitive generator, using a patch of incoming vertices and
their associated data.
Compilation units written in the OpenGL Shading Language to run on this processor are called
tessellation evaluation shaders.
When a set of tessellation evaluation shaders are successfully compiled and
linked, they result in a <em>tessellation evaluation shader executable</em> that
runs on the tessellation evaluation processor.</p>
</div>
<div class="paragraph">
<p>Each invocation of the tessellation evaluation executable computes the
position and attributes of a single vertex generated by the tessellation
primitive generator.
The executable can read the attributes of any vertex in the input patch,
plus the tessellation coordinate, which is the relative location of the
vertex in the primitive being tessellated.
The executable writes the position and other attributes of the vertex.</p>
</div>
</div>
<div class="sect2">
<h3 id="geometry-processor">2.4. Geometry Processor</h3>
<div class="paragraph">
<p>The <em>geometry processor</em> is a programmable unit that operates on data for
incoming vertices for a primitive assembled after vertex processing and
outputs a sequence of vertices forming output primitives.
Compilation units written in the OpenGL Shading Language to run on this processor are called
<em>geometry shaders</em>.
When a set of geometry shaders are successfully compiled and linked, they
result in a <em>geometry shader executable</em> that runs on the geometry
processor.</p>
</div>
<div class="paragraph">
<p>A single invocation of the geometry shader executable on the geometry
processor will operate on a declared input primitive with a fixed number of
vertices.
This single invocation can emit a variable number of vertices that are
assembled into primitives of a declared output primitive type and passed to
subsequent pipeline stages.</p>
</div>
</div>
<div class="sect2">
<h3 id="fragment-processor">2.5. Fragment Processor</h3>
<div class="paragraph">
<p>The <em>fragment processor</em> is a programmable unit that operates on fragment
values and their associated data.
Compilation units written in the OpenGL Shading Language to run on this processor are called
<em>fragment shaders</em>.
When a set of fragment shaders are successfully compiled and linked, they
result in a <em>fragment shader executable</em> that runs on the fragment
processor.</p>
</div>
<div class="paragraph">
<p>A fragment shader cannot change a fragment&#8217;s (<em>x</em>, <em>y</em>) position.
Access to neighboring fragments is not allowed.
The values computed by the fragment shader are ultimately used to update
framebuffer memory or texture memory, depending on the current API
state and the API command that caused the fragments to be generated.</p>
</div>
</div>
<div class="sect2">
<h3 id="compute-processor">2.6. Compute Processor</h3>
<div class="paragraph">
<p>The <em>compute processor</em> is a programmable unit that operates independently
from the other shader processors.
Compilation units written in the OpenGL Shading Language to run on this processor are called
<em>compute shaders</em>.
When a set of compute shaders are successfully compiled and linked, they
result in a <em>compute shader executable</em> that runs on the compute processor.</p>
</div>
<div class="paragraph">
<p>A compute shader has access to many of the same resources as fragment and
other shader processors, such as textures, buffers, image variables, and
atomic counters.
It does not have fixed-function outputs.
It is not part of the graphics pipeline and its visible side effects are
through changes to images, storage buffers, and atomic counters.</p>
</div>
<div class="paragraph">
<p>A compute shader operates on a group of work items called a <em>workgroup</em>.
A workgroup is a collection of shader invocations that execute the same
code, potentially in parallel.
An invocation within a workgroup may share data with other members of the
same workgroup through shared variables and issue memory and control flow
barriers to synchronize with other members of the same workgroup.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="basics">3. Basics</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="character-set">3.1. Character Set and Phases of Compilation</h3>
<div class="paragraph">
<p>The source character set used for the OpenGL Shading Language is Unicode in the UTF-8
encoding scheme.</p>
</div>
<div class="paragraph">
<p>After preprocessing, only the following characters are allowed in the
resulting stream of GLSL tokens:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The letters <strong>a-z</strong>, <strong>A-Z</strong>, and the underscore (<strong>_</strong>).</p>
</li>
<li>
<p>The numbers <strong>0-9</strong>.</p>
</li>
<li>
<p>The symbols period (<strong>.</strong>), plus (<strong>+</strong>), dash (<strong>-</strong>), slash (<strong>/</strong>), asterisk
(<strong>*</strong>), percent (<strong>%</strong>), angled brackets (<strong>&lt;</strong> and <strong>&gt;</strong>), square brackets
(<strong>[</strong> and <strong>]</strong>), parentheses (<strong>(</strong> and <strong>)</strong>), braces (<strong>{</strong> and <strong>}</strong>), caret
(<strong>^</strong>), vertical bar (<strong>|</strong>), ampersand (<strong>&amp;</strong>), tilde (<strong>~</strong>), equals (<strong>=</strong>),
exclamation point (<strong>!</strong>), colon (<strong>:</strong>), semicolon (<strong>;</strong>), comma (<strong>,</strong>), and
question mark (<strong>?</strong>).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>A compile-time error will be given if any other character is used in a GLSL
token.</p>
</div>
<div class="paragraph">
<p>There are no digraphs or trigraphs.
There are no escape sequences or other uses of the backslash beyond use as
the line-continuation character.</p>
</div>
<div class="paragraph">
<p>Lines are relevant for compiler diagnostic messages and the preprocessor.
They are terminated by carriage-return or line-feed.
If both are used together, it will count as only a single line termination.
For the remainder of this document, any of these combinations is simply
referred to as a new-line.
Lines may be of arbitrary length.</p>
</div>
<div class="paragraph">
<p>In general, the language&#8217;s use of this character set is case sensitive.</p>
</div>
<div class="paragraph">
<p>There are no character or string data types, so no quoting characters are
included.</p>
</div>
<div class="paragraph">
<p>There is no end-of-file character.</p>
</div>
<div class="paragraph">
<p>More formally, compilation happens as if the following logical phases were
executed in order:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Source strings are concatenated to form a single input.
All provided new-lines are retained.</p>
</li>
<li>
<p>Line numbering is noted, based on all present new-lines, and does not
change when new-lines are later eliminated.</p>
</li>
<li>
<p>Wherever a backslash ('\') occurs immediately before a new-line, both
are eliminated.
(Note no white space is substituted, allowing a single token to span a
new-line.) Any newly formed backslash followed by a new-line is not
eliminated; only those pairs originally occurring after phase 1 are
eliminated.</p>
</li>
<li>
<p>All comments are replaced with a single space.
(Note that '//' style comments end before their terminating new-lines
and white space is generally relevant to preprocessing.)</p>
</li>
<li>
<p>Preprocessing is done, resulting in a sequence of GLSL tokens, formed
from the character set stated above.</p>
</li>
<li>
<p>GLSL processing is done on the sequence of GLSL tokens.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Details that fully define source strings, comments, line numbering, new-line
elimination, and preprocessing are all discussed in upcoming sections.
Sections beyond those describe GLSL processing.</p>
</div>
</div>
<div class="sect2">
<h3 id="source-strings">3.2. Source Strings</h3>
<div class="paragraph">
<p>The source for a single shader is an array of strings of characters from the
character set.
A single shader is made from the concatenation of these strings.
Each string can contain multiple lines, separated by new-lines.
No new-lines need be present in a string; a single line can be formed from
multiple strings.
No new-lines or other characters are inserted by the implementation when it
concatenates the strings to form a single shader.
Multiple shaders can be linked together to form a single program.</p>
</div>
<div class="paragraph">
<p>Diagnostic messages returned from compiling a shader must identify both the
line number within a string and which source string the message applies to.
Source strings are counted sequentially with the first string being string
0.
Line numbers are one more than the number of new-lines that have been
processed, including counting the new-lines that will be removed by the
line-continuation character (<strong>\</strong>).</p>
</div>
<div class="paragraph">
<p>Lines separated by the line-continuation character preceding a new-line are
concatenated together before either comment processing or preprocessing.
This means that no white space is substituted for the line-continuation
character.
That is, a single token could be formed by the concatenation by taking the
characters at the end of one line concatenating them with the characters at
the beginning of the next line.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> f\
oo;
<span class="comment">// forms a single line equivalent to &quot;float foo;&quot;</span>
<span class="comment">// (assuming '\' is the last character before the new-line and &quot;oo&quot; are</span>
<span class="comment">// the first two characters of the next line)</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="preprocessor">3.3. Preprocessor</h3>
<div class="paragraph">
<p>There is a preprocessor that processes the source strings as part of the
compilation process.
Except as noted below, it behaves as the C++ standard preprocessor (see
&#8220;<a href="#references">Normative References</a>&#8221;).</p>
</div>
<div class="paragraph">
<p>The complete list of preprocessor directives is as follows.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>#<br>
#define<br>
#undef<br></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>#if<br>
#ifdef<br>
#ifndef<br>
#else<br>
#elif<br>
#endif<br></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>#error<br>
#pragma<br></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>#extension<br>
#version<br></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>#line</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The following
operators are
also available:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>defined<br>
##</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Each number sign (<strong>#</strong>) can be preceded in its line only by spaces or
horizontal tabs.
It may also be followed by spaces and horizontal tabs, preceding the
directive.
Each directive is terminated by a new-line.
Preprocessing does not change the number or relative location of new-lines
in a source string.
Preprocessing takes places after new-lines have been removed by the
line-continuation character.</p>
</div>
<div class="paragraph">
<p>The number sign (<strong>#</strong>) on a line by itself is ignored.
Any directive not listed above will cause a compile-time error.</p>
</div>
<div class="paragraph">
<p><strong>#define</strong> and <strong>#undef</strong> functionality are defined as is standard for C++
preprocessors for macro definitions both with and without macro parameters.</p>
</div>
<div class="paragraph">
<p>The following predefined macros are available:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>__LINE__<br>
__FILE__<br>
__VERSION__<br></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>__LINE__ will substitute a decimal integer constant that is one more than
the number of preceding new-lines in the current source string.</p>
</div>
<div class="paragraph">
<p>__FILE__ will substitute a decimal integer constant that says which source
string number is currently being processed.</p>
</div>
<div class="paragraph">
<p>__VERSION__ will substitute a decimal integer reflecting the version
number of the OpenGL Shading Language.
The version of the shading language described in this document will have
__VERSION__ substitute the decimal integer 460.</p>
</div>
<div class="paragraph">
<p>By convention, all macro names containing two consecutive underscores (__)
are reserved for use by underlying software layers.
Defining
or undefining
such a name in a shader does not itself result in an error, but may
result in unintended behaviors that stem from having multiple definitions of
the same name.
All macro names prefixed with &#8220;GL_&#8221; (&#8220;GL&#8221; followed by a single
underscore) are also reserved, and defining
or undefining
such a name results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>Implementations must support macro-name lengths of up to 1024 characters.
Implementations are allowed to generate an error for a macro name of length
greater than 1024 characters, but are also allowed to support lengths
greater than 1024.</p>
</div>
<div class="paragraph">
<p><strong>#if</strong>, <strong>#ifdef</strong>, <strong>#ifndef</strong>, <strong>#else</strong>, <strong>#elif</strong>, and <strong>#endif</strong> are defined to
operate as is standard for C++ preprocessors except for the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Expressions following <strong>#if</strong> and <strong>#elif</strong> are
further restricted to
expressions operating on literal integer constants, plus identifiers
consumed by the <strong>defined</strong> operator.</p>
</li>
<li>
<p>Character constants are not supported.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The operators available are as follows.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Precedence</th>
<th class="tableblock halign-left valign-top">Operator class</th>
<th class="tableblock halign-left valign-top">Operators</th>
<th class="tableblock halign-left valign-top">Associativity</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">1 (highest)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">parenthetical grouping</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">( )</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">NA</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">unary</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">defined<br>
+ - ~ !</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">multiplicative</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">* / %</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">additive</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ -</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise shift</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;&lt; &gt;&gt;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">relational</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt; &gt; &lt;= &gt;=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">equality</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">== !=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise and</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&amp;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">9</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise exclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">^</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">10</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise inclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">|</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">11</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">logical and</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&amp;&amp;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">12 (lowest)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">logical inclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">||</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The <strong>defined</strong> operator can be used in either of the following ways:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">defined identifier
defined ( identifier )</code></pre>
</div>
</div>
<div class="paragraph">
<p>Two tokens in a macro can be concatenated into one token using the token
pasting (<strong>##</strong>) operator, as is standard for C++ preprocessors.
The result must be a valid single token, which will then be subject to macro
expansion.
That is, macro expansion happens only after token pasting.
There are no other number sign based operators (e.g. no <strong>#</strong> or <strong>#@</strong>), nor is
there a <strong>sizeof</strong> operator.</p>
</div>
<div class="paragraph">
<p>The semantics of applying operators to integer literals in the preprocessor
match those standard in the C++ preprocessor, not those in the OpenGL Shading Language.</p>
</div>
<div class="paragraph">
<p>Preprocessor expressions will be evaluated according to the behavior of the
host processor, not the processor targeted by the shader.</p>
</div>
<div class="paragraph">
<p><strong>#error</strong> will cause the implementation to put a compile-time diagnostic message
into the shader object&#8217;s information log (see section 7.12 &#8220;Shader, Program
and Program Pipeline Queries&#8221; of the <a href="#references">OpenGL Specification</a> for how to
access a shader object&#8217;s information log).
The message will be the tokens following the <strong>#error</strong> directive, up to the
first new-line.
The implementation must treat the presence of a <strong>#error</strong> directive as a
compile-time error.</p>
</div>
<div class="paragraph">
<p><strong>#pragma</strong> allows implementation-dependent compiler control.
Tokens following <strong>#pragma</strong> are not subject to preprocessor macro expansion.
If an implementation does not recognize the tokens following <strong>#pragma</strong>, then
it will ignore that pragma.
The following pragmas are defined as part of the language.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> STDGL</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>STDGL</strong> pragma is used to reserve pragmas for use by future revisions of
this language.
No implementation may use a pragma whose first token is <strong>STDGL</strong>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> optimize(on)
<span class="preprocessor">#pragma</span> optimize(off)</code></pre>
</div>
</div>
<div class="paragraph">
<p>can be used to turn off optimizations as an aid in developing and debugging
shaders.
It can only be used outside function definitions.
By default, optimization is turned on for all shaders.
The debug pragma</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> debug(on)
<span class="preprocessor">#pragma</span> debug(off)</code></pre>
</div>
</div>
<div class="paragraph">
<p>can be used to enable compiling and annotating a shader with debug
information, so that it can be used with a debugger.
It can only be used outside function definitions.
By default, debug is turned off.</p>
</div>
<div class="paragraph">
<p>Shaders should declare the version of the language they are written to.
The language version a shader is written to is specified by</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#version</span> number profile_opt</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <em>number</em> must be a version of the language, following the same
convention as __VERSION__ above.
The directive &#8220;<strong>#version 460</strong>&#8221; is required in any shader that
uses version 4.60 of the language.
Any <em>number</em> representing a version of the language a compiler does not
support will cause a compile-time error to be generated.
Version 1.10 of the language does not require shaders to include this
directive, and shaders that do not include a <strong>#version</strong> directive will be
treated as targeting version 1.10.
Shaders that specify <strong>#version</strong> 100 will be treated as targeting version
1.00 of the OpenGL ES Shading Language.
Shaders that specify <strong>#version</strong> 300 will be treated as targeting version
3.00 of the OpenGL ES Shading Language.
Shaders that specify <strong>#version</strong> 310 will be treated as targeting version
3.10 of the OpenGL ES Shading Language.</p>
</div>
<div class="paragraph">
<p>If the optional <em>profile</em> argument is provided, it must be the name of an
OpenGL profile.
Currently, there are three choices:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">core
compatibility
es</code></pre>
</div>
</div>
<div class="paragraph">
<p>A <em>profile</em> argument can only be used with version 150 or greater.
If no profile argument is provided and the version is 150 or greater, the
default is <strong>core</strong>.
If version 300 or 310 is specified, the profile argument is not optional and
must be <strong>es</strong>, or a compile-time error results.
The Language Specification for the <strong>es</strong> profile is specified in The OpenGL
ES Shading Language specification.</p>
</div>
<div class="paragraph">
<p>Shaders for the <strong>core</strong> or <strong>compatibility</strong> profiles that declare different
versions can be linked together.
However, <strong>es</strong> profile shaders cannot be linked with non-<strong>es</strong> profile shaders
or with <strong>es</strong> profile shaders of a different version, or a link-time error
will result.
When linking shaders of versions allowed by these rules, remaining link-time
errors will be given as per the linking rules in the GLSL version
corresponding to the version of the context the shaders are linked under.
Shader compile-time errors must still be given strictly based on the version
declared (or defaulted to) within each shader.</p>
</div>
<div class="paragraph">
<p>Unless otherwise specified, this specification is documenting the core
profile, and everything specified for the core profile is also available in
the compatibility profile.
Features specified as belonging specifically to the compatibility profile
are not available in the core profile.
Compatibility-profile features are not available when generating SPIR-V.</p>
</div>
<div class="paragraph">
<p>There is a built-in macro definition for each profile the implementation
supports.
All implementations provide the following macro:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_core_profile <span class="integer">1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Implementations providing the <strong>compatibility</strong> profile provide the following
macro:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_compatibility_profile <span class="integer">1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Implementations providing the <strong>es</strong> profile provide the following macro:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_es_profile <span class="integer">1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>#version</strong> directive must occur in a shader before anything else, except
for comments and white space.</p>
</div>
<div class="paragraph">
<p>By default, compilers of this language must issue compile-time
lexical
and
grammatical errors for shaders that do not conform to this specification.
Any extended behavior must first be enabled.
Directives to control the behavior of the compiler with respect to
extensions are declared with the <strong>#extension</strong> directive</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#extension</span> extension_name : behavior
<span class="preprocessor">#extension</span> all : behavior</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <em>extension_name</em> is the name of an extension.
Extension names are not documented in this specification.
The token <strong>all</strong> means the behavior applies to all extensions supported by
the compiler.
The <em>behavior</em> can be one of the following:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Behavior</th>
<th class="tableblock halign-left valign-top">Effect</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>require</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>.<br>
Give a compile-time error on the <strong>#extension</strong> if the extension
<em>extension_name</em> is not supported, or if <strong>all</strong> is specified.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>enable</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>.<br>
Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is
not supported.<br>
Give a compile-time error on the <strong>#extension</strong> if <strong>all</strong> is
specified.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>warn</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>,
except issue warnings on any detectable use of that extension,
unless such use is supported by other enabled or required
extensions.<br>
If <strong>all</strong> is specified, then warn on all detectable uses of any
extension used.<br>
Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is
not supported.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>disable</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Behave (including issuing errors and warnings) as if the
extension <em>extension_name</em> is not part of the language
definition.<br>
If <strong>all</strong> is specified, then behavior must revert back to that
of the non-extended core version of the language being
compiled to.<br>
Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is
not supported.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The <strong>extension</strong> directive is a simple, low-level mechanism to set the
behavior for each extension.
It does not define policies such as which combinations are appropriate,
those must be defined elsewhere.
Order of directives matters in setting the behavior for each extension:
Directives that occur later override those seen earlier.
The <strong>all</strong> variant sets the behavior for all extensions, overriding all
previously issued <strong>extension</strong> directives, but only for the <em>behaviors</em>
<strong>warn</strong> and <strong>disable</strong>.</p>
</div>
<div class="paragraph">
<p>The initial state of the compiler is as if the directive</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#extension</span> all : disable</code></pre>
</div>
</div>
<div class="paragraph">
<p>was issued, telling the compiler that all error and warning reporting must
be done according to this specification, ignoring any extensions.</p>
</div>
<div class="paragraph">
<p>Each extension can define its allowed granularity of scope.
If nothing is said, the granularity is a shader (that is, a single
compilation unit), and the extension directives must occur before any
non-preprocessor tokens.
If necessary, the linker can enforce granularities larger than a single
compilation unit, in which case each involved shader will have to contain
the necessary extension directive.</p>
</div>
<div class="paragraph">
<p>Macro expansion is not done on lines containing <strong>#extension</strong> and <strong>#version</strong>
directives.</p>
</div>
<div class="paragraph">
<p><strong>#line</strong> must have, after macro substitution, one of the following forms:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#line</span> line
<span class="preprocessor">#line</span> line source-<span class="predefined-type">string</span>-number</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <em>line</em> and <em>source-string-number</em> are
constant integer expressions.
If these constant expressions are not integer literals then behavior is undefined.
After processing this directive (including its new-line), the implementation
will behave as if it is compiling at line number <em>line</em> and source string
number <em>source-string-number</em>.
Subsequent source strings will be numbered sequentially, until another
<strong>#line</strong> directive overrides that numbering.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="title">Note</div>
<div class="paragraph">
<p>Some implementations have allowed constant expressions in #line directives and
some have not. Even where expressions are supported the grammar is ambiguous and so
results are implementation dependent. For example,
+ #line +2 +2 // Line number set to 4, or file to 2 and line to 2</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>When shaders are compiled for OpenGL SPIR-V, the following predefined
macro is available:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_SPIRV <span class="integer">100</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When targeting Vulkan, the following predefined macro is available:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> VULKAN <span class="integer">100</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="comments">3.4. Comments</h3>
<div class="paragraph">
<p>Comments are delimited by <strong>/*</strong> and <strong>*/</strong>, or by <strong>//</strong> and a new-line.
The begin comment delimiters (/* or //) are not recognized as comment
delimiters inside of a comment, hence comments cannot be nested.
A <strong>/*</strong> comment includes its terminating delimiter (*/).
However, a <strong>//</strong> comment does not include (or eliminate) its terminating new
line.</p>
</div>
<div class="paragraph">
<p>Inside comments, any byte values may be used, except a byte whose value is
0.
No errors will be given for the content of comments and no validation on the
content of comments need be done.</p>
</div>
<div class="paragraph">
<p>Removal of new-lines by the line-continuation character (<strong>\</strong>) logically
occurs before comments are processed.
That is, a single-line comment ending in the line-continuation character
(<strong>\</strong>) includes the next line in the comment.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// a single-line comment containing the next line \
a = b; // this is still in the first comment</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tokens">3.5. Tokens</h3>
<div class="paragraph">
<p>The language, after preprocessing, is a sequence of tokens.
A token can be</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>token</em> : </dt>
<dd>
<p><em>keyword</em><br>
<em>identifier</em><br>
<em>integer-constant</em><br>
<em>floating-constant</em><br>
<em>operator</em><br>
<strong>;</strong> <strong>{</strong> <strong>}</strong></p>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="keywords">3.6. Keywords</h3>
<div class="paragraph">
<p>The following are the keywords in the language and (after
preprocessing) can only be used as described in this specification,
or a compile-time error results:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><strong>const</strong> <strong>uniform</strong> <strong>buffer</strong> <strong>shared</strong>
<strong>attribute</strong> <strong>varying</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>coherent</strong> <strong>volatile</strong> <strong>restrict</strong> <strong>readonly</strong> <strong>writeonly</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>atomic_uint</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>layout</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>centroid</strong> <strong>flat</strong> <strong>smooth</strong>
<strong>noperspective</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>patch</strong> <strong>sample</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>invariant</strong> <strong>precise</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>break</strong> <strong>continue</strong> <strong>do</strong> <strong>for</strong> <strong>while</strong> <strong>switch</strong> <strong>case</strong> <strong>default</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>if</strong> <strong>else</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>subroutine</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>in</strong> <strong>out</strong> <strong>inout</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>int</strong> <strong>void</strong> <strong>bool</strong> <strong>true</strong> <strong>false</strong> <strong>float</strong>
<strong>double</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>discard</strong> <strong>return</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>vec2</strong> <strong>vec3</strong> <strong>vec4</strong> <strong>ivec2</strong> <strong>ivec3</strong> <strong>ivec4</strong> <strong>bvec2</strong> <strong>bvec3</strong> <strong>bvec4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>uint</strong> <strong>uvec2</strong> <strong>uvec3</strong> <strong>uvec4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>dvec2</strong> <strong>dvec3</strong> <strong>dvec4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>mat2</strong> <strong>mat3</strong> <strong>mat4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>mat2x2</strong> <strong>mat2x3</strong> <strong>mat2x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>mat3x2</strong> <strong>mat3x3</strong> <strong>mat3x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>mat4x2</strong> <strong>mat4x3</strong> <strong>mat4x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>dmat2</strong> <strong>dmat3</strong> <strong>dmat4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>dmat2x2</strong> <strong>dmat2x3</strong> <strong>dmat2x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>dmat3x2</strong> <strong>dmat3x3</strong> <strong>dmat3x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>dmat4x2</strong> <strong>dmat4x3</strong> <strong>dmat4x4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>lowp</strong> <strong>mediump</strong> <strong>highp</strong> <strong>precision</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler1D</strong> <strong>sampler1DShadow</strong> <strong>sampler1DArray</strong> <strong>sampler1DArrayShadow</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>isampler1D</strong> <strong>isampler1DArray</strong> <strong>usampler1D</strong> <strong>usampler1DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler2D</strong> <strong>sampler2DShadow</strong> <strong>sampler2DArray</strong> <strong>sampler2DArrayShadow</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>isampler2D</strong> <strong>isampler2DArray</strong> <strong>usampler2D</strong> <strong>usampler2DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler2DRect</strong> <strong>sampler2DRectShadow</strong> <strong>isampler2DRect</strong> <strong>usampler2DRect</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler2DMS</strong> <strong>isampler2DMS</strong> <strong>usampler2DMS</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler2DMSArray</strong> <strong>isampler2DMSArray</strong> <strong>usampler2DMSArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler3D</strong> <strong>isampler3D</strong> <strong>usampler3D</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>samplerCube</strong> <strong>samplerCubeShadow</strong> <strong>isamplerCube</strong> <strong>usamplerCube</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>samplerCubeArray</strong> <strong>samplerCubeArrayShadow</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>isamplerCubeArray</strong> <strong>usamplerCubeArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>samplerBuffer</strong> <strong>isamplerBuffer</strong> <strong>usamplerBuffer</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image1D</strong> <strong>iimage1D</strong> <strong>uimage1D</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image1DArray</strong> <strong>iimage1DArray</strong> <strong>uimage1DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image2D</strong> <strong>iimage2D</strong> <strong>uimage2D</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image2DArray</strong> <strong>iimage2DArray</strong> <strong>uimage2DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image2DRect</strong> <strong>iimage2DRect</strong> <strong>uimage2DRect</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image2DMS</strong> <strong>iimage2DMS</strong> <strong>uimage2DMS</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image2DMSArray</strong> <strong>iimage2DMSArray</strong> <strong>uimage2DMSArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>image3D</strong> <strong>iimage3D</strong> <strong>uimage3D</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>imageCube</strong> <strong>iimageCube</strong> <strong>uimageCube</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>imageCubeArray</strong> <strong>iimageCubeArray</strong> <strong>uimageCubeArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>imageBuffer</strong> <strong>iimageBuffer</strong> <strong>uimageBuffer</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>struct</strong></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>In addition, when targeting Vulkan, the following keywords also exist:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture1D</strong> <strong>texture1DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>itexture1D</strong> <strong>itexture1DArray</strong> <strong>utexture1D</strong> <strong>utexture1DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture2D</strong> <strong>texture2DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>itexture2D</strong> <strong>itexture2DArray</strong> <strong>utexture2D</strong> <strong>utexture2DArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture2DRect</strong> <strong>itexture2DRect</strong> <strong>utexture2DRect</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture2DMS</strong> <strong>itexture2DMS</strong> <strong>utexture2DMS</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture2DMSArray</strong> <strong>itexture2DMSArray</strong> <strong>utexture2DMSArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>texture3D</strong> <strong>itexture3D</strong> <strong>utexture3D</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>textureCube</strong> <strong>itextureCube</strong> <strong>utextureCube</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>textureCubeArray</strong> <strong>itextureCubeArray</strong> <strong>utextureCubeArray</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>textureBuffer</strong> <strong>itextureBuffer</strong> <strong>utextureBuffer</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler</strong> <strong>samplerShadow</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>subpassInput</strong> <strong>isubpassInput</strong> <strong>usubpassInput</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>subpassInputMS</strong> <strong>isubpassInputMS</strong> <strong>usubpassInputMS</strong></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The following are the keywords reserved for future use.
Using them will result in a compile-time error:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><strong>common</strong> <strong>partition</strong> <strong>active</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>asm</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>class</strong> <strong>union</strong> <strong>enum</strong> <strong>typedef</strong> <strong>template</strong> <strong>this</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>resource</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>goto</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>inline</strong> <strong>noinline</strong> <strong>public</strong> <strong>static</strong> <strong>extern</strong> <strong>external</strong> <strong>interface</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>long</strong> <strong>short</strong> <strong>half</strong> <strong>fixed</strong> <strong>unsigned</strong> <strong>superp</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>input</strong> <strong>output</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>hvec2</strong> <strong>hvec3</strong> <strong>hvec4</strong> <strong>fvec2</strong> <strong>fvec3</strong> <strong>fvec4</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>filter</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sizeof</strong> <strong>cast</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>namespace</strong> <strong>using</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler3DRect</strong></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>In addition, all identifiers containing two consecutive underscores (__)
are reserved for use by underlying software layers.
Defining such a name in a shader does not itself result in an error, but may
result in unintended behaviors that stem from having multiple definitions of
the same name.</p>
</div>
</div>
<div class="sect2">
<h3 id="identifiers">3.7. Identifiers</h3>
<div class="paragraph">
<p>Identifiers are used for variable names, function names, structure names,
and field selectors (field selectors select components of
<code><a href="#vector-components">vectors</a></code> and <code><a href="#matrix-components">matrices</a></code>,
similarly to structure members).
Identifiers have the form:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>identifier</em> : </dt>
<dd>
<p><em>nondigit</em><br>
<em>identifier</em> <em>nondigit</em><br>
<em>identifier</em> <em>digit</em></p>
</dd>
<dt class="hdlist1"><em>nondigit</em> : one of </dt>
<dd>
<p><strong>_</strong> <strong>a b c d e f g h i j k l m n o p q r s t u v w x y z</strong><br>
<strong>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z</strong></p>
</dd>
<dt class="hdlist1"><em>digit</em> : one of </dt>
<dd>
<p><strong>0 1 2 3 4 5 6 7 8 9</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Identifiers starting with &#8220;gl_&#8221; are reserved, and
in general, may not be declared in a shader;
this results in a compile-time error.
However, as noted in the specification, there are some cases where
previously declared variables can be redeclared, and predeclared &#8220;gl_&#8221;
names are allowed to be redeclared in a shader only for these specific
purposes.</p>
</div>
<div class="paragraph">
<p>Implementations must support identifier lengths of up to 1024 characters.
Implementations are allowed to generate an error for an identifier of length
greater than 1024 characters, but are also allowed to support lengths
greater than 1024.</p>
</div>
</div>
<div class="sect2">
<h3 id="definitions">3.8. Definitions</h3>
<div class="paragraph">
<p>Some language rules described below depend on the following definitions.</p>
</div>
<div class="sect3">
<h4 id="static-use">3.8.1. Static Use</h4>
<div class="paragraph">
<p>A shader contains a <em>static use</em> of a variable <em>x</em> if, after preprocessing,
the shader contains a statement that would access any part of <em>x</em>,
whether or not flow of control will cause that statement to be executed.
Such a variable is referred to as being <em>statically used</em>. If the access is a
write then <em>x</em> is further said to be <em>statically assigned</em>.</p>
</div>
</div>
<div class="sect3">
<h4 id="dynamically-uniform-expressions-and-uniform-control-flow">3.8.2. Dynamically Uniform Expressions and Uniform Control Flow</h4>
<div class="paragraph">
<p>Some operations require an expression to be <em>dynamically uniform</em>, or that
it be located in <em>uniform control flow</em>.
These requirements are defined by the following set of definitions.</p>
</div>
<div class="paragraph">
<p>An <em>invocation</em> is a single execution of <em>main()</em> for a particular stage,
operating only on the amount of data explicitly exposed within that stage&#8217;s
shaders.
(Any implicit operation on additional instances of data would comprise
additional invocations.) For example, in compute execution models, a single
invocation operates only on a single work item, or, in a vertex execution
model, a single invocation operates only on a single vertex.</p>
</div>
<div class="paragraph">
<p>An <em>invocation group</em> is the complete set of invocations collectively
processing a particular compute workgroup or graphical operation, where the
scope of a "graphical operation" is implementation-dependent, but at least
as large as a single triangle or patch, and at most as large as a single
rendering command, as defined by the client API.</p>
</div>
<div class="paragraph">
<p>Within a single invocation, a single shader statement can be executed
multiple times, giving multiple <em>dynamic instances</em> of that instruction.
This can happen when the instruction is executed in a loop, or in a function
called from multiple call sites, or combinations of multiple of these.
Different loop iterations and different dynamic function-call-site chains
yield different dynamic instances of such an instruction.
Dynamic instances are distinguished by their control-flow path within an
invocation, not by which invocation executed it.
That is, different invocations of <em>main()</em> execute the same dynamic
instances of an instruction when they follow the same control-flow path.</p>
</div>
<div class="paragraph">
<p>An expression is <em>dynamically uniform</em> for a dynamic instance consuming it
when its value is the same for all invocations (in the invocation group)
that execute that dynamic instance.</p>
</div>
<div class="paragraph">
<p><em>Uniform control flow</em> (or converged control flow) occurs when all
invocations in the invocation group execute the same control-flow path (and
hence the same sequence of dynamic instances of instructions).
Uniform control flow is the initial state at the entry into <em>main()</em>, and
lasts until a conditional branch takes different control paths for different
invocations (non-uniform or divergent control flow).
Such divergence can reconverge, with all the invocations once again
executing the same control-flow path, and this re-establishes the existence
of uniform control flow.
If control flow is uniform upon entry into a selection or loop, and all
invocations in the invocation group subsequently leave that selection or
loop, then control flow reconverges to be uniform.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">main()
{
<span class="predefined-type">float</span> a = ...; <span class="comment">// this is uniform control flow</span>
<span class="keyword">if</span> (a &lt; b) { <span class="comment">// this expression is true for some fragments, not all</span>
...; <span class="comment">// non-uniform control flow</span>
} <span class="keyword">else</span> {
...; <span class="comment">// non-uniform control flow</span>
}
...; <span class="comment">// uniform control flow again</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that constant expressions are trivially dynamically uniform.
It follows that typical loop counters based on these are also dynamically
uniform.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="variables-and-types">4. Variables and Types</h2>
<div class="sectionbody">
<div class="paragraph">
<p>All variables and functions must be declared before being used.
Variable and function names are identifiers.</p>
</div>
<div class="paragraph">
<p>There are no default types.
All variable and function declarations must have a declared type, and
optionally qualifiers.
A variable is declared by specifying its type followed by one or more names
separated by commas.
In many cases, a variable can be initialized as part of its declaration by
using the assignment operator (<strong>=</strong>).</p>
</div>
<div class="paragraph">
<p>User-defined types may be defined using <strong>struct</strong> to aggregate a list of
existing types into a single name.</p>
</div>
<div class="paragraph">
<p>The OpenGL Shading Language is type safe.
There are some implicit conversions between types.
Exactly how and when this can occur is described in section
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; and as referenced by other
sections in this specification.</p>
</div>
<div class="sect2">
<h3 id="basic-types">4.1. Basic Types</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">Definition</dt>
<dd>
<p>A <em>basic type</em> is a type defined by a keyword in the language.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The OpenGL Shading Language supports the following basic data types, grouped as follows.</p>
</div>
<div class="paragraph">
<p><strong>Transparent Types</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>void</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">for functions that do not return a value</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bool</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a conditional type, taking on values of true or false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a signed integer</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uint</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">an unsigned integer</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>float</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point scalar</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>double</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point scalar</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a two-component single-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a three-component single-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a four-component single-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a two-component double-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a three-component double-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a four-component double-precision floating-point vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a two-component Boolean vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a three-component Boolean vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a four-component Boolean vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a two-component signed integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a three-component signed integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a four-component signed integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a two-component unsigned integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a three-component unsigned integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a four-component unsigned integer vector</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 2 × 2 single-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 3 × 3 single-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 4 × 4 single-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 2 columns and 3 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 2 columns and 4 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 3 columns and 2 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 3 columns and 4 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 4 columns and 2 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 4 columns and 3 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 2 × 2 double-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 3 × 3 double-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a 4 × 4 double-precision floating-point matrix</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 2 columns and 3 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 2 columns and 4 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 3 columns and 2 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 3 columns and 4 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 4 columns and 2 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 4 columns and 3 rows</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat4</strong></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Note that where the following tables say &#8220;accessing a texture&#8221;, the
<strong>sampler*</strong> opaque types access textures, and the <strong>image*</strong> opaque types
access images, of a specified type.</p>
</div>
<div class="paragraph">
<p><strong>Floating-Point Opaque Types</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1D</strong><br>
<strong>texture1D</strong><br>
<strong>image1D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DArray</strong><br>
<strong>texture1DArray</strong><br>
<strong>image1DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DArrayShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D array depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2D</strong><br>
<strong>texture2D</strong><br>
<strong>image2D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DArray</strong><br>
<strong>texture2DArray</strong><br>
<strong>image2DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DArrayShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D array depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DMS</strong><br>
<strong>texture2DMS</strong><br>
<strong>image2DMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D multisample texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DMSArray</strong><br>
<strong>texture2DMSArray</strong><br>
<strong>image2DMSArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D multisample array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DRect</strong><br>
<strong>texture2DRect</strong><br>
<strong>image2DRect</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a rectangle texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DRectShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a rectangle texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler3D</strong><br>
<strong>texture3D</strong><br>
<strong>image3D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 3D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCube</strong><br>
<strong>textureCube</strong><br>
<strong>imageCube</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube mapped texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeArray</strong><br>
<strong>textureCubeArray</strong><br>
<strong>imageCubeArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeArrayShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map array depth texture with comparison</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerBuffer</strong><br>
<strong>textureBuffer</strong><br>
<strong>imageBuffer</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a buffer texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>subpassInput</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a floating-point subpass input</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>subpassInputMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled floating-point subpass input</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><strong>Signed Integer Opaque Types</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler1D</strong><br>
<strong>itexture1D</strong><br>
<strong>iimage1D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 1D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler1DArray</strong><br>
<strong>itexture1DArray</strong><br>
<strong>iimage1DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 1D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2D</strong><br>
<strong>itexture2D</strong><br>
<strong>iimage2D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DArray</strong><br>
<strong>itexture2DArray</strong><br>
<strong>iimage2DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DMS</strong><br>
<strong>itexture2DMS</strong><br>
<strong>iimage2DMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D multisample texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DMSArray</strong><br>
<strong>itexture2DMSArray</strong><br>
<strong>iimage2DMSArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D multisample array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DRect</strong><br>
<strong>itexture2DRect</strong><br>
<strong>iimage2DRect</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D rectangle texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler3D</strong><br>
<strong>itexture3D</strong><br>
<strong>iimage3D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 3D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerCube</strong><br>
<strong>itextureCube</strong><br>
<strong>iimageCube</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer cube mapped texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerCubeArray</strong><br>
<strong>itextureCubeArray</strong><br>
<strong>iimageCubeArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer cube map array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerBuffer</strong><br>
<strong>itextureBuffer</strong><br>
<strong>iimageBuffer</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer buffer texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isubpassInput</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer subpass input</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isubpassInputMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled integer subpass input</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><strong>Unsigned Integer Opaque Types</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler1D</strong><br>
<strong>utexture1D</strong><br>
<strong>uimage1D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 1D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler1DArray</strong><br>
<strong>utexture1DArray</strong><br>
<strong>uimage1DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 1D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2D</strong><br>
<strong>utexture2D</strong><br>
<strong>uimage2D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DArray</strong><br>
<strong>utexture1DArray</strong><br>
<strong>uimage2DArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DMS</strong><br>
<strong>utexture2DMS</strong><br>
<strong>uimage2DMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D multisample texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DMSArray</strong><br>
<strong>utexture2DMSArray</strong><br>
<strong>uimage2DMSArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D multisample array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DRect</strong><br>
<strong>utexture2DRect</strong><br>
<strong>uimage2DRect</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer rectangle texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler3D</strong><br>
<strong>utexture3D</strong><br>
<strong>uimage3D</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 3D texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerCube</strong><br>
<strong>utextureCube</strong><br>
<strong>uimageCube</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer cube mapped texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerCubeArray</strong><br>
<strong>utextureCubeArray</strong><br>
<strong>uimageCubeArray</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer cube map array texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerBuffer</strong><br>
<strong>utextureBuffer</strong><br>
<strong>uimageBuffer</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer buffer texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atomic_uint</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer atomic counter</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usubpassInput</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned-integer subpass input</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usubpassInputMS</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled unsigned-integer subpass input</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><strong>Sampler Opaque Types</strong></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing state describing how to sample a texture</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerShadow</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing state describing how to sample a depth
texture with comparison</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>In addition, a shader can aggregate these basic types using arrays and
structures to build more complex types.</p>
</div>
<div class="paragraph">
<p>There are no pointer types.</p>
</div>
<div class="paragraph">
<p>In this specification, an <em>aggregate</em> will mean a structure or array.
(Matrices and vectors are not by themselves aggregates.) Aggregates,
matrices, and vectors will collectively be referred to as <em>composites</em>.</p>
</div>
<div class="sect3">
<h4 id="void">4.1.1. Void</h4>
<div class="paragraph">
<p>Functions that do not return a value must be declared as <strong>void</strong>.
There is no default function return type.
The keyword <strong>void</strong> cannot be used in any other declarations (except for
empty formal or actual parameter lists), or a compile-time error results.</p>
</div>
</div>
<div class="sect3">
<h4 id="booleans">4.1.2. Booleans</h4>
<div class="dlist">
<dl>
<dt class="hdlist1">Definition</dt>
<dd>
<p>A <em>boolean type</em> is any boolean scalar or vector type (<strong>bool</strong>, <strong>bvec2</strong>,
<strong>bvec3</strong>, <strong>bvec4</strong>)</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>To make conditional execution of code easier to express, the type <strong>bool</strong> is
supported.
There is no expectation that hardware directly supports variables of this
type.
It is a genuine Boolean type, holding only one of two values meaning either
true or false.
Two keywords <strong>true</strong> and <strong>false</strong> can be used as literal Boolean constants.
Booleans are declared and optionally initialized as in the follow example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">bool</span> success; <span class="comment">// declare &quot;success&quot; to be a Boolean</span>
<span class="predefined-type">bool</span> done = <span class="predefined-constant">false</span>; <span class="comment">// declare and initialize &quot;done&quot;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Expressions used for conditional jumps (<strong>if</strong>, <strong>for</strong>, <strong>?:</strong>, <strong>while</strong>,
<strong>do</strong>-<strong>while</strong>) must evaluate to the type <strong>bool</strong>.</p>
</div>
</div>
<div class="sect3">
<h4 id="integers">4.1.3. Integers</h4>
<div class="dlist">
<dl>
<dt class="hdlist1">Definitions</dt>
<dd>
<p>An <em>integral type</em> is any signed or unsigned, scalar or vector integer type.
It excludes arrays and structures.</p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>A <em>scalar integral type</em> is a scalar signed or unsigned integer type:</p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>A <em>vector integral type</em> is a vector of signed or unsigned integers:</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Signed and unsigned integer variables are fully supported.
In this document, the term <em>integer</em> is meant to generally include both
signed and unsigned integers.</p>
</div>
<div class="paragraph">
<p>For OpenGL, unsigned integers have exactly 32 bits of precision.
When targeting Vulkan, <strong>highp</strong>
unsigned integers have exactly 32 bits of precision.</p>
</div>
<div class="paragraph">
<p>For OpenGL, signed integers use 32 bits, including a sign bit, in two&#8217;s complement form.
When targeting Vulkan, <strong>highp</strong>
signed integers use 32 bits, including a sign bit, in two&#8217;s complement form.</p>
</div>
<div class="paragraph">
<p>When targeting Vulkan, <strong>mediump</strong> and <strong>lowp</strong> integers are as defined by the
SPIR-V <strong>RelaxedPrecision</strong> decoration.</p>
</div>
<div class="paragraph">
<p>Addition,
subtraction and multiplication resulting in overflow or
underflow will result in the low-order
32
bits of the correct result R, where
R is computed with enough precision to avoid overflow or underflow.
Division resulting in overflow will result in an undefined value.</p>
</div>
<div class="paragraph">
<p>Integers are declared and optionally initialized with integer expressions,
as in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i, j = <span class="integer">42</span>; <span class="comment">// default integer literal type is int</span>
uint k = <span class="integer">3</span>u; <span class="comment">// &quot;u&quot; establishes the type as uint</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Literal integer constants can be expressed in decimal (base 10), octal (base
8), or hexadecimal (base 16) as follows.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>integer-constant</em> : </dt>
<dd>
<p><em>decimal-constant</em> <em>integer-suffix<sub>opt</sub></em><br>
<em>octal-constant</em> <em>integer-suffix<sub>opt</sub></em><br>
<em>hexadecimal-constant</em> <em>integer-suffix<sub>opt</sub></em></p>
</dd>
<dt class="hdlist1"><em>integer-suffix</em> : one of </dt>
<dd>
<p><strong>u</strong> <strong>U</strong></p>
</dd>
<dt class="hdlist1"><em>decimal-constant</em> : </dt>
<dd>
<p><em>nonzero-digit</em><br>
<em>decimal-constant</em> <em>digit</em></p>
</dd>
<dt class="hdlist1"><em>octal-constant</em> : </dt>
<dd>
<p><strong>0</strong><br>
<em>octal-constant</em> <em>octal-digit</em></p>
</dd>
<dt class="hdlist1"><em>hexadecimal-constant</em> : </dt>
<dd>
<p><strong>0x</strong> <em>hexadecimal-digit</em><br>
<strong>0X</strong> <em>hexadecimal-digit</em><br>
<em>hexadecimal-constant</em> <em>hexadecimal-digit</em></p>
</dd>
<dt class="hdlist1"><em>digit</em> : </dt>
<dd>
<p><strong>0</strong><br>
<em>nonzero-digit</em></p>
</dd>
<dt class="hdlist1"><em>nonzero-digit</em> : one of </dt>
<dd>
<p><strong>1 2 3 4 5 6 7 8 9</strong></p>
</dd>
<dt class="hdlist1"><em>octal-digit</em> : one of </dt>
<dd>
<p><strong>0 1 2 3 4 5 6 7</strong></p>
</dd>
<dt class="hdlist1"><em>hexadecimal-digit</em> : one of </dt>
<dd>
<p><strong>0 1 2 3 4 5 6 7 8 9<br>
a b c d e f<br>
A B C D E F</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>No white space is allowed between the digits of an integer constant,
including after the leading <strong>0</strong> or after the leading <strong>0x</strong> or <strong>0X</strong> of a
constant, or before the suffix <strong>u</strong> or <strong>U</strong>.
When tokenizing, the maximal token matching the above will be recognized
before a new token is started.
When the suffix <strong>u</strong> or <strong>U</strong> is present, the literal has type <strong>uint</strong>,
otherwise the type is <strong>int</strong>.
A leading unary minus sign (-) is interpreted as an arithmetic unary
negation, not as part of the constant.
Hence, literals themselves are always expressed with non-negative syntax,
though they could result in a negative value.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to provide a literal integer whose bit pattern
cannot fit in 32 bits.
The bit pattern of the literal is always used unmodified.
So a signed literal whose bit pattern includes a set sign bit creates a
negative value.</p>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="integer">1</span> <span class="comment">// OK. Signed integer, value 1</span>
<span class="integer">1</span>u <span class="comment">// OK. Unsigned integer, value 1</span>
-<span class="integer">1</span> <span class="comment">// OK. Unary minus applied to signed integer.</span>
<span class="comment">// result is a signed integer, value -1</span>
-<span class="integer">1</span>u <span class="comment">// OK. Unary minus applies to unsigned integer.</span>
<span class="comment">// Result is an unsigned integer, value 0xffffffff</span>
<span class="hex">0xA0000000</span> <span class="comment">// OK. 32-bit signed hexadecimal</span>
<span class="hex">0xABcdEF00</span>u <span class="comment">// OK. 32-bit unsigned hexadecimal</span>
<span class="hex">0xffffffff</span> <span class="comment">// OK. Signed integer, value -1</span>
<span class="hex">0x80000000</span> <span class="comment">// OK. Evaluates to -2147483648</span>
<span class="hex">0xffffffff</span>u <span class="comment">// OK. Unsigned integer, value 0xffffffff</span>
<span class="hex">0xfffffffff</span> <span class="comment">// Error: needs more than 32 bits</span>
<span class="integer">3000000000</span> <span class="comment">// OK. A signed decimal literal taking 32 bits.</span>
<span class="comment">// It evaluates to -1294967296</span>
<span class="integer">2147483648</span> <span class="comment">// OK. Evaluates to -2147483648 (the literal set the sign bit)</span>
<span class="integer">5000000000</span> <span class="comment">// Error: needs more than 32 bits</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="floats">4.1.4. Floats</h4>
<div class="paragraph">
<p>Single-precision and double-precision floating-point variables are available
for use in a variety of scalar calculations.
Generally, the term <em>floating-point</em> will refer to both single- and
double-precision floating-point.
Floating-point variables are defined as in the following examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a, b = <span class="float">1</span><span class="float">.5</span>; <span class="comment">// single-precision floating-point</span>
<span class="predefined-type">double</span> c, d = <span class="float">2</span><span class="float">.0</span>LF; <span class="comment">// double-precision floating-point</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>As an input value to one of the processing units, a single-precision or
double-precision floating-point variable is expected to match the
corresponding IEEE 754 floating-point definition for precision and dynamic
range.
Floating-point variables within a shader are also encoded according to the
IEEE 754 specification for single-precision floating-point values</p>
</div>
<div class="paragraph">
<p>(logically, not necessarily physically).
While encodings are logically IEEE 754, operations (addition,
multiplication, etc.) are not necessarily performed as required by IEEE 754.
See &#8220;<a href="#range-and-precision">Range and Precision</a>&#8221; for more details on
precision and usage of NaNs (Not a Number) and Infs (positive or negative
infinities).</p>
</div>
<div class="paragraph">
<p>Floating-point constants are defined as follows.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>floating-constant</em> : </dt>
<dd>
<p><em>fractional-constant</em> <em>exponent-part<sub>opt</sub></em> <em>floating-suffix<sub>opt</sub></em><br>
<em>digit-sequence</em> <em>exponent-part</em> <em>floating-suffix<sub>opt</sub></em></p>
</dd>
<dt class="hdlist1"><em>fractional-constant</em> : </dt>
<dd>
<p><em>digit-sequence</em> <strong>.</strong> <em>digit-sequence</em><br>
<em>digit-sequence</em> <strong>.</strong><br>
<strong>.</strong> <em>digit-sequence</em></p>
</dd>
<dt class="hdlist1"><em>exponent-part</em> : </dt>
<dd>
<p><strong>e</strong> <em>sign<sub>opt</sub></em> <em>digit-sequence</em><br>
<strong>E</strong> <em>sign<sub>opt</sub></em> <em>digit-sequence</em></p>
</dd>
<dt class="hdlist1"><em>sign</em> : one of </dt>
<dd>
<p><strong>+</strong> <strong>-</strong></p>
</dd>
<dt class="hdlist1"><em>digit-sequence</em> : </dt>
<dd>
<p><em>digit</em><br>
<em>digit-sequence</em> <em>digit</em></p>
</dd>
<dt class="hdlist1"><em>floating-suffix</em> : one of </dt>
<dd>
<p> <strong>f</strong> <strong>F</strong>
<strong>lf</strong> <strong>LF</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>A decimal point (<strong>.</strong>) is not needed if the exponent part is present.
No white space may appear anywhere within a floating-point constant,
including before a suffix.
When tokenizing, the maximal token matching the above will be recognized
before a new token is started.
When the suffix "lf" or "LF" is present, the literal has type <strong>double</strong>.
Otherwise, the literal has type <strong>float</strong>.
A leading unary minus sign (<strong>-</strong>) is interpreted as a unary operator and is
not part of the floating-point constant.</p>
</div>
</div>
<div class="sect3">
<h4 id="vectors">4.1.5. Vectors</h4>
<div class="paragraph">
<p>The OpenGL Shading Language includes data types for generic 2-, 3-, and 4-component vectors
of floating-point values, integers, and Booleans.
Floating-point vector variables can be used to store colors, normals,
positions, texture coordinates, texture lookup results and the like.
Boolean vectors can be used for component-wise comparisons of numeric
vectors.
Some examples of vector declarations are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec2 texcoord1, texcoord2;
vec3 position;
vec4 myRGBA;
ivec2 textureLookup;
bvec3 less;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Initialization of vectors can be done with constructors.
See &#8220;<a href="#vector-and-matrix-constructors">Vector and Matrix Constructors</a>&#8221;.</p>
</div>
</div>
<div class="sect3">
<h4 id="matrices">4.1.6. Matrices</h4>
<div class="paragraph">
<p>The OpenGL Shading Language has built-in types for 2 × 2, 2 × 3, 2 × 4, 3
× 2, 3 × 3, 3 × 4, 4 × 2, 4 × 3, and 4 ×
4 matrices of floating-point numbers.
Matrix types beginning with "<strong>mat</strong>" have single-precision components while
matrix types beginning with "<strong>dmat</strong>" have double-precision components.
The first number in the type is the number of columns, the second is the
number of rows.
If there is only one number, the matrix is square.
Example matrix declarations:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat2 mat2D;
mat3 optMatrix;
mat4 view, projection;
mat4x4 view; <span class="comment">// an alternate way of declaring a mat4</span>
mat3x2 m; <span class="comment">// a matrix with 3 columns and 2 rows</span>
dmat4 highPrecisionMVP;
dmat2x4 dm;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Initialization of matrix values is done with constructors (described in
&#8220;<a href="#vector-and-matrix-constructors">Vector and Matrix Constructors</a>&#8221;) in
column-major order.</p>
</div>
</div>
<div class="sect3">
<h4 id="opaque-types">4.1.7. Opaque Types</h4>
<div class="dlist">
<dl>
<dt class="hdlist1">Definition</dt>
<dd>
<p>An <em>opaque type</em> is a type where the internal structure of the type is
hidden from the language.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The opaque types, as listed in the following sections, declare variables
that are effectively opaque handles to other objects.
These objects are accessed through built-in functions, not through direct
reading or writing of the declared variable.
They can only be declared as function parameters or in <strong>uniform</strong>-qualified
variables (see &#8220;<a href="#uniform-variables">Uniform Variables</a>&#8221;).
The only opaque types that take memory qualifiers are the image types.
Except for array indexing, structure member selection, and parentheses,
opaque variables are not allowed to be operands in expressions; such use
results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>Opaque variables cannot be treated as l-values; hence cannot be used as
<strong>out</strong> or <strong>inout</strong> function parameters, nor can they be assigned into.
Any such use results in a compile-time error.
However, they can be passed as <strong>in</strong> parameters with matching types and
memory qualifiers.
They cannot be declared with an initializer.</p>
</div>
<div class="paragraph">
<p>Because a single opaque type declaration effectively declares two objects,
the opaque handle itself and the object it is a handle to, there is room for
both a storage qualifier and a memory qualifier.
The storage qualifier will qualify the opaque handle, while the memory
qualifier will qualify the object it is a handle to.</p>
</div>
<div class="sect4">
<h5 id="samplers">Texture-Combined Samplers</h5>
<div class="paragraph">
<p>Texture-combined sampler types (e.g. <strong>sampler2D</strong>) are the sampler types
described in the Basic Types tables as handles for accessing textures.
(They do not include <strong>sampler</strong> and <strong>samplerShadow</strong>.)
There are distinct texture-combined sampler types for each texture target,
and for each of float, integer, and unsigned integer data types.
Texture accesses are done through built-in texture functions (described in
&#8220;<a href="#texture-functions">Texture Functions</a>&#8221;) and texture-combined samplers
are used to specify which texture to access and how it is to be filtered.</p>
</div>
<div class="paragraph">
<p>Texture-combined sampler types are opaque types,
declared and behaving as described above for opaque types.
When aggregated into arrays within a shader, they can only be indexed
with a dynamically uniform integral expression, otherwise results are
undefined.</p>
</div>
</div>
<div class="sect4">
<h5 id="images">Images</h5>
<div class="paragraph">
<p>Image types are opaque types, declared and behaving as described above for
opaque types.
They can be further qualified with memory qualifiers.
When aggregated into arrays within a shader, images can only be indexed with
a dynamically uniform integral expression, otherwise results are undefined.</p>
</div>
<div class="paragraph">
<p>Image variables are handles to
one-,
two-, or three-dimensional images
corresponding to all or a portion of a single level of a texture image bound
to an image unit.
There are distinct image variable types for each texture target, and for
each of float, integer, and unsigned integer data types.
Image accesses should use an image type that matches the target of the
texture whose level is bound to the image unit, or for non-layered bindings
of 3D or array images should use the image type that matches the
dimensionality of the layer of the image (i.e., a layer of 3D, 2DArray,
Cube, or CubeArray should use
<strong>image2D</strong>, a layer of 1DArray should use <strong>image1D</strong>, and a layer of 2DMSArray
should use <strong>image2DMS</strong>).
If the image target type does not match the bound image in this manner, if
the data type does not match the bound image, or if the format layout
qualifier does not match the image unit format as described in section
8.25
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL Specification</a>, the
results of image accesses are undefined but cannot include program
termination.</p>
</div>
<div class="paragraph">
<p>Image variables are used in the image load, store, and atomic functions
described in &#8220;<a href="#image-functions">Image Functions</a>&#8221; to specify an image to
access.</p>
</div>
</div>
<div class="sect4">
<h5 id="atomic-counters">Atomic Counters</h5>
<div class="paragraph">
<p>Atomic counter types (e.g. <strong>atomic_uint</strong>) are opaque handles to counters,
declared and behaving as described above for opaque types.
The variables they declare specify which counter to access when using the
built-in atomic counter functions as described in
&#8220;<a href="#atomic-counter-functions">Atomic Counter Functions</a>&#8221;.
They are bound to buffers as described in
&#8220;<a href="#atomic-counter-layout-qualifiers">Atomic Counter Layout Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Atomic counters aggregated into arrays within a shader can only be indexed
with dynamically uniform integral expressions, otherwise results are
undefined.</p>
</div>
<div class="paragraph">
<p>Members of structures cannot be declared as atomic counter types.</p>
</div>
<div class="paragraph">
<p>Atomic counter types are not available when targeting Vulkan.</p>
</div>
</div>
<div class="sect4">
<h5 id="_texture_sampler_and_samplershadow_types">Texture, <strong>sampler</strong>, and <strong>samplerShadow</strong> Types</h5>
<div class="paragraph">
<p>Texture (e.g., <strong>texture2D</strong>), <strong>sampler</strong>, and <strong>samplerShadow</strong> types are opaque
types, declared and behaving as described above for opaque types.
These types are only available when targeting Vulkan.
When aggregated into arrays within a shader, these types can only be indexed
with a dynamically uniform expression, or texture lookup will result in
undefined values.
Texture variables are handles to one-, two-, and three-dimensional textures,
cube maps, etc., as enumerated in the basic types tables.
There are distinct texture types for each texture target, and for each of
float, integer, and unsigned integer data types.
Textures can be combined with a variable of type <strong>sampler</strong> or <strong>samplerShadow</strong>
to create a texture-combined sampler type (e.g., sampler2D, or sampler2DShadow).
This is done with a constructor, e.g., <code>sampler2D(texture2D, sampler)</code>,
<code>sampler2DShadow(texture2D, sampler)</code>, <code>sampler2DShadow(texture2D, samplerShadow)</code>,
or <code>sampler2D(texture2D, samplerShadow)</code> and is described in more detail
in section 5.4 "Constructors".</p>
</div>
</div>
<div class="sect4">
<h5 id="_subpass_inputs">Subpass Inputs</h5>
<div class="paragraph">
<p>Subpass-input types are only available when targeting Vulkan.</p>
</div>
<div class="paragraph">
<p>Subpass-input types (e.g., <strong>subpassInput</strong>) are opaque types, declared
and behaving as described above for opaque types.
When aggregated into arrays within a shader, they can only be indexed with a
dynamically uniform integral expression, otherwise results are undefined.</p>
</div>
<div class="paragraph">
<p>Subpass-input types are handles to two-dimensional single sampled or
multi-sampled images, with distinct types for each of float, integer,
and unsigned integer data types.</p>
</div>
<div class="paragraph">
<p>Subpass-input types are only available in fragment shaders. It is
a compile-time error to use them in any other stage.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="structures">4.1.8. Structures</h4>
<div class="paragraph">
<p>User-defined types can be created by aggregating other already defined types
into a structure using the <strong>struct</strong> keyword.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> light {
<span class="predefined-type">float</span> intensity;
vec3 position;
} lightVar;</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this example, <em>light</em> becomes the name of the new type, and <em>lightVar</em>
becomes a variable of type <em>light</em>.
To declare variables of the new type, use its name (without the keyword
<strong>struct</strong>).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">light lightVar2;</code></pre>
</div>
</div>
<div class="paragraph">
<p>More formally, structures are declared as follows.
However, the definitive grammar is as given in
&#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221;.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>struct-definition</em> : </dt>
<dd>
<p><em>qualifier<sub>opt</sub></em> <strong>struct</strong> name<sub>opt</sub>_ <strong>{</strong> <em>member-list</em> <strong>}</strong>
<em>declarators<sub>opt</sub></em> <strong>;</strong></p>
</dd>
<dt class="hdlist1"><em>member-list</em> : </dt>
<dd>
<p><em>member-declaration</em> <strong>;</strong><br>
<em>member-declaration</em> <em>member-list</em> <strong>;</strong></p>
</dd>
<dt class="hdlist1"><em>member-declaration</em> : </dt>
<dd>
<p><em>basic-type</em> <em>declarators</em> <strong>;</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>where <em>name</em> becomes the user-defined type, and can be used to declare
variables to be of this new type.
The <em>name</em> shares the same name space as other variables, types, and
functions.
All previously visible variables, types, constructors, or functions with
that name are hidden.
The optional <em>qualifier</em> only applies to any <em>declarators</em>, and is not part
of the type being defined for <em>name</em>.</p>
</div>
<div class="paragraph">
<p>Structures must have at least one member declaration.
Member declarators may contain precision qualifiers, but use of any other
qualifier results in a compile-time error.
Bit fields are not supported.
Member types must be already defined (there are no forward references).
A compile-time error results if a member declaration contains an
initializer.
Member declarators can contain arrays.
Such arrays must have a size specified, and the size must be a constant
integral expression that&#8217;s greater than zero (see
&#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221;).
Each level of structure has its own name space for names given in member
declarators; such names need only be unique within that name space.</p>
</div>
<div class="paragraph">
<p>Anonymous structures are not supported.
Embedded structure definitions are not supported.
These result in compile-time errors.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> S { <span class="predefined-type">float</span> f; }; <span class="comment">// Allowed: S is defined as a structure.</span>
<span class="keyword">struct</span> T {
S; <span class="comment">// Error: anonymous structures disallowed</span>
<span class="keyword">struct</span> { ... }; <span class="comment">// Error: embedded structures disallowed</span>
S s; <span class="comment">// Allowed: nested structure with a name.</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Structures can be initialized at declaration time using constructors, as
discussed in &#8220;<a href="#structure-constructors">Structure Constructors</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Any restrictions on the usage of a type or qualifier also apply to any
structure that contains a member of that type or qualifier.
This also applies to structure members that are structures, recursively.</p>
</div>
</div>
<div class="sect3">
<h4 id="arrays">4.1.9. Arrays</h4>
<div class="paragraph">
<p>Variables of the same type can be aggregated into arrays by declaring a name
followed by brackets (<strong>[ ]</strong>) enclosing an optional size.
When an array size is specified in a declaration, it must be an integral
constant expression (see &#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221;)
greater than zero.
Except for the last declared member of a shader storage block (see section
&#8220;<a href="#interface-blocks">Interface Blocks</a>&#8221;), the size of an array must be
declared (<em>explicitly sized</em>) before it is indexed with anything other than
a constant integral expression.
The size of any array must be declared before passing it as an argument to a
function.
Violation of any of these rules result in compile-time errors.
It is legal to declare an array without a size (<em>unsized</em>) and then later
redeclare the same name as an array of the same type and specify a size, or
index it only with constant integral expressions (<em>implicitly sized</em>).
However, unless noted otherwise, blocks cannot be redeclared; an unsized
array member in a user-declared block cannot be sized by a block redeclaration.
It is a compile-time error to declare an array with a size, and then later
(in the same shader) index the same array with a constant integral
expression greater than or equal to the declared size.
It is a compile-time error to redeclare an unsized array with a size equal
to or smaller than any index used earlier in the shader to index the array.
It is also a compile-time error to index an array with a negative constant
expression.
Arrays declared as formal parameters in a function declaration must specify
a size.
Undefined behavior results from indexing an array with a non-constant
expression that&#8217;s greater than or equal to the array&#8217;s size or less than 0.
Arrays only have a single dimension (a single entry within "[ ]"), however,
arrays of arrays can be declared.
All types (basic types, structures, arrays) can be formed into an array.</p>
</div>
<div class="paragraph">
<p>All arrays are inherently homogeneous; made of elements all having the same
type and size, with one exception.
The exception is a shader storage block having an unsized array as its last
member (<em>run-time sized</em>); an array can be formed from such a shader storage
block, even if the storage blocks have differing lengths for their last
member.</p>
</div>
<div class="paragraph">
<p>Some examples are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> frequencies[<span class="integer">3</span>];
uniform vec4 lightPosition[<span class="integer">4</span>];
light lights[];
<span class="directive">const</span> <span class="predefined-type">int</span> numLights = <span class="integer">2</span>;
light lights[numLights];
<span class="comment">// a shader storage block, introduced in section 4.3.7 &quot;Buffer Variables&quot;</span>
buffer b {
<span class="predefined-type">float</span> u[]; <span class="comment">// an error, unless u gets statically sized by link time</span>
vec4 v[]; <span class="comment">// okay, v will be sized dynamically, if not statically</span>
} name[<span class="integer">3</span>]; <span class="comment">// when the block is arrayed, all u will be the same size,</span>
<span class="comment">// but not necessarily all v, if sized dynamically</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>An array type can be formed by specifying non-array type followed by an
array specifier.
All dimensions of such an array specifier must include a size.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] <span class="comment">// an array of size [5] of float</span>
<span class="predefined-type">float</span>[<span class="integer">2</span>][<span class="integer">3</span>] <span class="comment">// an array of size [2][3] of float, not size [3] of float[2]</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This type can be used anywhere any other type can be used, including as the
return value from a function</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] foo() { }</code></pre>
</div>
</div>
<div class="paragraph">
<p>as a constructor of an array:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>)</code></pre>
</div>
</div>
<div class="paragraph">
<p>as an unnamed parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> foo(<span class="predefined-type">float</span>[<span class="integer">5</span>])</code></pre>
</div>
</div>
<div class="paragraph">
<p>and as an alternate way of declaring a variable or function parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] a;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Arrays can have initializers formed from array constructors:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[<span class="integer">5</span>](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>);
<span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); <span class="comment">// same thing</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>An array of arrays can be declared as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>]; <span class="comment">// size-3 array of size-2 array of vec4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>which declares a one-dimensional array of size 3 of one-dimensional arrays
of size 2 of <strong>vec4</strong>.
The following declarations do the same thing:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4[<span class="integer">2</span>] a[<span class="integer">3</span>]; <span class="comment">// size-3 array of size-2 array of vec4</span>
vec4[<span class="integer">3</span>][<span class="integer">2</span>] a; <span class="comment">// size-3 array of size-2 array of vec4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When in transparent memory (like in a uniform block), the layout is that the
inner-most (right-most in declaration) dimensions iterate faster than the
outer dimensions.
That is, for the above, the order in memory would be:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>Low address : a[0][0] : a[0][1] : a[1][0] : a[1][1] : a[2][0] : a[2][1]
: High address</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The type of <em>a</em> needed for both constructors and nameless parameters is
&#8220;vec4[3][2]&#8221;:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 b[<span class="integer">2</span>] = vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">0</span><span class="float">.1</span>));
vec4[<span class="integer">3</span>][<span class="integer">2</span>] a = vec4[<span class="integer">3</span>][<span class="integer">2</span>](b, b, b); <span class="comment">// constructor</span>
<span class="directive">void</span> foo(vec4[<span class="integer">3</span>][<span class="integer">2</span>]); <span class="comment">// prototype with unnamed parameter</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively, the initializer-list syntax can be used to initialize an
array of arrays:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>] = { vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)),
vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)),
vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)) };</code></pre>
</div>
</div>
<div class="paragraph">
<p>Unsized arrays can be explicitly sized by an initializer at declaration
time:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>];
...
<span class="predefined-type">float</span> b[] = a; <span class="comment">// b is explicitly size 5</span>
<span class="predefined-type">float</span> b[<span class="integer">5</span>] = a; <span class="comment">// means the same thing</span>
<span class="predefined-type">float</span> b[] = <span class="predefined-type">float</span>[](<span class="integer">1</span>,<span class="integer">2</span>,<span class="integer">3</span>,<span class="integer">4</span>,<span class="integer">5</span>); <span class="comment">// also explicitly sizes to 5</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>However, it is a compile-time error to assign to an unsized array.
Note, this is a rare case that initializers and assignments appear to have
different semantics.
For arrays of arrays, any unsized dimension is explicitly sized by the
initializer:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 a[][] = { vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)), <span class="comment">// okay, size to a[3][2]</span>
vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)),
vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)) };</code></pre>
</div>
</div>
<div class="paragraph">
<p>Arrays know the number of elements they contain.
This can be obtained by using the <strong>length</strong>() method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>];
a.length(); <span class="comment">// returns 5</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This returns a type <strong>int</strong>.
If an array has been explicitly sized, the value returned by the <strong>length</strong>()
method is a constant expression.
If an array has not been explicitly sized and is the last declared member of
a shader storage block, the value returned will not be a constant expression
and will be determined at runtime based on the size of the buffer object
providing storage for the block.
Such arrays are runtime sized.
For runtime-sized arrays, the value returned by the <strong>length</strong>() method will be
undefined if the array is contained in an array of shader storage blocks
that is indexed with a non-constant expression less than zero or greater
than or equal to the number of blocks in the array.</p>
</div>
<div class="paragraph">
<p>The <strong>length</strong>() method cannot be called on an array that is not runtime sized
and also has not yet been explicitly sized;
this results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>When the <strong>length</strong>() method returns a compile-time constant, the expression the
<strong>length</strong>() method is applied to cannot contain any side effects, such as writes
to l-values within the expression, or function calls that themselves have side
effects: only the compile-time constant length itself need be computed.
Behavior and results, including any compile-time error reporting,
are undefined if the expression contains other effects.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a, b;
<span class="directive">const</span> <span class="predefined-type">int</span> s = <span class="predefined-type">float</span>[<span class="integer">2</span>](a=<span class="float">3</span><span class="float">.0</span>, ++b).length(); <span class="comment">// illegal side effects</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>length</strong>() method works equally well for arrays of arrays:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>];
a.length() <span class="comment">// this is 3</span>
a[x].length() <span class="comment">// this is 2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When the <strong>length</strong>() method returns a compile-time constant, the expression
in brackets (<em>x</em> above) will be parsed and subjected to the rules required for
array indices, but the array will not be dereferenced.
Thus, behavior is well defined even if the run-time value of the expression
is out of bounds, as long as the expression contains no side effects.</p>
</div>
<div class="paragraph">
<p>When the <strong>length</strong>() method returns a run-time value
(not a compile-time constant), the array will be
dereferenced.
E.g., if <em>x</em> is not a compile-time constant and is out of range, an undefined
value results.
More generally, all involved expressions are fully evaluated and executed.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// for a compile time-sized array b containing a member array a:</span>
b[x+<span class="integer">3</span>].a.length(); <span class="comment">// b is never dereferenced, x+3 is evaluated and checked</span>
b[++x].a.length(); <span class="comment">// not allowed; results are undefined</span>
<span class="comment">// for an array s of a shader storage object (run-time sized) containing a member array a:</span>
s[++x].a.length(); <span class="comment">// s is dereferenced; ++x needs to be a valid index</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For implicitly-sized or run-time-sized arrays, only the outer-most dimension
can be lacking a size.
A type that includes an unknown array size cannot be formed into an array
until it gets an explicit size, except for shader storage blocks where the
only unsized array member is the last member of the block.</p>
</div>
<div class="paragraph">
<p>In a shader storage block, the last member may be declared without an
explicit size.
In this case, the effective array size is inferred at run-time from the size
of the data store backing the interface block.
Such run-time-sized arrays may be indexed with general integer expressions.
However, it is a compile-time error to pass them as an argument to a
function or index them with a negative constant expression.</p>
</div>
</div>
<div class="sect3">
<h4 id="implicit-conversions">4.1.10. Implicit Conversions</h4>
<div class="paragraph">
<p>In some situations, an expression and its type will be implicitly converted
to a different type.
The following table shows all allowed implicit conversions:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Type of expression</th>
<th class="tableblock halign-left valign-top">Can be implicitly converted to</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uint</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong><br>
<strong>uint</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>float</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong><br>
<strong>uint</strong><br>
<strong>float</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>double</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong><br>
<strong>uvec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong><br>
<strong>uvec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong><br>
<strong>uvec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong><br>
<strong>uvec2</strong><br>
<strong>vec2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong><br>
<strong>uvec3</strong><br>
<strong>vec3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong><br>
<strong>uvec4</strong><br>
<strong>vec4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x3</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x4</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x4</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x2</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x2</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x3</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x3</strong></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>There are no implicit array or structure conversions.
For example, an array of <strong>int</strong> cannot be implicitly converted to an array of
<strong>float</strong>.</p>
</div>
<div class="paragraph">
<p>When an implicit conversion is done, it is the same conversion that would be
done under explicit conversion, using a constructor.
The explicit conversions via constructors are described in
<a href="#conversion-and-scalar-constructors">Conversion and Scalar Constructors</a>.</p>
</div>
<div class="paragraph">
<p>When performing implicit conversion for binary operators, there may be
multiple data types to which the two operands can be converted.
For example, when adding an <strong>int</strong> value to a <strong>uint</strong> value, both values can
be implicitly converted to <strong>uint</strong>, <strong>float</strong>, and <strong>double</strong>.
In such cases, a floating-point type is chosen if either operand has a
floating-point type.
Otherwise, an unsigned integer type is chosen if either operand has an
unsigned integer type.
Otherwise, a signed integer type is chosen.
If operands can be implicitly converted to multiple data types deriving from
the same base data type, the type with the smallest component size is used.</p>
</div>
<div class="paragraph">
<p>The conversions in the table above are done only as indicated by other
sections of this specification.</p>
</div>
</div>
<div class="sect3">
<h4 id="initializers">4.1.11. Initializers</h4>
<div class="paragraph">
<p>At declaration, an initial value for a variable may be provided, specified
as an equals (=) followed by an initializer.
The initializer is either an <em>assignment-expression</em> or a list of
initializers enclosed in curly braces.
The grammar for the initializer is:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>initializer</em> : </dt>
<dd>
<p><em>assignment-expression</em><br>
<strong>{</strong> <em>initializer-list</em> <strong>}</strong><br>
<strong>{</strong> <em>initializer-list</em> <strong>,</strong> <strong>}</strong></p>
</dd>
<dt class="hdlist1"><em>initializer-list</em> : </dt>
<dd>
<p><em>initializer</em><br>
<em>initializer-list</em> , <em>initializer</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The <em>assignment-expression</em> is a normal expression except that a comma (<strong>,</strong>)
outside parentheses is interpreted as the end of the initializer, not as the
sequence operator.
As explained in more detail below, this allows creation of nested
initializers: The variable type and its initializer must exactly match in
terms of nesting, number of components/elements/members present at each
level, and types of components/elements/members.
An <em>assignment-expression</em> at global scope can include calls to user-defined
functions.</p>
</div>
<div class="paragraph">
<p>An <em>assignment-expression</em> in an initializer must be either the same type as
the object it initializes or be a type that can be converted to the object&#8217;s
type according to &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221;.
Since these include constructors, a composite variable can be initialized by
either a constructor or an initializer list; and an element in an
initializer list can be a constructor.</p>
</div>
<div class="paragraph">
<p>If an initializer is a list of initializers enclosed in curly braces, the
variable being declared must be a vector, a matrix, an array, or a
structure.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i = { <span class="integer">1</span> }; <span class="comment">// illegal, i is not a composite</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>A list of initializers enclosed in a matching set of curly braces is applied
to one composite.
This may be the variable being declared or a composite contained in the
variable being declared.
Individual initializers from the initializer list are applied to the
elements/members of the composite, in order.</p>
</div>
<div class="paragraph">
<p>If the composite has a vector type, initializers from the list are applied
to the components of the vector, in order, starting with component 0.
The number of initializers must match the number of components.</p>
</div>
<div class="paragraph">
<p>If the composite has a matrix type, initializers from the list must be
vector initializers and are applied to the columns of the matrix, in order,
starting with column 0.
The number of initializers must match the number of columns.</p>
</div>
<div class="paragraph">
<p>If the composite has a structure type, initializers from the list are
applied to the members of the structure, in the order declared in the
structure, starting with the first member.
The number of initializers must match the number of members.</p>
</div>
<div class="paragraph">
<p>Applying these rules, the following matrix declarations are equivalent:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat2x2 a = mat2( vec2( <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> ), vec2( <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> ) );
mat2x2 b = { vec2( <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> ), vec2( <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> ) };
mat2x2 c = { { <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> }, { <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> } };</code></pre>
</div>
</div>
<div class="paragraph">
<p>All of the following declarations result in a compile-time error.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">2</span>] = { <span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span> }; <span class="comment">// illegal</span>
vec2 b = { <span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span> }; <span class="comment">// illegal</span>
mat3x3 c = { vec3(<span class="float">0</span><span class="float">.0</span>), vec3(<span class="float">1</span><span class="float">.0</span>), vec3(<span class="float">2</span><span class="float">.0</span>), vec3(<span class="float">3</span><span class="float">.0</span>) }; <span class="comment">// illegal</span>
mat2x2 d = { <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> }; <span class="comment">// illegal, can't flatten nesting</span>
<span class="keyword">struct</span> {
<span class="predefined-type">float</span> a;
<span class="predefined-type">int</span> b;
} e = { <span class="float">1</span><span class="float">.2</span>, <span class="integer">2</span>, <span class="integer">3</span> }; <span class="comment">// illegal</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In all cases, the inner-most initializer (i.e., not a list of initializers
enclosed in curly braces) applied to an object must have the same type as
the object being initialized or be a type that can be converted to the
object&#8217;s type according to &#8220;<a href="#implicit-conversions">Implicit
Conversions</a>&#8221;.
In the latter case, an implicit conversion will be done on the initializer
before the assignment is done.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> {
<span class="predefined-type">float</span> a;
<span class="predefined-type">int</span> b;
} e = { <span class="float">1</span><span class="float">.2</span>, <span class="integer">2</span> }; <span class="comment">// legal, all types match</span>
<span class="keyword">struct</span> {
<span class="predefined-type">float</span> a;
<span class="predefined-type">int</span> b;
} e = { <span class="integer">1</span>, <span class="integer">3</span> }; <span class="comment">// legal, first initializer is converted</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All of the following declarations result in a compile-time error.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> a = <span class="predefined-constant">true</span>; <span class="comment">// illegal</span>
vec4 b[<span class="integer">2</span>] = { vec4(<span class="float">0</span><span class="float">.0</span>), <span class="float">1</span><span class="float">.0</span> }; <span class="comment">// illegal</span>
mat4x2 c = { vec3(<span class="float">0</span><span class="float">.0</span>), vec3(<span class="float">1</span><span class="float">.0</span>) }; <span class="comment">// illegal</span>
<span class="keyword">struct</span> S1 {
vec4 a;
vec4 b;
};
<span class="keyword">struct</span> {
<span class="predefined-type">float</span> s;
<span class="predefined-type">float</span> t;
} d[] = { S1(vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.1</span>)) }; <span class="comment">// illegal</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If an initializer (of either form) is provided for an unsized array, the
size of the array is determined by the number of top-level (non-nested)
initializers within the initializer.
All of the following declarations create arrays explicitly sized with five
elements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[] = <span class="predefined-type">float</span>[](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>);
<span class="predefined-type">float</span> b[] = { <span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span> };
<span class="predefined-type">float</span> c[] = a; <span class="comment">// c is explicitly size 5</span>
<span class="predefined-type">float</span> d[<span class="integer">5</span>] = b; <span class="comment">// means the same thing</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>It is a compile-time error to have too few or too many initializers in an
initializer list for the composite being initialized.
That is, all elements of an array, all members of a structure, all columns
of a matrix, and all components of a vector must have exactly one
initializer expression present, with no unconsumed initializers.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="scoping">4.2. Scoping</h3>
<div class="paragraph">
<p>The scope of a variable is determined by where it is declared.
If it is declared outside all function definitions, it has global scope,
which starts from where it is declared and persists to the end of the shader
it is declared in.
If it is declared in a <strong>while</strong> test or a <strong>for</strong> statement, then it is scoped
to the end of the following sub-statement.
If it is declared in an <strong>if</strong> or <strong>else</strong> statement, it is scoped to the end of
that statement.
(See &#8220;<a href="#selection">Selection</a>&#8221; and &#8220;<a href="#iteration">Iteration</a>&#8221; for the
location of statements and sub-statements.) Otherwise, if it is declared as
a statement within a compound statement, it is scoped to the end of that
compound statement.
If it is declared as a parameter in a function definition, it is scoped
until the end of that function definition.
A function&#8217;s parameter declarations and body together form a single scope
nested in the global scope.
The <strong>if</strong> statement&#8217;s expression does not allow new variables to be declared,
hence does not form a new scope.</p>
</div>
<div class="paragraph">
<p>Within a declaration, the scope of a name starts immediately after the
initializer if present or immediately after the name being declared if not.
Several examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> x = <span class="integer">1</span>;
{
<span class="predefined-type">int</span> x = <span class="integer">2</span>, y = x; <span class="comment">// y is initialized to 2</span>
}
<span class="keyword">struct</span> S
{
<span class="predefined-type">int</span> x;
};
{
S S = S(<span class="integer">0</span>); <span class="comment">// 'S' is only visible as a struct and constructor</span>
S; <span class="comment">// 'S' is now visible as a variable</span>
}
<span class="predefined-type">int</span> x = x; <span class="comment">// Error if x has not been previously defined.</span>
<span class="comment">// If the previous definition of x was in this</span>
<span class="comment">// same scope, this causes a redeclaration error.</span>
<span class="predefined-type">int</span> f( <span class="comment">/* nested scope begins here */</span> <span class="predefined-type">int</span> k)
{
<span class="predefined-type">int</span> k = k + <span class="integer">3</span>; <span class="comment">// redeclaration error of the name k</span>
...
}
<span class="predefined-type">int</span> f(<span class="predefined-type">int</span> k)
{
{
<span class="predefined-type">int</span> k = k + <span class="integer">3</span>; <span class="comment">// 2nd k is parameter, initializing nested first k</span>
<span class="predefined-type">int</span> m = k; <span class="comment">// use of new k, which is hiding the parameter</span>
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>For both <strong>for</strong> and <strong>while</strong> loops, the sub-statement itself does not
introduce a new scope for variable names, so the following has a
redeclaration compile-time error:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">for</span> ( <span class="comment">/* nested scope begins here */</span> <span class="predefined-type">int</span> i = <span class="integer">0</span>; i &lt; <span class="integer">10</span>; i++) {
<span class="predefined-type">int</span> i; <span class="comment">// redeclaration error</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The body of a <strong>do</strong>-<strong>while</strong> loop introduces a new scope lasting only between
the <strong>do</strong> and <strong>while</strong> (not including the while test expression), whether or
not the body is simple or compound:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i = <span class="integer">17</span>;
<span class="keyword">do</span>
<span class="predefined-type">int</span> i = <span class="integer">4</span>; <span class="comment">// okay, in nested scope_</span>
<span class="keyword">while</span> (i == <span class="integer">0</span>); <span class="comment">// i is 17, scoped outside the do-while body</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The statement following a <strong>switch</strong> (&#8230;&#8203;) forms a nested scope.</p>
</div>
<div class="paragraph">
<p>All variable names, structure type names, and function names in a given
scope share the same name space.
Function names can be redeclared in the same scope, with the same or
different parameters, without error.
An implicitly-sized array can be redeclared in the same scope as an array of
the same base type.
Otherwise, within one compilation unit, a declared name cannot be redeclared
in the same scope; doing so results in a redeclaration compile-time error.
If a nested scope redeclares a name used in an outer scope, it hides all
existing uses of that name.
There is no way to access the hidden name or make it unhidden, without
exiting the scope that hid it.</p>
</div>
<div class="paragraph">
<p>The built-in functions are scoped in a scope outside the global scope that
users declare global variables in.
That is, a shader&#8217;s global scope, available for user-defined functions and
global variables, is nested inside the scope containing the built-in
functions.
When a function name is redeclared in a nested scope, it hides all functions
declared with that name in the outer scope.
Function declarations (prototypes) cannot occur inside of functions; they
must be at global scope, or for the built-in functions, outside the global
scope, otherwise a compile-time error results.</p>
</div>
<div class="paragraph">
<p>Shared globals are global variables declared with the same name in
independently compiled units (shaders) within the same language (i.e., same
stage, e.g. vertex) that are linked together when making a single program.
(Globals forming the interface between two different shader languages are
discussed in other sections.) Shared globals share the same name space, and
must be declared with the same type.
They will share the same storage.</p>
</div>
<div class="paragraph">
<p>Shared global arrays must have the same base type and the same explicit
size.
An array implicitly sized in one shader can be explicitly sized by another
shader in the same stage.
If no shader in a stage has an explicit size for the array, the largest
implicit size (one more than the largest index used) in that stage is used.
There is no cross-stage array sizing.
If there is no static access to an implicitly sized array within the stage
declaring it, then the array is given a size of 1, which is relevant when
the array is declared within an interface block that is shared with other
stages or the application (other unused arrays might be eliminated by the
optimizer).</p>
</div>
<div class="paragraph">
<p>Shared global scalars must have exactly the same type name and type
definition.
Structures must have the same name, sequence of type names, and type
definitions, and member names to be considered the same type.
This rule applies recursively for nested or embedded types.
If a shared global has multiple initializers, the initializers must all be
constant expressions, and they must all have the same value.
Otherwise, a link-time error will result.
(A shared global having only one initializer does not require that
initializer to be a constant expression.)</p>
</div>
</div>
<div class="sect2">
<h3 id="storage-qualifiers">4.3. Storage Qualifiers</h3>
<div class="paragraph">
<p>Variable declarations may have at most one storage qualifier specified in
front of the type.
These are summarized as</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Storage Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;none: default&gt;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">local read/write memory, or an input parameter to a
function</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>const</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">a variable whose value cannot be changed</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">linkage into a shader from a previous stage, variable
is copied in</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>out</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">linkage out of a shader to a subsequent stage,
variable is copied out</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>attribute</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">compatibility profile only and vertex language only;
same as <strong>in</strong> when in a vertex shader</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uniform</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">value does not change across the primitive being
processed, uniforms form the linkage between a shader,
API, and the application</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>varying</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">compatibility profile only and vertex and fragment
languages only; same as <strong>out</strong> when in a vertex shader
and same as <strong>in</strong> when in a fragment shader</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>buffer</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">value is stored in a buffer object, and can be read or
written both by shader invocations and the API</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>shared</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">compute shader only; variable storage is shared across
all work items in a workgroup</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Some input and output qualified variables can be qualified with at most one
additional auxiliary storage qualifier:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Auxiliary Storage Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>centroid</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">centroid-based interpolation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sample</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">per-sample interpolation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>patch</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">per-tessellation-patch attributes</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Not all combinations of qualification are allowed.
Auxiliary storage qualifiers can only be used with the <strong>in</strong> or <strong>out</strong> storage
qualifiers.
Additional qualifier rules are defined in upcoming sections.</p>
</div>
<div class="paragraph">
<p>Local variables can only use the <strong>const</strong> storage qualifier (or use no
storage qualifier).</p>
</div>
<div class="paragraph">
<p>Note that function parameters can use <strong>const</strong>, <strong>in</strong>, and <strong>out</strong> qualifiers,
but as <em>parameter qualifiers</em>.
Parameter qualifiers are discussed in
&#8220;<a href="#function-calling-conventions">Function Calling Conventions</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Function return types and structure members do not use storage qualifiers.</p>
</div>
<div class="paragraph">
<p>Initializers in global declarations may only be used in declarations of
global variables with no storage qualifier, with a <strong>const</strong> qualifier, or
with a <strong>uniform</strong> qualifier.</p>
</div>
<div class="paragraph">
<p>Global variables without storage qualifiers that are not initialized in
their declaration or by the application will not be initialized,
but rather will enter <em>main()</em> with undefined values.</p>
</div>
<div class="paragraph">
<p>When comparing an output from one shader stage to an input of a subsequent
shader stage, the input and output don&#8217;t match if their auxiliary qualifiers
(or lack thereof) are not the same.</p>
</div>
<div class="sect3">
<h4 id="default-storage-qualifier">4.3.1. Default Storage Qualifier</h4>
<div class="paragraph">
<p>If no qualifier is present on a global variable, then the variable has no
linkage to the application or shaders running on other pipeline stages.
For either global or local unqualified variables, the declaration will
appear to allocate memory associated with the processor it targets.
This variable will provide read/write access to this allocated memory.</p>
</div>
</div>
<div class="sect3">
<h4 id="constant-qualifier">4.3.2. Constant Qualifier</h4>
<div class="paragraph">
<p>Named compile-time constants
or read-only variables
can be declared using
the <strong>const</strong> qualifier.
The <strong>const</strong> qualifier can be used with any of the non-void transparent basic
data types, as well as with structures and arrays of these.
It is a compile-time error to write to a <strong>const</strong> variable outside of its
declaration, so they must be initialized when declared.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> vec3 zAxis = vec3 (<span class="float">0</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>);
<span class="directive">const</span> <span class="predefined-type">float</span> ceiling = a + b; <span class="comment">// a and b not necessarily constants</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Structure members may not be qualified with <strong>const</strong>.
Structure variables can be declared as <strong>const</strong>, and initialized with a
structure
constructor or initializer.</p>
</div>
<div class="paragraph">
<p>Initializers for <strong>const</strong> declarations
at global scope
must be constant expressions, as defined in
&#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221;.</p>
</div>
</div>
<div class="sect3">
<h4 id="constant-expressions">4.3.3. Constant Expressions</h4>
<div class="paragraph">
<p>SPIR-V specialization constants are expressed in GLSL as <strong>const</strong> with the
layout qualifier <strong>constant_id</strong>, as described in
&#8220;<a href="#specialization-constant-qualifier">Specialization-Constant
Qualifier.</a>&#8221;</p>
</div>
<div class="paragraph">
<p>A <em>constant expression</em> is one of</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A literal value (e.g. <strong>5</strong> or <strong>true</strong>).</p>
</li>
<li>
<p>A variable declared with the <strong>const</strong> qualifier and an initializer, where
the initializer is a constant expression.
This includes both <strong>const</strong> declared with a specialization-constant
layout qualifier, e.g. <strong>layout</strong>(<strong>constant_id</strong> = &#8230;&#8203;), and those declared
without a specialization-constant layout qualifier.</p>
</li>
<li>
<p>Built-in variables qualified as <strong>const</strong>.</p>
</li>
<li>
<p>An expression formed by an operator on operands that are all constant
expressions, including getting an element of a constant array, or a
member of a constant structure, or components of a constant vector.
However, the lowest precedence operators of the sequence operator (<strong>,</strong>)
and the assignment operators (<strong>=</strong>, <strong>+=</strong>, <strong>&#8230;&#8203;</strong>) are not included in the
operators that can create a constant expression.
Also, an array access with a specialization constant as an index does
not result in a constant expression.</p>
</li>
<li>
<p>Valid use of the <strong>length</strong>() method on an explicitly sized object,
whether or not the object itself is constant (implicitly sized or
run-time sized arrays do not return a constant expression).</p>
</li>
<li>
<p>A constructor whose arguments are all constant expressions.</p>
</li>
<li>
<p>For non-specialization constants only: The value returned by certain
built-in function calls whose arguments are all constant expressions,
including at least the list below.
Any other built-in function that does not access memory (not the texture
lookup functions, image access, atomic counter, etc.), that has a
non-<strong>void</strong> return type, that has no <strong>out</strong> parameter, and is not a noise
function might also be considered a constant.
When a function is called with an argument that is a specialization
constant, the result is not a constant expression.</p>
<div class="ulist">
<ul>
<li>
<p>Angle and Trigonometric Functions</p>
<div class="ulist">
<ul>
<li>
<p><strong>radians</strong></p>
</li>
<li>
<p><strong>degrees</strong></p>
</li>
<li>
<p><strong>sin</strong></p>
</li>
<li>
<p><strong>cos</strong></p>
</li>
<li>
<p><strong>asin</strong></p>
</li>
<li>
<p><strong>acos</strong></p>
</li>
</ul>
</div>
</li>
<li>
<p>Exponential Functions</p>
<div class="ulist">
<ul>
<li>
<p><strong>pow</strong></p>
</li>
<li>
<p><strong>exp</strong></p>
</li>
<li>
<p><strong>log</strong></p>
</li>
<li>
<p><strong>exp2</strong></p>
</li>
<li>
<p><strong>log2</strong></p>
</li>
<li>
<p><strong>sqrt</strong></p>
</li>
<li>
<p><strong>inversesqrt</strong></p>
</li>
</ul>
</div>
</li>
<li>
<p>Common Functions</p>
<div class="ulist">
<ul>
<li>
<p><strong>abs</strong></p>
</li>
<li>
<p><strong>sign</strong></p>
</li>
<li>
<p><strong>floor</strong></p>
</li>
<li>
<p><strong>trunc</strong></p>
</li>
<li>
<p><strong>round</strong></p>
</li>
<li>
<p><strong>ceil</strong></p>
</li>
<li>
<p><strong>mod</strong></p>
</li>
<li>
<p><strong>min</strong></p>
</li>
<li>
<p><strong>max</strong></p>
</li>
<li>
<p><strong>clamp</strong></p>
</li>
</ul>
</div>
</li>
<li>
<p>Geometric Functions</p>
<div class="ulist">
<ul>
<li>
<p><strong>length</strong></p>
</li>
<li>
<p><strong>dot</strong></p>
</li>
<li>
<p><strong>normalize</strong></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Function calls to user-defined functions (non-built-in functions) cannot
be used to form constant expressions.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>A <em>constant integral expression</em> is a constant expression that evaluates to
a scalar signed or unsigned integer.</p>
</div>
<div class="paragraph">
<p>Constant expressions will be evaluated in an invariant way so as to create
the same value in multiple shaders when the same constant expressions appear
in those shaders.
See &#8220;<a href="#the-invariant-qualifier">The Invariant Qualifier</a>&#8221; for more details
on how to create invariant expressions and
&#8220;<a href="#precision-qualifiers">Precision Qualifiers</a>&#8221; for detail on how
expressions are evaluated.</p>
</div>
<div class="paragraph">
<p>Constant expressions respect the <strong>precise</strong> and <strong>invariant</strong> qualifiers but
will be always be evaluated in an invariant way, independent of the use of
such qualification, so as to create the same value in multiple shaders when
the same constant expressions appear in those shaders.
See &#8220;<a href="#the-invariant-qualifier">The Invariant Qualifier</a>&#8221; and
&#8220;<a href="#the-precise-qualifier">The Precise Qualifier</a>&#8221; for more details on how
to create invariant expressions.</p>
</div>
<div class="paragraph">
<p>Constant-expressions may be evaluated by a
host platform, and are therefore not required to compute the same value that
the same expression would evaluate to on the shader execution target.
However, the host must use the same or greater precision than the target
would use.
When the precision qualification cannot be determined, the expression is
evaluated at <strong>highp</strong>.
See &#8220;<a href="#default-precision-qualifiers">Default Precision Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Specialization-constant expressions are never evaluated by the compiler
front end, but instead retain the expression&#8217;s operations needed to evaluate
them later on the host.</p>
</div>
</div>
<div class="sect3">
<h4 id="input-variables">4.3.4. Input Variables</h4>
<div class="paragraph">
<p>Shader input variables are declared with the <strong>in</strong> storage qualifier.
They form the input interface between previous stages of the API
pipeline and the declaring shader.
Input variables must be declared at global scope.
Values from the previous pipeline stage are copied into input variables at
the beginning of shader execution.
It is a compile-time error to write to a variable declared as an input.</p>
</div>
<div class="paragraph">
<p>Only the input variables that are
statically
read need to be written by the
previous stage; it is allowed to have superfluous declarations of input
variables.
This is shown in the following table.</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<colgroup>
<col>
<col>
<col>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top" colspan="2" rowspan="2"><p class="tableblock">Treatment of Mismatched Input Variables</p></td>
<td class="tableblock halign-left valign-top" colspan="3"><p class="tableblock">Consuming Shader (input variables)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">No Declaration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Declared but no Static Use</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Declared and Static Use</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top" rowspan="3"><p class="tableblock">Generating Shader (output variables)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No Declaration</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Link-Time Error</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Declared but no Static Use</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed (values are undefined)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Declared and Static Use</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allowed (values are potentially undefined)</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Consumption errors are based on static use only.
Compilation may generate a warning, but not an error, for any dynamic use
the compiler can deduce that might cause consumption of undefined values.</p>
</div>
<div class="paragraph">
<p>See &#8220;<a href="#built-in-variables">Built-In Variables</a>&#8221; for a list of the built-in
input names.</p>
</div>
<div class="paragraph">
<p>Vertex shader input variables (or attributes) receive per-vertex data.
It is a compile-time error to use auxiliary storage or interpolation qualifiers
on a vertex shader input.
The values copied in are established by the API or through the use
of the layout identifier <strong>location</strong>.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to declare a vertex shader input with, or that
contains, any of the following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <a href="#booleans">boolean type</a></p>
</li>
<li>
<p>An <a href="#opaque-types">opaque type</a></p>
</li>
<li>
<p>A structure</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Example declarations in a vertex shader:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 position;
in vec3 normal;
in vec2 texCoord[<span class="integer">4</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>It is expected that graphics hardware will have a small number of fixed
vector locations for passing vertex inputs.
Therefore, the OpenGL Shading Language defines each non-matrix input variable as taking up
one such vector location.
There is an implementation-dependent limit on the number of locations that
can be used, and if this is exceeded it will cause a link-time error.
(Declared input variables that are not statically used do not count against
this limit.) A scalar input counts the same amount against this limit as a
<strong>vec4</strong>, so applications may want to consider packing groups of four
unrelated float inputs together into a vector to better utilize the
capabilities of the underlying hardware.
A matrix input will use up multiple locations.
The number of locations used will equal the number of columns in the matrix.</p>
</div>
<div class="paragraph">
<p>Tessellation control, evaluation, and geometry shader input variables get
the per-vertex values written out by output variables of the same names in
the previous active shader stage.
For these inputs, <strong>centroid</strong> and interpolation qualifiers are allowed, but
have no effect.
Since tessellation control, tessellation evaluation, and geometry shaders
operate on a set of vertices, each input variable (or input block, see
interface blocks below) needs to be declared as an array.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in <span class="predefined-type">float</span> foo[]; <span class="comment">// geometry shader input for vertex &quot;out float foo&quot;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Each element of such an array corresponds to one vertex of the primitive
being processed.
Each array can optionally have a size declared.
For geometry shaders, the array size will be set by, (or if provided must be
consistent with) the input <strong>layout</strong> declaration(s) establishing the type of
input primitive, as described later in &#8220;<a href="#input-layout-qualifiers">Input
Layout Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Some inputs and outputs are <em>arrayed</em>, meaning that for an interface between
two shader stages either the input or output declaration requires an extra
level of array indexing for the declarations to match.
For example, with the interface between a vertex shader and a geometry
shader, vertex shader output variables and geometry shader input variables
of the same name must have matching types, except that the geometry shader
will have one more array dimension than the vertex shader, to allow for
vertex indexing.
If such an arrayed interface variable is not declared with the necessary
additional input or output array dimension, a link-time error will result.
Geometry shader inputs, tessellation control shader inputs and outputs, and
tessellation evaluation inputs all have an additional level of arrayness
relative to other shader inputs and outputs.
These inputs and outputs are known as <em>per-vertex-arrayed</em> inputs and
outputs.
Component limits for arrayed interfaces (e.g.
<em>gl_MaxTessControlInputComponents</em>) are limits per vertex, not limits for
the entire interface.</p>
</div>
<div class="paragraph">
<p>For non-arrayed interfaces (meaning array dimensionally stays the same
between stages), it is a link-time error if the input variable is not
declared with the same type, including array dimensionality, as the matching
output variable.</p>
</div>
<div class="paragraph">
<p>The link-time type-matching rules apply to all declared input and output
variables, whether or not they are used.</p>
</div>
<div class="paragraph">
<p>Additionally, tessellation evaluation shaders support per-patch input
variables declared with the <strong>patch</strong> and <strong>in</strong> qualifiers.
Per-patch input variables are filled with the values of per-patch output
variables written by the tessellation control shader.
Per-patch inputs may be declared as one-dimensional arrays, but are not
indexed by vertex number.
Applying the <strong>patch</strong> qualifier to inputs can only be done in tessellation
evaluation shaders.
As with other input variables, per-patch inputs must be declared using the
same type and qualification as per-patch outputs from the previous
(tessellation control) shader stage.
It is a compile-time error to use <strong>patch</strong> with inputs in any other stage.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to declare a tessellation control, tessellation
evaluation or geometry shader input with, or that contains, any of the
following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <a href="#booleans">boolean type</a></p>
</li>
<li>
<p>An <a href="#opaque-types">opaque type</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment shader inputs get per-fragment values, typically interpolated from
a previous stage&#8217;s outputs.
The auxiliary storage qualifiers <strong>centroid</strong> and <strong>sample</strong> can also be
applied, as well as the interpolation qualifiers <strong>flat</strong>, <strong>noperspective</strong>,
and <strong>smooth.</strong></p>
</div>
<div class="paragraph">
<p>It is a compile-time error to declare a fragment shader input with, or that
contains, any of the following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <a href="#booleans">boolean type</a></p>
</li>
<li>
<p>An <a href="#opaque-types">opaque type</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment shader inputs that are, or contain, integral
or double-precision floating-point
types must be
qualified with the interpolation qualifier <strong>flat</strong>.</p>
</div>
<div class="paragraph">
<p>Fragment inputs are declared as in the following examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec3 normal;
centroid in vec2 TexCoord;
invariant centroid in vec4 Color;
noperspective in <span class="predefined-type">float</span> temperature;
flat in vec3 myColor;
noperspective centroid in vec2 myTexCoord;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The fragment shader inputs form an interface with the last active shader in
the vertex processing pipeline.
For this interface, the last active shader stage output variables and
fragment shader input variables of the same name must match in type and
qualification, with a few exceptions: The storage qualifiers must, of
course, differ (one is <strong>in</strong> and one is <strong>out</strong>).
Also,
interpolation qualification (e.g. <strong>flat</strong>) and
auxiliary qualification (e.g. <strong>centroid</strong>) may differ.
These mismatches are allowed between any pair of stages.
When
interpolation or
auxiliary qualifiers do not match, those provided in
the fragment shader supersede those provided in previous stages.
If any such qualifiers are completely missing in the fragment shaders, then
the default is used, rather than any qualifiers that may have been declared
in previous stages.
That is, what matters is what is declared in the fragment shaders, not what
is declared in shaders in previous stages.</p>
</div>
<div class="paragraph">
<p>When an interface between shader stages is formed using shaders from two
separate program objects, it is not possible to detect mismatches between
inputs and outputs when the programs are linked.
When there are mismatches between inputs and outputs on such interfaces,
the values passed across the interface will be partially or completely
undefined.</p>
</div>
<div class="paragraph">
<p>Shaders can ensure matches across such interfaces either by using input and
output layout qualifiers (sections &#8220;<a href="#input-layout-qualifiers">Input Layout
Qualifiers</a>&#8221; and &#8220;<a href="#output-layout-qualifiers">Output Layout
Qualifiers</a>&#8221;) or by using identical input and output declarations of
blocks or variables.
Complete rules for interface matching are found in section 7.4.1 &#8220;Shader
Interface Matching&#8221; of the <a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>Compute shaders do not permit user-defined input variables and do not form a
formal interface with any other shader stage.
See &#8220;<a href="#compute-shader-special-variables">Compute Shader Special
Variables</a>&#8221; for a description of built-in compute shader input variables.
All other input to a compute shader is retrieved explicitly through image
loads, texture fetches, loads from uniforms or uniform buffers, or other
user supplied code.
Redeclaration of built-in input variables in compute shaders is not
permitted.</p>
</div>
</div>
<div class="sect3">
<h4 id="uniform-variables">4.3.5. Uniform Variables</h4>
<div class="paragraph">
<p>The <strong>uniform</strong> qualifier is used to declare global variables whose values are
the same across the entire primitive being processed.
All <strong>uniform</strong> variables are read-only and are initialized externally either
at link time or through the API.
The link-time initial value is either the value of the variable&#8217;s
initializer, if present, or 0 if no initializer is present.
Opaque types cannot have initializers, or a compile-time error results.
When targeting Vulkan, it is a compile-time error to declare <strong>uniform</strong>
variables outside a block.</p>
</div>
<div class="paragraph">
<p>Example declarations are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">uniform vec4 lightPosition;
uniform vec3 color = vec3(<span class="float">0</span><span class="float">.7</span>, <span class="float">0</span><span class="float">.7</span>, <span class="float">0</span><span class="float">.2</span>); <span class="comment">// value assigned at link time</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>uniform</strong> qualifier can be used with any of the basic data types, or
when declaring a variable whose type is a structure, or an array of any of
these.</p>
</div>
<div class="paragraph">
<p>There is an implementation-dependent limit on the amount of storage for
uniforms that can be used for each type of shader and if this is exceeded it
will cause a compile-time or link-time error.
Uniform variables that are declared but not
used do not count against this limit.
The number of user-defined uniform variables and the number of built-in
uniform variables that are used within a shader are added together to
determine whether available uniform storage has been exceeded.</p>
</div>
<div class="paragraph">
<p>Uniforms in shaders all share a single global name space when linked into a
program or separable program.
Hence, the types,
initializers,
and any location specifiers of all statically used uniform variables with the
same name must match across all shaders that are linked into a single program.
However it is not required to repeat the
initializer or
location specifier in all the linked shaders.
While this single uniform name space is cross stage, a uniform variable
name&#8217;s scope is per stage: If a uniform variable name is declared in one
stage (e.g. a vertex shader) but not in another (e.g. a fragment shader),
then that name is still available in the other stage for a different use.</p>
</div>
</div>
<div class="sect3">
<h4 id="output-variables">4.3.6. Output Variables</h4>
<div class="paragraph">
<p>Shader output variables are declared with the <strong>out</strong> storage qualifier.
They form the output interface between the declaring shader and the
subsequent stages of the API pipeline.
Output variables must be declared at global scope.
During shader execution they will behave as normal unqualified global
variables.
Their values are copied out to the subsequent pipeline stage on shader exit.
Only output variables that are read by the subsequent pipeline stage need to
be written; it is allowed to have superfluous declarations of output
variables.</p>
</div>
<div class="paragraph">
<p>There is <em>not</em> an <strong>inout</strong> storage qualifier for declaring a single variable
name as both input and output to a shader.
Also, a variable cannot be declared with both the <strong>in</strong> and the <strong>out</strong>
qualifiers, this will result in a compile-time or link-time error.
Output variables must be declared with different names than input variables.
However, nesting an input or output inside an interface block with an
instance name allows the same names with one referenced through a block
instance name.</p>
</div>
<div class="paragraph">
<p>Vertex, tessellation evaluation, and geometry output variables output
per-vertex data and are declared using the <strong>out</strong> storage qualifier.
Applying <strong>patch</strong> to an output can only be done in a tessellation control
shader.
It is a compile-time error to use <strong>patch</strong> on outputs in any other stage.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to declare a vertex, tessellation evaluation,
tessellation control, or geometry shader output with, or that contains, any
of the following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <a href="#booleans">boolean type</a></p>
</li>
<li>
<p>An <a href="#opaque-types">opaque type</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Individual outputs are declared as in the following examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out vec3 normal;
centroid out vec2 TexCoord;
invariant centroid out vec4 Color;
flat out vec3 myColor;
sample out vec4 perSampleColor;</code></pre>
</div>
</div>
<div class="paragraph">
<p>These can also appear in interface blocks, as described in
&#8220;<a href="#interface-blocks">Interface Blocks</a>&#8221;.
Interface blocks allow simpler addition of arrays to the interface from
vertex to geometry shader.
They also allow a fragment shader to have the same input interface as a
geometry shader for a given vertex shader.</p>
</div>
<div class="paragraph">
<p>Tessellation control shader output variables are used to output
per-vertex and per-patch data.
Per-vertex output variables are arrayed (see <em>arrayed</em> under
&#8220;<a href="#input-variables">Input Variables</a>&#8221;) and declared using the <strong>out</strong>
qualifier without the <strong>patch</strong> qualifier.
Per-patch output variables are declared using the <strong>patch</strong> and <strong>out</strong>
qualifiers.</p>
</div>
<div class="paragraph">
<p>Since tessellation control shaders produce an arrayed primitive comprising
multiple vertices, each per-vertex output variable (or output block, see
interface blocks below) needs to be declared as an array.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out <span class="predefined-type">float</span> foo[]; <span class="comment">// feeds next stage input &quot;in float foo[]&quot;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Each element of such an array corresponds to one vertex of the primitive
being produced.
Each array can optionally have a size declared.
The array size will be set by (or if provided must be consistent with) the
output layout declaration(s) establishing the number of vertices in the
output patch, as described later in
&#8220;<a href="#tessellation-control-outputs">Tessellation Control Outputs</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Each tessellation control shader invocation has a corresponding output patch
vertex, and may assign values to per-vertex outputs only if they belong to
that corresponding vertex.
If a per-vertex output variable is used as an l-value, it is a compile-time
or link-time error if the expression indicating the vertex index is not the
identifier <em>gl_InvocationID</em>.</p>
</div>
<div class="paragraph">
<p>The order of execution of a tessellation control shader invocation relative
to the other invocations for the same input patch is undefined unless the
built-in function <strong>barrier</strong>() is used.
This provides some control over relative execution order.
When a shader invocation calls <strong>barrier</strong>(), its execution pauses until all
other invocations have reached the same point of execution.
Output variable assignments performed by any invocation executed prior to
calling <strong>barrier</strong>() will be visible to any other invocation after the call
to <strong>barrier</strong>() returns.</p>
</div>
<div class="paragraph">
<p>Because tessellation control shader invocations execute in undefined order
between barriers, the values of per-vertex or per-patch output variables
will sometimes be undefined.
Consider the beginning and end of shader execution and each call to
<strong>barrier</strong>() as synchronization points.
The value of an output variable will be undefined in any of the three
following cases:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>At the beginning of execution.</p>
</li>
<li>
<p>At each synchronization point, unless</p>
<div class="openblock">
<div class="content">
<div class="ulist">
<ul>
<li>
<p>the value was well-defined after the previous synchronization point and
was not written by any invocation since, or</p>
</li>
<li>
<p>the value was written by exactly one shader invocation since the previous
synchronization point, or</p>
</li>
<li>
<p>the value was written by multiple shader invocations since the previous
synchronization point, and the last write performed by all such
invocations wrote the same value.</p>
</li>
</ul>
</div>
</div>
</div>
</li>
<li>
<p>When read by a shader invocation, if</p>
<div class="openblock">
<div class="content">
<div class="ulist">
<ul>
<li>
<p>the value was undefined at the previous synchronization point and has not
been written by the same shader invocation since, or</p>
</li>
<li>
<p>the output variable is written to by any other shader invocation between
the previous and next synchronization points, even if that assignment
occurs in code following the read.</p>
</li>
</ul>
</div>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Fragment outputs output per-fragment data and are declared using the <strong>out</strong>
storage qualifier.
It is a compile-time error to use auxiliary storage qualifiers or
interpolation qualifiers in a fragment shader output declaration.
It is a compile-time error to declare a fragment shader output with, or that
contains, any of the following types:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A <a href="#booleans">boolean type</a></p>
</li>
<li>
<p>A double-precision scalar or vector (<strong>double</strong>, <strong>dvec2</strong>, <strong>dvec3</strong>,
<strong>dvec4</strong>)</p>
</li>
<li>
<p>An <a href="#opaque-types">opaque type</a></p>
</li>
<li>
<p>A matrix type</p>
</li>
<li>
<p>A structure</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment outputs are declared as in the following examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out vec4 FragmentColor;
out uint Luminosity;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compute shaders have no built-in output variables, do not support
user-defined output variables and do not form a formal interface with any
other shader stage.
All outputs from a compute shader take the form of the side effects such as
image stores and operations on atomic counters.</p>
</div>
</div>
<div class="sect3">
<h4 id="buffer-variables">4.3.7. Buffer Variables</h4>
<div class="paragraph">
<p>The <strong>buffer</strong> qualifier is used to declare global variables whose values are
stored in the data store of a buffer object bound through the API.
Buffer variables can be read and written, with the underlying storage shared
among all active shader invocations.
Buffer variable memory reads and writes within a single shader invocation
are processed in order.
However, the order of reads and writes performed in one invocation relative
to those performed by another invocation is largely undefined.
Buffer variables may be qualified with memory qualifiers affecting how the
underlying memory is accessed, as described in &#8220;<a href="#memory-qualifiers">Memory
Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>The <strong>buffer</strong> qualifier can be used to declare interface blocks (see
&#8220;<a href="#interface-blocks">Interface Blocks</a>&#8221;), which are then referred to as
shader storage blocks.
It is a compile-time error to declare buffer variables outside a block.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// use buffer to create a buffer block (shader storage block)</span>
buffer BufferName { <span class="comment">// externally visible name of buffer</span>
<span class="predefined-type">int</span> count; <span class="comment">// typed, shared memory...</span>
... <span class="comment">// ...</span>
vec4 v[]; <span class="comment">// last member may be an array that is not sized</span>
<span class="comment">// until after link time (dynamically sized)</span>
} Name; <span class="comment">// name of block within the shader</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>There are implementation-dependent limits on the number of shader storage
blocks used for each type of shader, the combined number of shader storage
blocks used for a program, and the amount of storage required by each
individual shader storage block.
If any of these limits are exceeded, it will cause a compile-time or
link-time error.</p>
</div>
<div class="paragraph">
<p>If multiple shaders are linked together, then they will share a single
global buffer variable name space.
Hence, the types of all declared buffer variables with the same name must
match across all shaders that are linked into a single program.</p>
</div>
</div>
<div class="sect3">
<h4 id="shared-variables">4.3.8. Shared Variables</h4>
<div class="paragraph">
<p>The <strong>shared</strong> qualifier is used to declare global variables that have storage
shared between all work items in a compute shader workgroup.
Variables declared as <strong>shared</strong> may only be used in compute shaders (see
&#8220;<a href="#compute-processor">Compute Processor</a>&#8221;).
Any other declaration of a <strong>shared</strong> variable is a compile-time error.
Shared variables are implicitly coherent (see
&#8220;<a href="#memory-qualifiers">Memory Qualifiers</a>&#8221;).</p>
</div>
<div class="paragraph">
<p>Variables declared as <strong>shared</strong> may not have initializers and their contents
are undefined at the beginning of shader execution.
Any data written to <strong>shared</strong> variables will be visible to other work items
(executing the same shader) within the same workgroup.</p>
</div>
<div class="paragraph">
<p>In the absence of synchronization, the order of reads and writes to the same
<strong>shared</strong> variable by different invocations of a shader is not defined.</p>
</div>
<div class="paragraph">
<p>In order to achieve ordering with respect to reads and writes to <strong>shared</strong>
variables, control flow barriers must be employed using the <strong>barrier</strong>() function
(see &#8220;<a href="#shader-invocation-control-functions">Shader Invocation Control
Functions</a>&#8221;).</p>
</div>
<div class="paragraph">
<p>There is a limit to the total size of all variables declared as <strong>shared</strong> in a
single program.
This limit, expressed in units of basic machine units may be determined by
using the OpenGL API to query the value of
MAX_COMPUTE_SHARED_MEMORY_SIZE.</p>
</div>
</div>
<div class="sect3">
<h4 id="interface-blocks">4.3.9. Interface Blocks</h4>
<div class="paragraph">
<p>Input, output, uniform, and buffer variable declarations can be grouped into
named interface blocks to provide coarser granularity backing than is
achievable with individual declarations.
They can have an optional instance name, used in the shader to reference
their members.
An output block of one programmable stage is backed by a corresponding input
block in the subsequent programmable stage.
A <em>uniform block</em> is backed by the application with a buffer object.
A block of buffer variables, called a <em>shader storage block</em>, is also backed
by the application with a buffer object.
It is a compile-time error to have an input block in a vertex shader or an
output block in a fragment shader.
These uses are reserved for future use.</p>
</div>
<div class="paragraph">
<p>An interface block is started by an <strong>in</strong>, <strong>out</strong>, <strong>uniform</strong>, or <strong>buffer</strong>
keyword, followed by a block name, followed by an open curly brace (<strong>{</strong>) as
follows:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>interface-block</em> : </dt>
<dd>
<p><em>layout-qualifier<sub>opt</sub></em> <em>interface-qualifier</em> <em>block-name</em> <strong>{</strong>
<em>member-list</em> <strong>}</strong> <em>instance-name<sub>opt</sub></em> <strong>;</strong></p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>interface-qualifier</em> : </dt>
<dd>
<p><strong>in</strong><br>
<strong>out</strong><br>
<strong>patch</strong> <strong>in</strong> // Note: Qualifiers can be in any order.<br>
<strong>patch</strong> <strong>out</strong><br>
<strong>uniform</strong><br>
<strong>buffer</strong></p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>member-list</em> : </dt>
<dd>
<p><em>member-declaration</em><br>
<em>member-declaration</em> <em>member-list</em></p>
</dd>
<dt class="hdlist1"><em>member-declaration</em> : </dt>
<dd>
<p><em>layout-qualifier<sub>opt</sub></em> <em>qualifiers<sub>opt</sub></em> <em>type</em> <em>declarators</em> <strong>;</strong></p>
</dd>
</dl>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>instance-name</em> : </dt>
<dd>
<p><em>identifier</em><br>
<em>identifier</em> <strong>[</strong> <strong>]</strong><br>
<em>identifier</em> <strong>[</strong> <em>constant-integral-expression</em> <strong>]</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Each of the above elements is discussed below, with the exception of layout
qualifiers (<em>layout-qualifier</em>), which are defined in the next section.</p>
</div>
<div class="paragraph">
<p>First, an example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">uniform Transform {
mat4 ModelViewMatrix;
mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix; <span class="comment">// allowed restatement of qualifier</span>
<span class="predefined-type">float</span> Deformation;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The above establishes a uniform block named &#8220;Transform&#8221; with four uniforms
grouped inside it.</p>
</div>
<div class="paragraph">
<p>Types and declarators are the same as for other input, output, uniform, and
buffer variable declarations outside blocks, with these exceptions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Initializers are not allowed</p>
</li>
<li>
<p>Opaque types are not allowed</p>
</li>
<li>
<p>Structure definitions cannot be nested inside a block</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Any of these would result in a compile-time error.</p>
</div>
<div class="paragraph">
<p>If no optional qualifier is used in a member-declaration, the qualification
of the member includes all <strong>in</strong>, <strong>out</strong>, <strong>patch</strong>, <strong>uniform</strong>, or <strong>buffer</strong> as
determined by <em>interface-qualifier</em>.
If optional qualifiers are used, they can include interpolation qualifiers,
auxiliary storage qualifiers,
and storage qualifiers and they must declare
an input, output, or uniform member consistent with the interface qualifier
of the block: Input variables, output variables, uniform variables, and
<strong>buffer</strong> members can only be in <strong>in</strong> blocks, <strong>out</strong> blocks, <strong>uniform</strong> blocks,
and shader storage blocks, respectively.</p>
</div>
<div class="paragraph">
<p>Repeating the <strong>in</strong>, <strong>out</strong>, <strong>patch</strong>, <strong>uniform</strong>, or <strong>buffer</strong> interface
qualifier for a member&#8217;s storage qualifier is optional.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in Material {
smooth in vec4 Color1; <span class="comment">// legal, input inside in block</span>
smooth vec4 Color2; <span class="comment">// legal, 'in' inherited from 'in Material'</span>
vec2 TexCoord; <span class="comment">// legal, TexCoord is an input</span>
uniform <span class="predefined-type">float</span> Atten; <span class="comment">// illegal, mismatched storage qualifier</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>A <em>shader interface</em> is defined to be one of these:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>All the uniform variables and uniform blocks declared in a program.
This spans all compilation units linked together within one program.</p>
</li>
<li>
<p>All the <strong>buffer</strong> blocks declared in a program.</p>
</li>
<li>
<p>The boundary between adjacent programmable pipeline stages: This spans
all the outputs declared in all compilation units of the first stage and
all the inputs declared in all compilation units of the second stage.
Note that for the purposes of this definition, the fragment shader and
the preceding shader are considered to have a shared boundary even
though in practice, all values passed to the fragment shader first pass
through the rasterizer and interpolator.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The block name (<em>block-name</em>) is used to match within shader interfaces: an
output block of one pipeline stage will be matched to an input block with
the same name in the subsequent pipeline stage.
For uniform or shader storage blocks, the application uses the block name to
identify the block.
Block names have no other use within a shader beyond interface matching; it
is a compile-time error
to use a block name at global scope for anything other than as a
block name (e.g. use of a block name for a global variable name or function
name is currently reserved).
It is a compile-time error to use the same block name for more than one
block declaration in the same shader interface (as defined above) within one
shader, even if the block contents are identical.</p>
</div>
<div class="paragraph">
<p>Matched block names within a shader interface (as defined above) must match
in terms of having the same number of declarations with the same sequence of
types and the same sequence of member names, as well as having matching
member-wise layout qualification
(see next section).
Matched uniform or shader storage block names (but not input or output block
names) must also either all be lacking an instance name or all having an
instance name, putting their members at the same scoping level.
When instance names are present on matched block names, it is allowed for
the instance names to differ; they need not match for the blocks to match.
Furthermore, if a matching block is declared as an array, then the array
sizes must also match (or follow array matching rules for the shader
interface between consecutive shader stages).
Any mismatch will generate a link-time error.
A block name is allowed to have different definitions in different shader
interfaces within the same shader, allowing, for example, an input block and
output block to have the same name.</p>
</div>
<div class="paragraph">
<p>If an instance name (<em>instance-name</em>) is not used, the names declared inside
the block are scoped at the global level and accessed as if they were
declared outside the block.
If an instance name (<em>instance-name</em>) is used, then it puts all the members
inside a scope within its own name space, accessed with the field selector
(<strong>.</strong>) operator (analogously to structures).
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in Light {
vec4 LightPos;
vec3 LightColor;
};
in ColoredTexture {
vec4 Color;
vec2 TexCoord;
} Material; <span class="comment">// instance name</span>
vec3 Color; <span class="comment">// different Color than Material.Color</span>
vec4 LightPos; <span class="comment">// illegal, already defined</span>
...
... = LightPos; <span class="comment">// accessing LightPos</span>
... = Material.Color; <span class="comment">// accessing Color in ColoredTexture block</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Outside the shading language (i.e., in the API), members are similarly
identified except the block name is always used in place of the instance
name (API accesses are to shader interfaces, not to shaders).
If there is no instance name, then the API does not use the block name to
access a member, just the member name.</p>
</div>
<div class="paragraph">
<p>Within a shader interface, all declarations of the same global name must be
for the same object and must match in type and in whether they declare a
variable or member of a block with no instance name.
The API also needs this name to uniquely identify an object in the shader
interface.
It is a link-time error if any particular shader interface contains</p>
</div>
<div class="ulist">
<ul>
<li>
<p>two different blocks, each having no instance name, and each having a
member of the same name, or</p>
</li>
<li>
<p>a variable outside a block, and a block with no instance name, where the
variable has the same name as a member in the block.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out Vertex {
vec4 Position; <span class="comment">// API transform/feedback will use &quot;Vertex.Position&quot;</span>
vec2 Texture;
} Coords; <span class="comment">// shader will use &quot;Coords.Position&quot;</span>
out Vertex2 {
vec4 Color; <span class="comment">// API will use &quot;Color&quot;</span>
<span class="predefined-type">float</span> Color2;
};
<span class="comment">// in same program as Vertex2 above:</span>
out Vertex3 {
<span class="predefined-type">float</span> Intensity;
vec4 Color; <span class="comment">// ERROR, name collision with Color in Vertex2</span>
};
<span class="predefined-type">float</span> Color2; <span class="comment">// ERROR, collides with Color2 in Vertex2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For blocks declared as arrays, the array index must also be included when
accessing members, as in this example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">uniform Transform { <span class="comment">// API uses &quot;Transform[2]&quot; to refer to instance 2</span>
mat4 ModelViewMatrix;
mat4 ModelViewProjectionMatrix;
vec4 a[]; <span class="comment">// array will get implicitly sized</span>
<span class="predefined-type">float</span> Deformation;
} transforms[<span class="integer">4</span>];
...
... = transforms[<span class="integer">2</span>].ModelViewMatrix; <span class="comment">// shader access of instance 2</span>
<span class="comment">// API uses &quot;Transform.ModelViewMatrix&quot; to query an offset or other query</span>
transforms[x].a.length(); <span class="comment">// same length for 'a' for all x</span>
Transform[x]; <span class="comment">// illegal, must use 'transforms'</span>
Transform.a.length(); <span class="comment">// illegal, must use 'transforms'</span>
...transforms[<span class="integer">2</span>].a[<span class="integer">3</span>]... <span class="comment">// if these are the only two dereferences of 'a',</span>
...transforms[<span class="integer">3</span>].a[<span class="integer">7</span>]... <span class="comment">// then 'a' must be size 8, for all</span>
transforms[x]</code></pre>
</div>
</div>
<div class="paragraph">
<p>For uniform or shader storage blocks declared as an array, each individual
array element corresponds to a separate buffer object bind range, backing
one instance of the block.
As the array size indicates the number of buffer objects needed, uniform and
shader storage block array declarations must specify an array size.
A uniform or shader storage block array can only be indexed with a
dynamically uniform integral expression, otherwise results are undefined.</p>
</div>
<div class="paragraph">
<p>When using OpenGL API entry points to identify the name of an individual
block in an array of blocks, the name string may include an array index
(e.g. <em>Transform[2]</em>).
When using OpenGL API entry points to refer to offsets or other
characteristics of a block member, an array index must not be specified
(e.g. <em>Transform.ModelViewMatrix</em>).</p>
</div>
<div class="paragraph">
<p>Tessellation control, tessellation evaluation and geometry shader input
blocks must be declared as arrays and follow the array declaration and
linking rules for all shader inputs for the respective stages.
All other input and output block arrays must specify an array size.</p>
</div>
<div class="paragraph">
<p>There are implementation-dependent limits on the number of uniform blocks
and the number of shader storage blocks that can be used per stage.
If either limit is exceeded, it will cause a link-time error.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="layout-qualifiers">4.4. Layout Qualifiers</h3>
<div class="paragraph">
<p>Layout qualifiers can appear in several forms of declaration.
They can appear as part of an interface block definition or block member, as
shown in the grammar in the previous section.
They can also appear with just an <em>interface-qualifier</em> to establish layouts
of other declarations made with that qualifier:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="paragraph">
<p><em>layout-qualifier</em> <em>interface-qualifier</em> <strong>;</strong></p>
</div>
</div>
</div>
<div class="paragraph">
<p>Or, they can appear with an individual variable declared with an interface
qualifier:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="paragraph">
<p><em>layout-qualifier</em> <em>interface-qualifier</em> <em>declaration</em> <strong>;</strong></p>
</div>
</div>
</div>
<div class="paragraph">
<p>Declarations of layouts can only be made at global scope or block members,
and only where indicated in the following subsections; their details are
specific to what the interface qualifier is, and are discussed individually.</p>
</div>
<div class="paragraph">
<p>The <em>layout-qualifier</em> expands to:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier</em> : </dt>
<dd>
<p><strong>layout</strong> <strong>(</strong> <em>layout-qualifier-id-list</em> <strong>)</strong></p>
</dd>
<dt class="hdlist1"><em>layout-qualifier-id-list</em> : </dt>
<dd>
<p><em>layout-qualifier-id</em><br>
<em>layout-qualifier-id</em> <strong>,</strong> <em>layout-qualifier-id-list</em></p>
</dd>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><em>layout-qualifier-name</em><br>
<em>layout-qualifier-name</em> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>shared</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-value</em> : </dt>
<dd>
<p><em>integer-constant-expression</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The tokens used for <em>layout-qualifier-name</em> are identifiers, not keywords,
however, the <strong>shared</strong> keyword is allowed as a <em>layout-qualifier-id</em>.
Generally, they can be listed in any order.
Order-dependent meanings exist only if explicitly called out below.
Similarly, these identifiers are not case sensitive, unless explicitly noted
otherwise.</p>
</div>
<div class="paragraph">
<p>More than one layout qualifier may appear in a single declaration.
Additionally, the same <em>layout-qualifier-name</em> can occur multiple times
within a layout qualifier or across multiple layout qualifiers in the same
declaration.
When the same <em>layout-qualifier-name</em> occurs multiple times, in a single
declaration, the last occurrence overrides the former occurrence(s).
Further, if such a <em>layout-qualifier-name</em> will affect subsequent
declarations or other observable behavior, it is only the last occurrence
that will have any effect, behaving as if the earlier occurrence(s) within
the declaration are not present.
This is also true for overriding <em>layout-qualifier-name</em>, where one
overrides the other (e.g. <strong>row_major</strong> vs.
<strong>column_major</strong>); only the last occurrence has any effect.</p>
</div>
<div class="paragraph">
<p><em>integer-constant-expression</em> is defined in
&#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221; as <em>constant integral
expression</em>, with it being a compile-time error for
<em>integer-constant-expression</em> to be a specialization constant.</p>
</div>
<div class="paragraph">
<p>The following table summarizes the use of layout qualifiers.
It shows for each one what kinds of declarations it may be applied to.
These are all discussed in detail in the following sections.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 16.667%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-middle">Layout Qualifier</th>
<th class="tableblock halign-center valign-middle">Qualifier Only</th>
<th class="tableblock halign-center valign-middle">Individual Variable</th>
<th class="tableblock halign-center valign-middle">Block</th>
<th class="tableblock halign-center valign-middle">Block Member</th>
<th class="tableblock halign-left valign-middle">Allowed Interfaces</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shared</strong><br>
<strong>packed</strong><br>
<strong>std140</strong><br>
<strong>std430</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle" rowspan="5"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>row_major</strong><br>
<strong>column_major</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>binding</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">opaque types only</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>offset</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">atomic counters only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>align</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>set</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">opaque types only</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong> (Vulkan only)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>push_constant</strong></p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> (Vulkan only)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>input_attachment_index</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">subpass types only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> (Vulkan only)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>location</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong> and subroutine variables</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>location</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">all <strong>in</strong> / <strong>out</strong>, except for compute</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>component</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>index</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">fragment <strong>out</strong> and subroutine functions</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>triangles</strong><br>
<strong>quads</strong><br>
<strong>isolines</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>equal_spacing</strong><br>
<strong>fractional_even_spacing</strong><br>
<strong>fractional_odd_spacing</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>cw</strong><br>
<strong>ccw</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>point_mode</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>points</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong>/<strong>out</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock">[ <strong>points</strong> ]<br>
<strong>lines</strong><br>
<strong>lines_adjacency</strong><br>
<strong>triangles</strong><br>
<strong>triangles_adjacency</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>invocations</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>origin_upper_left</strong><br>
<strong>pixel_center_integer</strong></p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock"><em>gl_FragCoord</em> only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">fragment <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>early_fragment_tests</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>local_size_x</strong> =<br>
<strong>local_size_y</strong> =<br>
<strong>local_size_z</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">compute <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>local_size_x_id</strong> =<br>
<strong>local_size_y_id</strong> =<br>
<strong>local_size_z_id</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">compute <strong>in</strong> (SPIR-V only)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>xfb_buffer</strong> =<br>
<strong>xfb_stride</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">vertex, tessellation, and geometry <strong>out</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>xfb_offset</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>vertices</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation control <strong>out</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock">[ <strong>points</strong> ]<br>
<strong>line_strip</strong><br>
<strong>triangle_strip</strong></p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle" rowspan="3"><p class="tableblock">geometry <strong>out</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>max_vertices</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>stream</strong> =</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>depth_any</strong><br>
<strong>depth_greater</strong><br>
<strong>depth_less</strong><br>
<strong>depth_unchanged</strong></p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock"><em>gl_FragDepth</em> only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock">fragment <strong>out</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>constant_id</strong> =</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">scalar only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>const</strong> (SPIR-V only)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>rgba32f</strong><br>
<strong>rgba16f</strong><br>
<strong>rg32f</strong><br>
<strong>rg16f</strong><br>
<strong>r11f_g11f_b10f</strong><br>
<strong>r32f</strong><br>
<strong>r16f</strong><br>
<strong>rgba16</strong><br>
<strong>rgb10_a2</strong><br>
<strong>rgba8</strong><br>
<strong>rg16</strong><br>
<strong>rg8</strong><br>
<strong>r16</strong><br>
<strong>r8</strong><br>
<strong>rgba16_snorm</strong><br>
<strong>rgba8_snorm</strong><br>
<strong>rg16_snorm</strong><br>
<strong>rg8_snorm</strong><br>
<strong>r16_snorm</strong><br>
<strong>r8_snorm</strong><br>
<strong>rgba32i</strong><br>
<strong>rgba16i</strong><br>
<strong>rgba8i</strong><br>
<strong>rg32i</strong><br>
<strong>rg16i</strong><br>
<strong>rg8i</strong><br>
<strong>r32i</strong><br>
<strong>r16i</strong><br>
<strong>r8i</strong><br>
<strong>rgba32ui</strong><br>
<strong>rgba16ui</strong><br>
<strong>rgb10_a2ui</strong><br>
<strong>rgba8ui</strong><br>
<strong>rg32ui</strong><br>
<strong>rg16ui</strong><br>
<strong>rg8ui</strong><br>
<strong>r32ui</strong><br>
<strong>r16ui</strong><br>
<strong>r8ui</strong></p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">image types only</p></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-center valign-middle"></td>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong></p></td>
</tr>
</tbody>
</table>
<div class="sect3">
<h4 id="input-layout-qualifiers">4.4.1. Input Layout Qualifiers</h4>
<div class="paragraph">
<p>Layout qualifiers specific to a particular shader language are discussed in
separate sections below.</p>
</div>
<div class="paragraph">
<p>All shaders except compute shaders allow <strong>location</strong> layout qualifiers on
input variable declarations, input block declarations, and input block
member declarations.
Of these, variables and block members (but not blocks) additionally allow
the <strong>component</strong> layout qualifier.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>component</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) in vec4 normal;
<span class="directive">const</span> <span class="predefined-type">int</span> start = <span class="integer">6</span>;
layout(location = start + <span class="integer">2</span>) <span class="predefined-type">int</span> vec4 v;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the shader input <em>normal</em> is assigned to vector location
number
3 and <em>v</em> is assigned location number 8.
For vertex shader inputs, the location specifies the number of the
vertex attribute from which input values are taken.
For inputs of all other shader types, the location specifies a vector number
that can be used to match against outputs from a previous shader stage, even
if that shader is in a different program object.</p>
</div>
<div class="paragraph">
<p>The following language describes how many locations are consumed by a given
type.
However, geometry shader inputs, tessellation control shader inputs and
outputs, and tessellation evaluation inputs all have an additional level of
arrayness relative to other shader inputs and outputs.
This outer array level is removed from the type before considering how many
locations the type consumes.</p>
</div>
<div class="paragraph">
<p>Except when targeting Vulkan,
if a vertex shader input is any scalar or vector type, it will consume a
single location.
If a non-vertex shader input, or any stage input when targeting Vulkan,
is a scalar or vector type other than <strong>dvec3</strong>
or <strong>dvec4</strong>, it will consume a single location, while types <strong>dvec3</strong> or
<strong>dvec4</strong> will consume two consecutive locations.
Inputs of type <strong>double</strong> and <strong>dvec2</strong> will consume only a single location, in
all stages.</p>
</div>
<div class="paragraph">
<p>If the declared input (after potentially removing an outer array level as
just described above) is an array of size <em>n</em> and each of the elements takes
<em>m</em> locations, it will be assigned <em>m</em> * <em>n</em> consecutive locations starting
with the location specified.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">6</span>) in vec4 colors[<span class="integer">3</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the shader input <em>colors</em> is assigned to vector location
numbers 6, 7, and 8.</p>
</div>
<div class="paragraph">
<p>If the declared input is an <em>n</em> × <em>m</em>
matrix, it will be assigned multiple locations starting with the location
specified.
The number of locations assigned for each matrix will be the same as for an
<em>n</em>-element array of <em>m</em>-component vectors.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">9</span>) in mat4 transforms[<span class="integer">2</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that shader input <em>transforms</em> is assigned to vector
locations 9-16, with <em>transforms[0]</em> being assigned to locations 9-12, and
<em>transforms[1]</em> being assigned to locations 13-16.</p>
</div>
<div class="paragraph">
<p>If the declared input is a structure or block, its members will be assigned
consecutive locations in their order of declaration, with the first member
assigned the location provided in the layout qualifier.
For a structure, this process applies to the entire structure.
It is a compile-time error to use a <strong>location</strong> qualifier on a member of a
structure.
For a block, this process applies to the entire block, or until the first
member is reached that has a <strong>location</strong> layout qualifier.</p>
</div>
<div class="paragraph">
<p>When a block member is declared with a <strong>location</strong> qualifier, its location
comes from that qualifier; the member&#8217;s <strong>location</strong> qualifier overrides the
block-level declaration.
Subsequent members are again assigned consecutive locations, based on the
newest location, until the next member declared with a <strong>location</strong> qualifier.
The values used for locations do not have to be declared in increasing
order.</p>
</div>
<div class="paragraph">
<p>If a block has no block-level <strong>location</strong> layout qualifier, it is required
that either all or none of its members have a <strong>location</strong> layout qualifier,
or a compile-time error results.
For some blocks declared as arrays, the <strong>location</strong> can only be applied at
the block level: When a block is declared as an array where additional
locations are needed for each member for each block array element, it is a
compile-time error to specify locations on the block members.
That is, when locations would be under specified by applying them on block
members, they are not allowed on block members.
For <em>arrayed</em> interfaces (those generally having an extra level of arrayness
due to interface expansion), the outer array is stripped before applying
this rule.</p>
</div>
<div class="paragraph">
<p>When generating SPIR-V, all <strong>in</strong> and <strong>out</strong> qualified user-declared (non
built-in) variables and blocks (or all their members) must have a
shader-specified <strong>location</strong>.
Otherwise, a compile-time error is generated.</p>
</div>
<div class="paragraph">
<p>The locations consumed by block and structure members are determined by
applying the rules above recursively as though the structure member were
declared as an input variable of the same type.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) in <span class="keyword">struct</span> S
{
vec3 a; <span class="comment">// gets location 3</span>
mat2 b; <span class="comment">// gets locations 4 and 5</span>
vec4 c[<span class="integer">2</span>]; <span class="comment">// gets locations 6 and 7</span>
layout(location = <span class="integer">8</span>) vec2 A; <span class="comment">// ERROR, can't use on struct member</span>
} s;
layout(location = <span class="integer">4</span>) in block
{
vec4 d; <span class="comment">// gets location 4</span>
vec4 e; <span class="comment">// gets location 5</span>
layout(location = <span class="integer">7</span>) vec4 f; <span class="comment">// gets location 7</span>
vec4 g; <span class="comment">// gets location 8</span>
layout(location = <span class="integer">1</span>) vec4 h; <span class="comment">// gets location 1</span>
vec4 i; <span class="comment">// gets location 2</span>
vec4 j; <span class="comment">// gets location 3</span>
vec4 k; <span class="comment">// ERROR, location 4 already used</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The number of input locations available to a shader is limited.
For vertex shaders, the limit is the advertised number of vertex attributes.
For all other shaders, the limit is implementation-dependent and must be no
less than one fourth of the advertised maximum input component count.</p>
</div>
<div class="paragraph">
<p>A program will fail to link if any attached shader uses a location greater
than or equal to the number of supported locations, unless device-dependent
optimizations are able to make the program fit within available hardware
resources.</p>
</div>
<div class="paragraph">
<p>A program will fail to link if explicit location assignments leave the
linker unable to find space for other variables without explicit
assignments.</p>
</div>
<div class="paragraph">
<p>For the purposes of determining if a non-vertex input matches an output from
a previous shader stage, the <strong>location</strong> layout qualifier (if any) must
match.</p>
</div>
<div class="paragraph">
<p>If a vertex shader input variable with no location assigned in the shader
text has a location specified through the OpenGL API, the API-assigned
location will be used.
Otherwise, such variables will be assigned a location by the linker.
See section 11.1.1 &#8220;Vertex Attributes&#8221; of the <a href="#references">OpenGL Specification</a> for
more details.
A link-time error will occur if an input variable is declared in multiple
shaders of the same language with conflicting locations.</p>
</div>
<div class="paragraph">
<p>The <strong>component</strong> qualifier allows the location to be more finely specified
for scalars and vectors, down to the individual components within a location
that are consumed.
It is a compile-time error to use <strong>component</strong> without also specifying the
<strong>location</strong> qualifier (order does not matter).
The components within a location are 0, 1, 2, and 3.
A variable or block member starting at component <em>N</em> will consume components
<em>N</em>, <em>N+1</em>, <em>N+2</em>, &#8230;&#8203;
up through its size.
It is a compile-time error if this sequence of components gets larger than
3.
A scalar <strong>double</strong> will consume two of these components, and a <strong>dvec2</strong> will
consume all four components available within a location.
A <strong>dvec3</strong> or <strong>dvec4</strong> can only be declared without specifying a <strong>component</strong>.
A <strong>dvec3</strong> will consume all four components of the first location and
components 0 and 1 of the second location.
This leaves components 2 and 3 available for other component-qualified
declarations.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// a consumes components 2 and 3 of location 4</span>
layout(location = <span class="integer">4</span>, component = <span class="integer">2</span>) in vec2 a;
<span class="comment">// b consumes component 1 of location 4</span>
layout(location = <span class="integer">4</span>, component = <span class="integer">1</span>) in <span class="predefined-type">float</span> b;
<span class="comment">// ERROR: c overflows component 3</span>
layout(location = <span class="integer">3</span>, component = <span class="integer">2</span>) in vec3 c;
<span class="comment">// d consumes components 2 and 3 of location 5</span>
layout(location = <span class="integer">5</span>, component = <span class="integer">2</span>) in <span class="predefined-type">double</span> d;
<span class="comment">// ERROR: e overflows component 3 of location 6</span>
layout(location = <span class="integer">6</span>, component = <span class="integer">2</span>) in dvec2 e;
<span class="comment">// ERROR: f overlaps with g</span>
layout(location = <span class="integer">7</span>, component = <span class="integer">0</span>) <span class="predefined-type">double</span> f;
layout(location = <span class="integer">7</span>, component = <span class="integer">1</span>) <span class="predefined-type">float</span> g;
layout(location = <span class="integer">8</span>) in dvec3 h; <span class="comment">// components 0,1,2 and 3 of location 8</span>
<span class="comment">// and components 0 and 1 of location 9</span>
layout(location = <span class="integer">9</span>, component = <span class="integer">2</span>) in <span class="predefined-type">float</span> i; <span class="comment">// okay, compts 2 and 3</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If the variable is an array, each element of the array, in order, is
assigned to consecutive locations, but all at the same specified component
within each location.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// component 3 in 6 locations are consumed</span>
layout(location = <span class="integer">2</span>, component = <span class="integer">3</span>) in <span class="predefined-type">float</span> d[<span class="integer">6</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>That is, location 2 component 3 will hold <em>d[0]</em>, location 3 component 3
will hold <em>d[1]</em>, &#8230;&#8203;, up through location 7 component 3 holding <em>d[5]</em>.</p>
</div>
<div class="paragraph">
<p>This allows packing of two arrays into the same set of locations:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// e consumes beginning (components 0, 1 and 2) of each of 6 slots</span>
layout(location = <span class="integer">0</span>, component = <span class="integer">0</span>) in vec3 e[<span class="integer">6</span>];
<span class="comment">// f consumes last component of the same 6 slots</span>
layout(location = <span class="integer">0</span>, component = <span class="integer">3</span>) in <span class="predefined-type">float</span> f[<span class="integer">6</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>If applying this to an array of arrays, all levels of arrayness are removed
to get to the elements that are assigned per location to the specified
component.
These non-arrayed elements will fill the locations in the order specified
for arrays of arrays in &#8220;<a href="#arrays">Arrays</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to apply the <strong>component</strong> qualifier to a matrix, a
structure, a block, or an array containing any of these.
It is a compile-time error to use <strong>component</strong> 1 or 3 as the beginning of a
<strong>double</strong> or <strong>dvec2</strong>.
It is a link-time error to specify different components for the same
variable within a program.</p>
</div>
<div class="paragraph">
<p><em>Location aliasing</em> is causing two variables or block members to have the
same location number.
<em>Component aliasing</em> is assigning the same (or overlapping) component
numbers for two location aliases.
(Recall if <strong>component</strong> is not used, components are assigned starting with
0.)
With one exception, location aliasing is allowed only if it does not
cause component aliasing; it is a compile-time or link-time error to cause
component aliasing.
Further, when location aliasing, the aliases sharing the location must have
the same underlying numerical type and bit width (floating-point or integer,
32-bit versus 64-bit, etc.) and the same
auxiliary storage and interpolation qualification.
The one exception where component aliasing is permitted is
when targeting OpenGL for two input
variables (not block members) to a vertex shader, which are allowed to have
component aliasing.
This vertex-variable component aliasing is intended only to support vertex
shaders where each execution path accesses at most one input per each
aliased component.
Implementations are permitted, but not required, to generate link-time
errors if they detect that every path through the vertex shader executable
accesses multiple inputs aliased to any single component.</p>
</div>
<div class="sect4">
<h5 id="tessellation-evaluation-inputs">Tessellation Evaluation Inputs</h5>
<div class="paragraph">
<p>Additional input layout qualifier identifiers allowed for tessellation
evaluation shaders are described below.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><em>primitive_mode</em><br>
<em>vertex_spacing</em><br>
<em>ordering</em><br>
<em>point_mode</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The <strong>primitive-mode</strong> is used to specify a tessellation primitive mode to be
used by the tessellation primitive generator.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>primitive-mode</em>: </dt>
<dd>
<p><strong>triangles</strong><br>
<strong>quads</strong><br>
<strong>isolines</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>If present, the <em>primitive-mode</em> specifies that the tessellation primitive
generator should subdivide a triangle into smaller triangles, a quad into
triangles, or a quad into a collection of lines, respectively.</p>
</div>
<div class="paragraph">
<p>A second group of layout identifiers, <em>vertex spacing</em>, is used to specify
the spacing used by the tessellation primitive generator when subdividing an
edge.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>vertex-spacing</em>: </dt>
<dd>
<p><strong>equal_spacing</strong><br>
<strong>fractional_even_spacing</strong><br>
<strong>fractional_odd_spacing</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p><strong>equal_spacing</strong> specifies that edges should be divided into a collection of
equal-sized segments;</p>
</div>
<div class="paragraph">
<p><strong>fractional_even_spacing</strong> specifies that edges should be divided into an
even number of equal-length segments plus two additional shorter
&#8220;fractional&#8221; segments; or</p>
</div>
<div class="paragraph">
<p><strong>fractional_odd_spacing</strong> specifies that edges should be divided into an odd
number of equal-length segments plus two additional shorter &#8220;fractional&#8221;
segments.</p>
</div>
<div class="paragraph">
<p>A third group of layout identifiers, <em>ordering</em>, specifies whether the
tessellation primitive generator produces triangles in clockwise or
counter-clockwise order, according to the coordinate system depicted in the
<a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>ordering</em>: </dt>
<dd>
<p><strong>cw</strong><br>
<strong>ccw</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The identifiers <strong>cw</strong> and <strong>ccw</strong> indicate clockwise and counter-clockwise
triangles, respectively.
If the tessellation primitive generator does not produce triangles, the
order is ignored.</p>
</div>
<div class="paragraph">
<p>Finally, <em>point mode</em> indicates that the tessellation primitive generator
should produce one point for each distinct vertex in the subdivided
primitive, rather than generating lines or triangles.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>point-mode</em>: </dt>
<dd>
<p><strong>point_mode</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Any or all of these identifiers may be specified one or more times in a
single input layout declaration.
If primitive mode, vertex spacing, or ordering is declared more than once in
the tessellation evaluation shaders of a program, all such declarations must
use the same identifier.</p>
</div>
<div class="paragraph">
<p>At least one tessellation evaluation shader (compilation unit) in a program
must declare a primitive mode in its input layout.
Declaring vertex spacing, ordering, or point mode identifiers is optional.
It is not required that all tessellation evaluation shaders in a program
declare a primitive mode.
If spacing or vertex ordering declarations are omitted, the tessellation
primitive generator will use equal spacing or counter-clockwise vertex
ordering, respectively.
If a point mode declaration is omitted, the tessellation primitive generator
will produce lines or triangles according to the primitive mode.</p>
</div>
</div>
<div class="sect4">
<h5 id="geometry-shader-inputs">Geometry Shader Inputs</h5>
<div class="paragraph">
<p>Additional layout qualifier identifiers for geometry shader inputs include
<em>primitive</em> identifiers and an <em>invocation count</em> identifier:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>points</strong><br>
<strong>lines</strong><br>
<strong>lines_adjacency</strong><br>
<strong>triangles</strong><br>
<strong>triangles_adjacency</strong><br>
<strong>invocations</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The identifiers <strong>points</strong>, <strong>lines</strong>, <strong>lines_adjacency</strong>, <strong>triangles</strong>, and
<strong>triangles_adjacency</strong> are used to specify the type of input primitive
accepted by the geometry shader, and only one of these is accepted.
At least one geometry shader (compilation unit) in a program must declare
this input primitive layout, and all geometry shader input layout
declarations in a program must declare the same layout.
It is not required that all geometry shaders in a program declare an input
primitive layout.</p>
</div>
<div class="paragraph">
<p>The identifier <strong>invocations</strong> is used to specify the number of times the
geometry shader executable is invoked for each input primitive received.
Invocation count declarations are optional.
If no invocation count is declared in any geometry shader in a program, the
geometry shader will be run once for each input primitive.
If an invocation count is declared, all such declarations must specify the
same count.
If a shader specifies an invocation count greater than the
implementation-dependent maximum, or less than or equal to zero,
a compile-time error results.</p>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(triangles, invocations = <span class="integer">6</span>) in;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that all inputs to the geometry shader are triangles and that
the geometry shader executable is run six times for each triangle processed.</p>
</div>
<div class="paragraph">
<p>All geometry shader input unsized array declarations will be sized by an
earlier input primitive layout qualifier, when present, as per the following
table.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Layout</th>
<th class="tableblock halign-left valign-top">Size of Input Arrays</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>points</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lines</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lines_adjacency</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>triangles</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>triangles_adjacency</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The intrinsically declared input array <em>gl_in[]</em> will also be sized by any
input primitive-layout declaration.
Hence, the expression</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_in.length()</code></pre>
</div>
</div>
<div class="paragraph">
<p>will return the value from the table above.</p>
</div>
<div class="paragraph">
<p>For inputs declared without an array size, including intrinsically declared
inputs (i.e., <em>gl_in</em>), a layout must be declared before any use of the
method <strong>length</strong>() or other any array use that requires the array size to be
known.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error if a layout declaration&#8217;s array size (from the
table above) does not match all the explicit array sizes specified in
declarations of an input variables in the same shader.
The following includes examples of compile-time errors:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// code sequence within one shader...</span>
in vec4 Color1[]; <span class="comment">// legal, size still unknown</span>
in vec4 Color2[<span class="integer">2</span>]; <span class="comment">// legal, size is 2</span>
in vec4 Color3[<span class="integer">3</span>]; <span class="comment">// illegal, input sizes are inconsistent</span>
layout(lines) in; <span class="comment">// legal for Color2, input size is 2, matching Color2</span>
in vec4 Color4[<span class="integer">3</span>]; <span class="comment">// illegal, contradicts layout of lines</span>
layout(lines) in; <span class="comment">// legal, matches other layout() declaration</span>
layout(triangles) in; <span class="comment">// illegal, does not match earlier layout() declaration</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>It is a link-time error if not all provided sizes (sized input arrays and
layout size) match across all geometry shaders in a program.</p>
</div>
</div>
<div class="sect4">
<h5 id="fragment-shader-inputs">Fragment Shader Inputs</h5>
<div class="paragraph">
<p>Additional fragment layout qualifier identifiers include the following for
<em>gl_FragCoord</em> :</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>origin_upper_left</strong><br>
<strong>pixel_center_integer</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>By default, <em>gl_FragCoord</em> in OpenGL assumes a lower-left origin for window
coordinates and assumes pixel centers are located at half-pixel coordinates.
For example, the (<em>x, y</em>) location (0.5, 0.5) is returned for the
lower-left-most pixel in a window.
The origin can be changed by redeclaring <em>gl_FragCoord</em> with the
<strong>origin_upper_left</strong> qualifier, moving the origin of <em>gl_FragCoord</em> to the
upper left of the window, with <em>y</em> increasing in value toward the bottom of
the window.
The values returned can also be shifted by half a pixel in both <em>x</em> and <em>y</em>
by <strong>pixel_center_integer</strong> so it appears the pixels are centered at whole
number pixel offsets.
This moves the (<em>x</em>, <em>y</em>) value returned by <em>gl_FragCoord</em> of (0.5, 0.5) by
default, to (0.0, 0.0) with <strong>pixel_center_integer</strong>.</p>
</div>
<div class="paragraph">
<p>Targeting Vulkan will assume and require an upper-left origin for <em>gl_FragCoord</em>
with pixel centers located at half-pixel coordinates.
This origin can be explicitly set by redeclaring <em>gl_FragCoord</em> with the
<strong>origin_upper_left</strong> identifier.</p>
</div>
<div class="paragraph">
<p>Redeclarations are done as follows</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_FragCoord; <span class="comment">// redeclaration that changes nothing is allowed</span>
<span class="comment">// All the following are allowed redeclaration that change behavior</span>
layout(origin_upper_left) in vec4 gl_FragCoord;
layout(pixel_center_integer) in vec4 gl_FragCoord;
layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;</code></pre>
</div>
</div>
<div class="paragraph">
<p>If <em>gl_FragCoord</em> is redeclared in any fragment shader in a program, it must
be redeclared in all the fragment shaders in that program that have a static
use <em>gl_FragCoord</em>.
All redeclarations of <em>gl_FragCoord in all fragment shaders in a single
program must have the same set of qualifiers.
Within any shader, the first redeclarations of _glFragCoord</em> must appear
before any use of <em>gl_FragCoord</em>.
The built-in <em>gl_FragCoord</em> is only predeclared in fragment shaders, so
redeclaring it in any other shader language results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>Redeclaring <em>glFragCoord</em> with <strong>origin_upper_left</strong> and/or
<strong>pixel_center_integer</strong> qualifiers only affects <em>gl_FragCoord.x</em> and
<em>gl_FragCoord.y</em>.
It has no effect on rasterization, transformation, or any other part of the
API pipeline or language features.</p>
</div>
<div class="paragraph">
<p>Fragment shaders allow the following layout qualifier on <strong>in</strong> only (not with
variable declarations):</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>early_fragment_tests</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>to request that fragment tests be performed before fragment shader
execution, as described in section 15.2.4 &#8220;Early Fragment Tests&#8221; of the
<a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(early_fragment_tests) in;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Specifying this will make per-fragment tests be performed before fragment
shader execution.
If this is not declared, per-fragment tests will be performed after fragment
shader execution.
Only one fragment shader (compilation unit) need declare this, though more
than one can.
If at least one declares this, then it is enabled.</p>
</div>
</div>
<div class="sect4">
<h5 id="compute-shader-inputs">Compute Shader Inputs</h5>
<div class="paragraph">
<p>There are no layout location qualifiers for compute shader inputs.</p>
</div>
<div class="paragraph">
<p>Layout qualifier identifiers for compute shader inputs are the workgroup
size qualifiers:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>local_size_x</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>local_size_y</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>local_size_z</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong> qualifiers are used
to declare a fixed workgroup size by the compute shader in the first,
second, and third dimension, respectively.
If a shader does not specify a size for one of the dimensions, that
dimension will have a size of 1.</p>
</div>
<div class="paragraph">
<p>For example, the following declaration in a compute shader</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">32</span>, local_size_y = <span class="integer">32</span>) in;</code></pre>
</div>
</div>
<div class="paragraph">
<p>is used to declare a two-dimensional compute shader with a workgroup size of 32
X 32 elements, which is equivalent to a three-dimensional compute shader
where the third dimension has size one.</p>
</div>
<div class="paragraph">
<p>As another example, the declaration</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">8</span>) in;</code></pre>
</div>
</div>
<div class="paragraph">
<p>effectively specifies that a one-dimensional compute shader is being
compiled, and its size is 8 elements.</p>
</div>
<div class="paragraph">
<p>If the fixed workgroup size of the shader in any dimension is less than
or equal to zero or greater than the maximum size supported by the
implementation for that dimension, a compile-time error results.
Also, if such a layout qualifier is declared more than once in the same
shader, all those declarations must set the same set of workgroup
sizes and set them to the same values; otherwise a compile-time error
results.
If multiple compute shaders attached to a single program object declare a
fixed workgroup size, the declarations must be identical; otherwise a
link-time error results.</p>
</div>
<div class="paragraph">
<p>Furthermore, if a program object contains any compute shaders, at least one
must contain an input layout qualifier specifying a fixed workgroup size
for the program, or a link-time error will occur.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="output-layout-qualifiers">4.4.2. Output Layout Qualifiers</h4>
<div class="paragraph">
<p>Some output layout qualifiers apply to all shader stages and some apply only
to specific stages.
The latter are discussed in separate sections below.</p>
</div>
<div class="paragraph">
<p>As with input layout qualifiers, all shaders except compute shaders allow
<strong>location</strong> layout qualifiers on output variable declarations, output block
declarations, and output block member declarations.
Of these, variables and block members (but not blocks) additionally allow
the <strong>component</strong> layout qualifier.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>component</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The usage and rules for applying the <strong>location</strong> qualifier
and the <strong>component</strong> qualifier
to blocks and structures are exactly as described in
&#8220;<a href="#input-layout-qualifiers">Input Layout Qualifiers</a>&#8221;.
Additionally, for fragment shader outputs, if two variables are placed
within the same location, they must have the same underlying type
(floating-point or integer).
No component aliasing of output variables or members is allowed.</p>
</div>
<div class="paragraph">
<p>Fragment shaders allow an additional <strong>index</strong> output layout qualifier:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>index</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Each of these qualifiers may appear at most once.
If <strong>index</strong> is specified, <strong>location</strong> must also be specified.
If <strong>index</strong> is not specified, the value 0 is used.
For example, in a fragment shader,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) out vec4 color;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the fragment shader output <em>color</em> is assigned to
fragment color 3 as the first (index zero) input to the blend equation.
And,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>, index = <span class="integer">1</span>) out vec4 factor;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the fragment shader output <em>factor</em> is assigned to
fragment color 3 as the second (index one) input to the blend equation.</p>
</div>
<div class="paragraph">
<p>For fragment shader outputs, the location
and index specify
the color output number
and index
receiving the values of the output.
For outputs of all other shader stages, the location specifies a vector
number that can be used to match against inputs in a subsequent shader
stage, even if that shader is in a different program object.</p>
</div>
<div class="paragraph">
<p>If a declared output is a scalar or vector type other than <strong>dvec3</strong> or
<strong>dvec4</strong>, it will consume a single location.
Outputs of type <strong>dvec3</strong> or <strong>dvec4</strong> will consume two consecutive locations.
Outputs of type <strong>double</strong> and <strong>dvec2</strong> will consume only a single location, in
all stages.</p>
</div>
<div class="paragraph">
<p>If the declared output is an array, it will be assigned consecutive
locations starting with the location specified.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">2</span>) out vec4 colors[<span class="integer">3</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that <em>colors</em> is assigned to vector location numbers 2, 3,
and 4.</p>
</div>
<div class="paragraph">
<p>If the declared output is an <em>n</em> × <em>m</em>
matrix, it will be assigned multiple locations starting with the location
specified.
The number of locations assigned will be the same as for an <em>n</em>-element
array of <em>m</em>-component vectors.</p>
</div>
<div class="paragraph">
<p>If the declared output is a structure, its members will be assigned
consecutive locations in the order of declaration, with the first member
assigned the location specified for the structure.
The number of locations consumed by a structure member is determined by
applying the rules above recursively as though the structure member were
declared as an output variable of the same type.</p>
</div>
<div class="paragraph">
<p><strong>location</strong> layout qualifiers may be used on output variables declared as
structures.
However, it is a compile-time error to use a <strong>location</strong> qualifier on a
structure member.
Location layout qualifiers may be used on output blocks and output block
members.</p>
</div>
<div class="paragraph">
<p>The number of output locations available to a shader is limited.
For fragment shaders, the limit is the advertised number of draw buffers.</p>
</div>
<div class="paragraph">
<p>For all other shaders, the limit is implementation-dependent and must be no
less than one fourth of the advertised maximum output component count
(compute shaders have no outputs).
A program will fail to link if any attached shader uses a location greater
than or equal to the number of supported locations, unless device-dependent
optimizations are able to make the program fit within available hardware
resources.</p>
</div>
<div class="paragraph">
<p>Compile-time errors may also be given if at compile time it is known the
link will fail.
A negative output location will result in a compile-time error.
It is also a compile-time error if a fragment shader sets a layout index to
less than 0 or greater than 1.</p>
</div>
<div class="paragraph">
<p>It is a compile-time or link-time error if any of the following occur:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>any two fragment shader output variables are assigned to the same
location and index.</p>
</li>
<li>
<p>if any two output variables from the same vertex, tessellation or
geometry shader stage are assigned to the same location.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For fragment shader outputs, locations can be assigned using either a
<strong>layout</strong> qualifier or via the OpenGL API.</p>
</div>
<div class="paragraph">
<p>For all shader types, a program will fail to link if explicit location
assignments leave the linker unable to find space for other variables
without explicit assignments.</p>
</div>
<div class="paragraph">
<p>If an output variable with no location or index assigned in the shader text
has a location specified through the OpenGL API, the API-assigned
location will be used.
Otherwise, such variables will be assigned a location by the linker.
All such assignments will have a color index of zero.
See section 15.2 &#8220;Shader Execution&#8221; of the <a href="#references">OpenGL Specification</a> for
more details.
A link-time error will occur if an output variable is declared in multiple
shaders of the same language with conflicting location or index values.</p>
</div>
<div class="paragraph">
<p>For the purposes of determining if a non-fragment output matches an input
from a subsequent shader stage, the <strong>location</strong> layout qualifier (if any)
must match.</p>
</div>
<div class="sect4">
<h5 id="transform-feedback-layout-qualifiers">Transform Feedback Layout Qualifiers</h5>
<div class="paragraph">
<p>The vertex, tessellation, and geometry stages allow shaders to control
transform feedback.
When doing this, shaders will dictate which transform feedback buffers are
in use, which output variables will be written to which buffers, and how
each buffer is laid out.
To accomplish this, shaders allow the following layout qualifier identifiers
on output declarations:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>xfb_buffer</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>xfb_offset</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>xfb_stride</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Any shader making any static use (after preprocessing) of any of these
<strong>xfb_</strong> qualifiers will cause the shader to be in a transform feedback
capturing mode and hence responsible for describing the transform feedback
setup.
This mode will capture any output selected by <strong>xfb_offset</strong>, directly or
indirectly, to a transform feedback buffer.</p>
</div>
<div class="paragraph">
<p>The <strong>xfb_buffer</strong> qualifier specifies which transform feedback buffer will
capture outputs selected with <strong>xfb_offset</strong>.
The <strong>xfb_buffer</strong> qualifier can be applied to the qualifier <strong>out</strong>, to output
variables, to output blocks, and to output block members.
Shaders in the transform feedback capturing mode have an initial global
default of</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(xfb_buffer = <span class="integer">0</span>) out;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This default can be changed by declaring a different buffer with
<strong>xfb_buffer</strong> on the interface qualifier <strong>out</strong>.
This is the only way the global default can be changed.
When a variable or output block is declared without an <strong>xfb_buffer</strong>
qualifier, it inherits the global default buffer.
When a variable or output block is declared with an <strong>xfb_buffer</strong> qualifier,
it has that declared buffer.
All members of a block inherit the block&#8217;s buffer.
A member is allowed to declare an <strong>xfb_buffer</strong>, but it must match the buffer
inherited from its block, or a compile-time error results.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(xfb_buffer=<span class="integer">2</span>, xfb_offset=<span class="integer">0</span>) out block { <span class="comment">// block's buffer is 2</span>
layout(xfb_buffer = <span class="integer">2</span>) vec4 v; <span class="comment">// okay, matches the inherited 2</span>
layout(xfb_buffer = <span class="integer">3</span>) vec4 u; <span class="comment">// ERROR, mismatched buffer</span>
vec4 w; <span class="comment">// inherited</span>
};
layout(xfb_offset=<span class="integer">16</span>) out vec4 t; <span class="comment">// initial default is buffer 0</span>
layout(xfb_buffer=<span class="integer">1</span>) out; <span class="comment">// new global default of 1</span>
out block { <span class="comment">// block has buffer 1</span>
vec4 x; <span class="comment">// x has buffer 1 (not captured)</span>
layout(xfb_buffer = <span class="integer">1</span>) vec4 y; <span class="comment">// okay (not captured)</span>
layout(xfb_buffer = <span class="integer">0</span>) vec4 z; <span class="comment">// ERROR, mismatched buffer</span>
};
layout(xfb_offset=<span class="integer">0</span>) out vec4 g; <span class="comment">// g has buffer 1</span>
layout(xfb_buffer=<span class="integer">2</span>) out vec4 h; <span class="comment">// does not change global default</span>
layout(xfb_offset=<span class="integer">16</span>) out vec4 j; <span class="comment">// j has buffer 1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note this means all members of a block that go to a transform feedback
buffer will go to the same buffer.</p>
</div>
<div class="paragraph">
<p>When a block is declared as an array, all members of block array-element 0
are captured, as previously described, by the declared or inherited
<strong>xfb_buffer</strong>.
Generally, an array of size <em>N</em> of blocks is captured by <em>N</em> consecutive
buffers, with all members of block array-element <em>E</em> captured by buffer <em>B</em>,
where <em>B</em> equals the declared or inherited <strong>xfb_buffer</strong> plus <em>E</em>.</p>
</div>
<div class="paragraph">
<p>It is a compile-time or link-time error to specify an <strong>xfb_buffer</strong>,
including any additional buffers needed to capture an arrays of blocks, that
is less than zero or greater than or equal to the implementation-dependent
constant <em>gl_MaxTransformFeedbackBuffers</em>.</p>
</div>
<div class="paragraph">
<p>The <strong>xfb_offset</strong> qualifier assigns a byte offset within a transform feedback
buffer.
Only variables, block members, or blocks can be qualified with <strong>xfb_offset</strong>.
If a block is qualified with <strong>xfb_offset</strong>, all its members are assigned
transform feedback buffer offsets.
If a block is not qualified with <strong>xfb_offset</strong>, any members of that block not
qualified with an <strong>xfb_offset</strong> will not be assigned transform feedback
buffer offsets.
Only variables and block members that are assigned offsets will be captured
(thus, a proper subset of a block can be captured).
Each time such a variable or block member is written in a shader, the
written value is captured at the assigned offset.
If such a block member or variable is not written during a shader
invocation, the buffer contents at the assigned offset will be undefined.
Even if there are no static writes to a variable or member that is assigned
a transform feedback offset, the space is still allocated in the buffer and
still affects the stride.</p>
</div>
<div class="paragraph">
<p>Variables and block members qualified with <strong>xfb_offset</strong> can be scalars,
vectors, matrices, structures, and (sized) arrays of these.
The offset must be a multiple of the size of the first component of the
first qualified variable or block member, or a compile-time error results.
Further, if applied to an aggregate containing a <strong>double</strong>, the offset must
also be a multiple of 8, and the space taken in the buffer will be a
multiple of 8.
The given offset applies to the first component of the first member of the
qualified entity.
Then, within the qualified entity, subsequent components are each assigned,
in order, to the next available offset aligned to a multiple of that
component&#8217;s size.
Aggregate types are flattened down to the component level to get this
sequence of components.
It is a compile-time error to apply <strong>xfb_offset</strong> to the declaration of an
unsized array.</p>
</div>
<div class="paragraph">
<p>No aliasing in output buffers is allowed: It is a compile-time or link-time
error to specify variables with overlapping transform feedback offsets.</p>
</div>
<div class="paragraph">
<p>The <strong>xfb_stride</strong> qualifier specifies how many bytes are consumed by each
captured vertex.
It applies to the transform feedback buffer for that declaration, whether it
is inherited or explicitly declared.
It can be applied to variables, blocks, block members, or just the qualifier
<strong>out</strong>.
If the buffer is capturing any outputs with double-precision components, the
stride must be a multiple of 8, otherwise it must be a multiple of 4, or a
compile-time or link-time error results.
It is a compile-time or link-time error to have any <strong>xfb_offset</strong> that
overflows <strong>xfb_stride</strong>, whether stated on declarations before or after the
<strong>xfb_stride</strong>, or in different compilation units.
While <strong>xfb_stride</strong> can be declared multiple times for the same buffer, it is
a compile-time or link-time error to have different values specified for the
stride for the same buffer.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// buffer 1 has 32-byte stride</span>
layout(xfb_buffer = <span class="integer">1</span>, xfb_stride = <span class="integer">32</span>) out;
<span class="comment">// same as previous example; order within layout does not matter</span>
layout(xfb_stride = <span class="integer">32</span>, xfb_buffer = <span class="integer">1</span>) out;
<span class="comment">// everything in this block goes to buffer 0</span>
layout(xfb_buffer = <span class="integer">0</span>, xfb_stride = <span class="integer">32</span>) out block1 {
layout(xfb_offset = <span class="integer">0</span>) vec4 a; <span class="comment">// a goes to byte offset 0 of buffer 0</span>
layout(xfb_offset = <span class="integer">16</span>) vec4 b; <span class="comment">// b goes to offset 16 of buffer 0</span>
};
layout(xfb_buffer = <span class="integer">3</span>, xfb_offset = <span class="integer">12</span>) out block2 {
vec4 v; <span class="comment">// v will be written to byte offsets 12 through 27 of buffer</span>
<span class="predefined-type">float</span> u; <span class="comment">// u will be written to offset 28</span>
layout(xfb_offset = <span class="integer">40</span>) vec4 w;
vec4 x; <span class="comment">// x will be written to offset 56, the next available offset</span>
};
layout(xfb_buffer = <span class="integer">2</span>, xfb_stride = <span class="integer">32</span>) out block3 {
layout(xfb_offset = <span class="integer">12</span>) vec3 c;
layout(xfb_offset = <span class="integer">24</span>) vec3 d; <span class="comment">// ERROR, requires stride of 36</span>
layout(xfb_offset = <span class="integer">0</span>) vec3 g; <span class="comment">// okay, increasing order not required</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>When no <strong>xfb_stride</strong> is specified for a buffer, the stride of the buffer
will be the smallest needed to hold the variable placed at the highest
offset, including any required padding.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// if there no other declarations for buffer 3, it has stride 32</span>
layout(xfb_buffer = <span class="integer">3</span>) out block4 {
layout(xfb_offset = <span class="integer">0</span>) vec4 e;
layout(xfb_offset = <span class="integer">16</span>) vec4 f;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The resulting stride (implicit or explicit), when divided by 4, must be less
than or equal to the implementation-dependent constant
<em>gl_MaxTransformFeedbackInterleavedComponents</em>.</p>
</div>
</div>
<div class="sect4">
<h5 id="tessellation-control-outputs">Tessellation Control Outputs</h5>
<div class="paragraph">
<p>Other than for the transform feedback layout qualifiers, tessellation
control shaders allow output layout qualifiers only on the interface
qualifier <strong>out</strong>, not on an output block, block member, or variable
declaration.
The output layout qualifier identifiers allowed for tessellation control
shaders are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>vertices</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The identifier <strong>vertices</strong> specifies the number of vertices in the output
patch produced by the tessellation control shader, which also specifies the
number of times the tessellation control shader is invoked.
It is a compile- or link-time error for the output vertex count to be less
than or equal to zero, or greater than the implementation-dependent maximum
patch size.</p>
</div>
<div class="paragraph">
<p>The intrinsically declared tessellation control output array <em>gl_out[]</em> will
also be sized by any output layout declaration.
Hence, the expression</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_out.length()</code></pre>
</div>
</div>
<div class="paragraph">
<p>will return the output patch vertex count specified in a previous output
layout qualifier.
For outputs declared without an array size, including intrinsically declared
outputs (i.e., <em>gl_out</em>), a layout must be declared before any use of the
method <strong>length</strong>() or other array use that requires its size to be known.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error if the output patch vertex count specified in an
output layout qualifier does not match the array size specified in any
output variable declaration in the same shader.</p>
</div>
<div class="paragraph">
<p>All tessellation control shader layout declarations in a program must
specify the same output patch vertex count.
There must be at least one layout qualifier specifying an output patch
vertex count in any program containing tessellation control shaders;
however, such a declaration is not required in all tessellation control
shaders.</p>
</div>
</div>
<div class="sect4">
<h5 id="geometry-outputs">Geometry Outputs</h5>
<div class="paragraph">
<p>Geometry shaders can have three additional types of output layout
identifiers: an output <em>primitive type</em>, a maximum output <em>vertex count</em>,
and per-output <em>stream</em> numbers.
The primitive type and vertex count identifiers are allowed only on the
interface qualifier <strong>out</strong>, not on an output block, block member, or variable
declaration.
The stream identifier is allowed on the interface qualifier <strong>out</strong>, on output
blocks, and on variable declarations.</p>
</div>
<div class="paragraph">
<p>The layout qualifier identifiers for geometry shader outputs are</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>points</strong><br>
<strong>line_strip</strong><br>
<strong>triangle_strip</strong><br>
<strong>max_vertices</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>stream</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The primitive type identifiers <strong>points</strong>, <strong>line_strip</strong>, and <strong>triangle_strip</strong>
are used to specify the type of output primitive produced by the geometry
shader, and only one of these is accepted.
At least one geometry shader (compilation unit) in a program must declare an
output primitive type, and all geometry shader output primitive type
declarations in a program must declare the same primitive type.
It is not required that all geometry shaders in a program declare an output
primitive type.</p>
</div>
<div class="paragraph">
<p>The vertex count identifier <strong>max_vertices</strong> is used to specify the maximum
number of vertices the shader will ever emit in a single invocation.
At least one geometry shader (compilation unit) in a program must declare a
maximum output vertex count, and all geometry shader output vertex count
declarations in a program must declare the same count.
It is not required that all geometry shaders in a program declare a count.</p>
</div>
<div class="paragraph">
<p>In this example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(triangle_strip, max_vertices = <span class="integer">60</span>) out; <span class="comment">// order does not matter</span>
layout(max_vertices = <span class="integer">60</span>) out; <span class="comment">// redeclaration okay</span>
layout(triangle_strip) out; <span class="comment">// redeclaration okay</span>
layout(points) out; <span class="comment">// error, contradicts triangle_strip</span>
layout(max_vertices = <span class="integer">30</span>) out; <span class="comment">// error, contradicts 60</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>all outputs from the geometry shader are triangles and at most 60 vertices
will be emitted by the shader.
It is an error for the maximum number of vertices to be greater than
<em>gl_MaxGeometryOutputVertices</em>.</p>
</div>
<div class="paragraph">
<p>The identifier <strong>stream</strong> is used to specify that a geometry shader output
variable or block is associated with a particular vertex stream (numbered
beginning with zero).
A default stream number may be declared at global scope by qualifying
interface qualifier <strong>out</strong> as in this example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(stream = <span class="integer">1</span>) out;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The stream number specified in such a declaration replaces any previous
default and applies to all subsequent block and variable declarations until
a new default is established.
The initial default stream number is zero.</p>
</div>
<div class="paragraph">
<p>Each output block or non-block output variable is associated with a vertex
stream.
If the block or variable is declared with the stream identifier, it is
associated with the specified stream; otherwise, it is associated with the
current default stream.
A block member may be declared with a stream identifier, but the specified
stream must match the stream associated with the containing block.
One example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(stream=<span class="integer">1</span>) out; <span class="comment">// default is now stream 1</span>
out vec4 var1; <span class="comment">// var1 gets default stream (1)</span>
layout(stream=<span class="integer">2</span>) out Block1 { <span class="comment">// &quot;Block1&quot; belongs to stream 2</span>
layout(stream=<span class="integer">2</span>) vec4 var2; <span class="comment">// redundant block member stream decl</span>
layout(stream=<span class="integer">3</span>) vec2 var3; <span class="comment">// ILLEGAL (must match block stream)</span>
vec3 var4; <span class="comment">// belongs to stream 2</span>
};
layout(stream=<span class="integer">0</span>) out; <span class="comment">// default is now stream 0</span>
out vec4 var5; <span class="comment">// var5 gets default stream (0)</span>
out Block2 { <span class="comment">// &quot;Block2&quot; gets default stream (0)</span>
vec4 var6;
};
layout(stream=<span class="integer">3</span>) out vec4 var7; <span class="comment">// var7 belongs to stream 3</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Each vertex emitted by the geometry shader is assigned to a specific stream,
and the attributes of the emitted vertex are taken from the set of output
blocks and variables assigned to the targeted stream.
After each vertex is emitted, the values of all output variables become
undefined.
Additionally, the output variables associated with each vertex stream may
share storage.
Writing to an output variable associated with one stream may overwrite
output variables associated with any other stream.
When emitting each vertex, a geometry shader should write to all outputs
associated with the stream to which the vertex will be emitted and to no
outputs associated with any other stream.</p>
</div>
<div class="paragraph">
<p>If a geometry shader output block or variable is declared more than once,
all such declarations must associate the variable with the same vertex
stream.
If any stream declaration specifies a non-existent stream number, the shader
will fail to compile.</p>
</div>
<div class="paragraph">
<p>Built-in geometry shader outputs are always associated with vertex stream
zero.</p>
</div>
<div class="paragraph">
<p>All geometry shader output layout declarations in a program must declare the
same layout and same value for <strong>max_vertices</strong>.
If geometry shaders are in a program, there must be at least one geometry
output layout declaration somewhere in that
program, but not all geometry
shaders (compilation units) are required to declare it.</p>
</div>
</div>
<div class="sect4">
<h5 id="fragment-outputs">Fragment Outputs</h5>
<div class="paragraph">
<p>The built-in fragment shader variable <em>gl_FragDepth</em> may be redeclared using
one of the following layout qualifiers.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>depth_any</strong><br>
<strong>depth_greater</strong><br>
<strong>depth_less</strong><br>
<strong>depth_unchanged</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The layout qualifier for <em>gl_FragDepth</em> constrains intentions of the final
value of <em>gl_FragDepth</em> written by any shader invocation.
GL implementations are allowed to perform optimizations assuming that the
depth test fails (or passes) for a given fragment if all values of
<em>gl_FragDepth</em> consistent with the layout qualifier would fail (or pass).
This potentially includes skipping shader execution if the fragment is
discarded because it is occluded and the shader has no side effects.
If the final value of <em>gl_FragDepth</em> is inconsistent with its layout
qualifier, the result of the depth test for the corresponding fragment is
undefined.
However, no error will be generated in this case.
If the depth test passes and depth writes are enabled, the value written to
the depth buffer is always the value of <em>gl_FragDepth</em>, whether or not it is
consistent with the layout qualifier.</p>
</div>
<div class="paragraph">
<p>By default, <em>gl_FragDepth</em> is qualified as <em>depth_any</em>.
When the layout qualifier for <em>gl_FragDepth</em> is <em>depth_any</em>, the shader
compiler will note any assignment to <em>gl_FragDepth</em> modifying it in an
unknown way, and depth testing will always be performed after the shader has
executed.
When the layout qualifier is <em>depth_greater</em>, the GL can assume that the
final value of <em>gl_FragDepth</em> is greater than or equal to the fragment&#8217;s
interpolated depth value, as given by the <em>z</em> component of <em>gl_FragCoord</em>.
When the layout qualifier is <em>depth_less</em>, the GL can assume that any
modification of <em>gl_FragDepth</em> will only decrease its value.
When the layout qualifier is <em>depth_unchanged</em>, the shader compiler will
honor any modification to <em>gl_FragDepth</em>, but the rest of the GL can assume
that <em>gl_FragDepth</em> is not assigned a new value.</p>
</div>
<div class="paragraph">
<p>Redeclarations of <em>gl_FragDepth</em> are performed as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// redeclaration that changes nothing is allowed +</span>
out <span class="predefined-type">float</span> gl_FragDepth;
<span class="comment">// assume it may be modified in any way</span>
layout(depth_any) out <span class="predefined-type">float</span> gl_FragDepth;
<span class="comment">// assume it may be modified such that its value will only increase</span>
layout(depth_greater) out <span class="predefined-type">float</span> gl_FragDepth;
<span class="comment">// assume it may be modified such that its value will only decrease</span>
layout(depth_less) out <span class="predefined-type">float</span> gl_FragDepth;
<span class="comment">// assume it will not be modified</span>
layout(depth_unchanged) out <span class="predefined-type">float</span> gl_FragDepth;</code></pre>
</div>
</div>
<div class="paragraph">
<p>If <em>gl_FragDepth</em> is redeclared in any fragment shader in a program, it must
be redeclared in all fragment shaders in that program that have static
assignments to <em>gl_FragDepth</em>.
All redeclarations of <em>gl_FragDepth</em> in all fragment shaders in a single
program must have the same set of qualifiers.
Within any shader, the first redeclarations of <em>gl_FragDepth</em> must appear
before any use of <em>gl_FragDepth</em>.
The built-in <em>gl_FragDepth</em> is only predeclared in fragment shaders, so
redeclaring it in any other shader language results in a compile-time error.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="uniform-variable-layout-qualifiers">4.4.3. Uniform Variable Layout Qualifiers</h4>
<div class="paragraph">
<p>Layout qualifiers can be used for uniform variables and subroutine uniforms.
The layout qualifier identifiers for uniform variables and subroutine
uniforms are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The location identifier can be used with default-block uniform variables and
subroutine uniforms.
The location specifies the location by which the API can reference
the uniform and update its value.
Individual elements of a uniform array are assigned consecutive locations
with the first element taking location <strong>location</strong>.
Default-block uniform variable declarations sharing the same location
linked in the program have to match by name, type, qualifiers and arrayness.
For arrays their array dimensionality and array sizes must match.
For structs this rule applies recursively to all members.
No two subroutine uniform variables can have the same location in the same
shader stage, otherwise a compile-time or link-time error will be generated.
Valid locations for default-block uniform variable locations are in the
range of 0 to the implementation-defined maximum number of uniform locations
minus one.
Valid locations for subroutine uniforms are in the range of 0 to the
implementation-defined per-stage maximum number of subroutine uniform
locations minus one.</p>
</div>
<div class="paragraph">
<p>Locations can be assigned to default-block uniform arrays and structures.
The first inner-most scalar, vector or matrix member or element takes the
specified <strong>location</strong> and the compiler assigns the next inner-most member or
element the next incremental location value.
Each subsequent inner-most member or element gets incremental locations for
the entire structure or array.
This rule applies to nested structures and arrays and gives each inner-most
scalar, vector, or matrix member a unique location.
For arrays without an explicit size, the size is calculated based on its
static usage.
When the linker generates locations for uniforms without an explicit
location, it assumes for all uniforms with an explicit location all their
array elements and structure members are used and the linker will not
generate a conflicting location, even if that element or member is deemed
unused.</p>
</div>
<div class="paragraph">
<p>When generating SPIR-V for API&#8217;s that accept individual (default block)
non-opaque uniform variables, it is a compile-time error to not
include a location when declaring them.</p>
</div>
<div class="paragraph">
<p>When targeting Vulkan, the <strong>push_constant</strong> qualifier is used to
declare an entire block, and represents a set of <em>push constants</em>, as defined
by the Vulkan API.
It is a compile-time error to apply this to anything other than a uniform block
declaration, or when not targeting Vulkan.
The values in the block will be initialized as per the Vulkan API specification.
A block declared with <code>layout(push_constant)</code> may optionally include an
<em>instance-name</em>.
There can be only one <strong>push_constant</strong> block per stage, or a compile-time or
link-time error will result.
A push-constant array can only be indexed with dynamically uniform indices.
Uniform blocks declared with <strong>push_constant</strong> use different resources
than those without; and are accounted for separately.</p>
</div>
</div>
<div class="sect3">
<h4 id="subroutine-function-layout-qualifiers">4.4.4. Subroutine Function Layout Qualifiers</h4>
<div class="paragraph">
<p>Layout qualifiers can be used for subroutine functions.
The layout qualifier identifiers for subroutine functions are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>index</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Each subroutine with an index qualifier in the shader must be given a unique
index, otherwise a compile- or link-time error will be generated.
The indices must be in the range of 0 to the implementation defined maximum
number of subroutines minus one.
It is recommended, but not required, that the shader assigns a range of
tightly packed <em>index</em> values starting from zero so that the OpenGL
subroutine function enumeration API returns a non-empty name for all active
indices.</p>
</div>
</div>
<div class="sect3">
<h4 id="uniform-and-shader-storage-block-layout-qualifiers">4.4.5. Uniform and Shader Storage Block Layout Qualifiers</h4>
<div class="paragraph">
<p>Layout qualifiers can be used for uniform and shader storage blocks, but not
for non-block uniform declarations.
The layout qualifier identifiers (and <strong>shared</strong> keyword) for uniform and
shader storage blocks are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>shared</strong><br>
<strong>packed</strong><br>
<strong>std140</strong><br>
<strong>std430</strong><br>
<strong>row_major</strong><br>
<strong>column_major</strong><br>
<strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>offset</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>align</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>None of these have any semantic effect at all on the usage of the variables
being declared; they only describe how data is laid out in memory.
For example, matrix semantics are always column-based, as described in the
rest of this specification, no matter what layout qualifiers are being used.</p>
</div>
<div class="paragraph">
<p>Uniform and shader storage block layout qualifiers can be declared for
global scope, on a single uniform or shader storage block, or on a single
block member declaration.</p>
</div>
<div class="paragraph">
<p>Default layouts are established at global scope for uniform blocks as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(layout-qualifier-id-list) uniform;</code></pre>
</div>
</div>
<div class="paragraph">
<p>and for shader storage blocks as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(layout-qualifier-id-list) buffer;</code></pre>
</div>
</div>
<div class="paragraph">
<p>When this is done, the previous default qualification is first inherited and
then overridden as per the override rules listed below for each qualifier
listed in the declaration.
The result becomes the new default qualification scoped to subsequent
uniform or shader storage block definitions.</p>
</div>
<div class="paragraph">
<p>The initial state of compilation when generating SPIR-V is as if the
following were declared:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(std140, column_major) uniform;
layout(std430, column_major) buffer;</code></pre>
</div>
</div>
<div class="paragraph">
<p>However, when <strong>push_constant</strong> is declared, the default layout of the
buffer will be <strong>std430</strong>. There is no method to globally set this default.</p>
</div>
<div class="paragraph">
<p>The initial state of compilation when not generating SPIR-V is as if the
following were declared:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(shared, column_major) uniform;
layout(shared, column_major) buffer;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Uniform and shader storage blocks can be declared with optional layout
qualifiers, and so can their individual member declarations.
Such block layout qualification is scoped only to the content of the block.
As with global layout declarations, block layout qualification first
inherits from the current default qualification and then overrides it.
Similarly, individual member layout qualification is scoped just to the
member declaration, and inherits from and overrides the block&#8217;s
qualification.</p>
</div>
<div class="paragraph">
<p>The <strong>shared</strong> qualifier overrides only the <strong>std140</strong>, <strong>std430</strong>, and <strong>packed</strong>
qualifiers; other qualifiers are inherited.
The compiler/linker will ensure that multiple programs and programmable
stages containing this definition will share the same memory layout for this
block, as long as all arrays are declared with explicit sizes and all
matrices have matching <strong>row_major</strong> and/or <strong>column_major</strong> qualifications
(which may come from a declaration outside the block definition).
This allows use of the same buffer to back the same block definition across
different programs.
It is a compile-time error to use the <strong>shared</strong> qualifier when generating
SPIR-V.</p>
</div>
<div class="paragraph">
<p>The <strong>packed</strong> qualifier overrides only <strong>std140</strong>, <strong>std430</strong>, and <strong>shared</strong>;
other qualifiers are inherited.
When <strong>packed</strong> is used, no shareable layout is guaranteed.
The compiler and linker can optimize memory use based on what variables
actively get used and on other criteria.
Offsets must be queried, as there is no other way of guaranteeing where (and
which) variables reside within the block.</p>
</div>
<div class="paragraph">
<p>It is a link-time error to access the same packed uniform or shader storage
block in multiple stages within a program.
Attempts to access the same packed uniform or shader storage block across
programs can result in conflicting member offsets and in undefined values
being read.
However, implementations may aid application management of packed blocks by
using canonical layouts for packed blocks.
It is a compile-time error to use the <strong>packed</strong> qualifier when generating
SPIR-V.</p>
</div>
<div class="paragraph">
<p>The <strong>std140</strong> and <strong>std430</strong> qualifiers override only the <strong>packed</strong>, <strong>shared</strong>,
<strong>std140</strong>, and <strong>std430</strong> qualifiers; other qualifiers are inherited.
The <strong>std430</strong> qualifier is supported only for shader storage blocks; a shader
using the <strong>std430</strong> qualifier on a uniform block will result in
a compile-time error, unless it is also declared with <strong>push_constant</strong>.</p>
</div>
<div class="paragraph">
<p>The layout is explicitly determined by this, as described in section 7.6.2.2
&#8220;Standard Uniform Block Layout&#8221; of the <a href="#references">OpenGL Specification</a>.
Hence, as in <strong>shared</strong> above, the resulting layout is shareable across
programs.</p>
</div>
<div class="paragraph">
<p>Layout qualifiers on member declarations cannot use the <strong>shared</strong>, <strong>packed</strong>,
<strong>std140</strong>, or <strong>std430</strong> qualifiers.
These can only be used at global scope (without an object) or on a block
declaration, or a compile-time error results.</p>
</div>
<div class="paragraph">
<p>The <strong>row_major</strong> and <strong>column_major</strong> qualifiers only affect the layout of
matrices, including all matrices contained in structures and arrays they are
applied to, to all depths of nesting.
These qualifiers can be applied to other types, but will have no effect.</p>
</div>
<div class="paragraph">
<p>The <strong>row_major</strong> qualifier overrides only the <strong>column_major</strong> qualifier; other
qualifiers are inherited.
Elements within a matrix row will be contiguous in memory.</p>
</div>
<div class="paragraph">
<p>The <strong>column_major</strong> qualifier overrides only the <strong>row_major</strong> qualifier; other
qualifiers are inherited.
Elements within a matrix column will be contiguous in memory.</p>
</div>
<div class="paragraph">
<p>The <strong>binding</strong> qualifier specifies the uniform buffer binding point
corresponding to the uniform or shader storage block, which will be used to
obtain the values of the member variables of the block.
It is a compile-time error to specify the <strong>binding</strong> qualifier for the global
scope or for block member declarations.
Any uniform or shader storage block declared without a <strong>binding</strong> qualifier
is initially assigned to block binding point zero.
After a program is linked, the binding points used for uniform
and shader storage blocks
declared with or without a <strong>binding</strong> qualifier can be updated
by the API.</p>
</div>
<div class="paragraph">
<p>When used with OpenGL,
if the <strong>binding</strong> qualifier is used with a uniform block or shader storage
block instanced as an array, the first element of the array takes the
specified block binding and each subsequent element takes the next
consecutive binding point.
For an array of arrays, each element (e.g. 6 elements for a[2][3]) gets a
binding point, and they are ordered per the array of array ordering
described in &#8220;<a href="#arrays">Arrays.</a>&#8221;</p>
</div>
<div class="paragraph">
<p>When targeting Vulkan,
if the <strong>binding</strong> qualifier is used with a uniform block or buffer block
instanced as an array, the entire array takes only the provided binding
number.
The next consecutive binding number is available for a different
object.
For an array of arrays, descriptor set array element numbers used
in descriptor set accesses are ordered per the array-of-array ordering
described in &#8220;<a href="#arrays">Arrays.</a>&#8221;</p>
</div>
<div class="paragraph">
<p>If the binding point for any uniform or shader storage block instance is
less than zero, or greater than or equal to the corresponding
implementation-dependent maximum number of buffer bindings, a compile-time
error will occur.
When the <strong>binding</strong> qualifier is used with a uniform or shader storage block
instanced as an array of size <em>N</em>, all elements of the array from <strong>binding</strong>
through <em>binding + N - 1</em> must be within this range.
It is a compile-time or link-time error to use the same binding number for
more than one uniform block or for more than one buffer block.</p>
</div>
<div class="paragraph">
<p>The <strong>set</strong> qualifier is only available when targeting Vulkan.
It specifies the descriptor set this object belongs to.
It is a compile-time error to apply <strong>set</strong> to a standalone qualifier, to
a member of a block, or when not targeting an API that supports descriptor sets.
It is a compile-time error to apply <strong>set</strong> to a block qualified as <strong>push_constant</strong>.
By default, any non-push-constant uniform or shader storage block declared
without a <strong>set</strong> identifier is assigned to descriptor set 0.
Similarly, any sampler, texture, or subpass-input type declared as a uniform
without a <strong>set</strong> identifier is also assigned to descriptor set 0.</p>
</div>
<div class="paragraph">
<p>If applied to an object declared as an array, all elements of the array
belong to the specified <strong>set</strong>.</p>
</div>
<div class="paragraph">
<p>When generating SPIR-V, it is a compile-time error for either the <strong>set</strong> or
<strong>binding</strong> value to exceed a front-end-configuration supplied maximum value.</p>
</div>
<div class="paragraph">
<p>When multiple arguments are listed in a <strong>layout</strong> declaration, the effect
will be the same as if they were declared one at a time, in order from left
to right, each in turn inheriting from and overriding the result from the
previous qualification.</p>
</div>
<div class="paragraph">
<p>For example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(row_major, column_major)</code></pre>
</div>
</div>
<div class="paragraph">
<p>results in the qualification being <strong>column_major</strong>.
Other examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(shared, row_major) uniform; <span class="comment">// default is now shared and row_major</span>
layout(std140) uniform Transform { <span class="comment">// layout of this block is std140</span>
mat4 M1; <span class="comment">// row major</span>
layout(column_major) mat4 M2; <span class="comment">// column major</span>
mat3 N1; <span class="comment">// row major</span>
};
uniform T2 { <span class="comment">// layout of this block is shared</span>
...
};
layout(column_major) uniform T3 { <span class="comment">// shared and column major</span>
mat4 M3; <span class="comment">// column major</span>
layout(row_major) mat4 m4; <span class="comment">// row major</span>
mat3 N2; <span class="comment">// column major</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>When targeting Vulkan, the <strong>offset</strong> and <strong>align</strong> qualifiers for blocks and
block members can only be used with <strong>uniform</strong> and <strong>buffer</strong> blocks.
When not targeting Vulkan, they can only be used with blocks declared with
<strong>std140</strong> or <strong>std430</strong> layouts.</p>
</div>
<div class="paragraph">
<p>The <strong>offset</strong> qualifier can only be used on block members.
The <strong>offset</strong> qualifier forces the qualified member to start at or after the
specified <em>layout-qualifier-value</em>, which will be its byte offset from
the beginning of the buffer.
It is a compile-time error to have any offset, explicit or assigned, that
lies within another member of the block.
When not generating SPIR-V, it is a compile-time error to specify an offset
that is smaller than the offset of the previous member in the block.
Two blocks linked together in the same program with the same block name must
have the exact same set of members qualified with <strong>offset</strong> and their
<em>layout-qualifier-value</em> values must be the same, or a link-time error
results.
The specified offset must be a multiple of the base alignment of the type of
the block member it qualifies, or a compile-time error results.</p>
</div>
<div class="paragraph">
<p>The <strong>align</strong> qualifier makes the start of each block member have a minimum
byte alignment.
It does not affect the internal layout within each member, which will still
follow the <strong>std140</strong> or <strong>std430</strong> rules.
The specified alignment must be greater than 0 and a power of 2, or a
compile-time error results.</p>
</div>
<div class="paragraph">
<p>The <em>actual alignment</em> of a member will be the greater of the specified
<strong>align</strong> alignment and the standard (e.g. <strong>std140</strong>) base alignment for the
member&#8217;s type.
The <em>actual offset</em> of a member is computed as follows: If <strong>offset</strong> was
declared, start with that offset, otherwise start with the offset immediately
following the preceding member (in declaration order).
If the resulting offset is not a multiple of the <em>actual alignment</em>,
increase it to the first offset that is a multiple of the <em>actual
alignment</em>.
This results in the <em>actual offset</em> the member will have.</p>
</div>
<div class="paragraph">
<p>When <strong>align</strong> is applied to an array, it affects only the start of the array,
not the array&#8217;s internal stride.
Both an <strong>offset</strong> and an <strong>align</strong> qualifier can be specified on a declaration.</p>
</div>
<div class="paragraph">
<p>The <strong>align</strong> qualifier, when used on a block, has the same effect as
qualifying each member with the same <strong>align</strong> value as declared on the block,
and gets the same compile-time results and errors as if this had been done.
As described in general earlier, an individual member can specify its own
<strong>align</strong>, which overrides the block-level <strong>align</strong>, but just for that member.</p>
</div>
<div class="paragraph">
<p>Examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(std140) uniform block {
vec4 a; <span class="comment">// a takes offsets 0-15</span>
layout(offset = <span class="integer">32</span>) vec3 b; <span class="comment">// b takes offsets 32-43</span>
layout(offset = <span class="integer">40</span>) vec2 c; <span class="comment">// ERROR, lies within previous member</span>
layout(offset = <span class="integer">48</span>) vec2 d; <span class="comment">// d takes offsets 48-55</span>
layout(align = <span class="integer">16</span>) <span class="predefined-type">float</span> e; <span class="comment">// e takes offsets 64-67</span>
layout(align = <span class="integer">2</span>) <span class="predefined-type">double</span> f; <span class="comment">// f takes offsets 72-79</span>
layout(align = <span class="integer">6</span>) <span class="predefined-type">double</span> g; <span class="comment">// ERROR, 6 is not a power of 2</span>
layout(offset = <span class="integer">80</span>) <span class="predefined-type">float</span> h; <span class="comment">// h takes offsets 80-83</span>
layout(align = <span class="integer">64</span>) dvec3 i; <span class="comment">// i takes offsets 128-151</span>
layout(offset = <span class="integer">164</span>, align = <span class="integer">8</span>)
<span class="predefined-type">float</span> j; <span class="comment">// j takes offsets 168-171</span>
};</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="opaque-uniform-layout-qualifiers">4.4.6. Opaque Uniform Layout Qualifiers</h4>
<div class="paragraph">
<p>Opaque uniform variables can take the uniform layout qualifier for binding:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The <strong>binding</strong> qualifier specifies the point where the variable will be bound.
Any opaque variable declared without a binding qualifier has a default binding
of zero.</p>
</div>
<div class="paragraph">
<p>When used with OpenGL,
if the <strong>binding</strong> qualifier is used with an array, the first element of the
array takes the specified binding point and each subsequent element takes the
next consecutive binding point.
For an array of arrays, each element (e.g. 6 elements for a[2][3]) gets a
binding point, and they are ordered per the array of array ordering
described in &#8220;<a href="#arrays">Arrays.</a>&#8221;</p>
</div>
<div class="paragraph">
<p>When targeting Vulkan,
if the <strong>binding</strong> qualifier is used with an array, the entire array
takes only the provided binding number. The next consecutive binding
number is available for a different object.</p>
</div>
<div class="paragraph">
<p>If the <strong>binding</strong> is less than zero, or greater than or equal to the
implementation-dependent maximum supported number of binding points,
a compile-time error will occur.
When the <strong>binding</strong> qualifier is used with an array of size <em>N</em>, all elements
of the array from <strong>binding</strong> through <em>binding + N - 1</em> must be within this
range.
It is a compile-time or link-time error to use the same <strong>binding</strong> number for
more than one atomic counter, unless the <em>offset</em> for the atomic counters
sharing the same binding are all different.</p>
</div>
<div class="paragraph">
<p>A link-time error will result if two shaders in a program specify different
<em>layout-qualifier-value</em> bindings for the same opaque-uniform name.
However, it is not an error to specify a binding on some but not all
declarations for the same name, as shown in the examples below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// in one shader...</span>
layout(binding=<span class="integer">3</span>) uniform sampler2D s; <span class="comment">// s bound to point 3</span>
<span class="comment">// in another shader...</span>
uniform sampler2D s; <span class="comment">// okay, s still bound at 3</span>
<span class="comment">// in another shader...</span>
layout(binding=<span class="integer">4</span>) uniform sampler2D s; <span class="comment">// ERROR: contradictory bindings</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="atomic-counter-layout-qualifiers">4.4.7. Atomic Counter Layout Qualifiers</h4>
<div class="paragraph">
<p>Atomic counters are not available when targeting Vulkan.</p>
</div>
<div class="paragraph">
<p>Atomic counter layout qualifiers can be used on atomic counter declarations.
The atomic counter qualifiers are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em><br>
<strong>offset</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>, offset = <span class="integer">4</span>) uniform atomic_uint a;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the opaque handle to the atomic counter <em>a</em> will be
bound to atomic counter buffer binding point 2 at an offset of 4 basic
machine units into that buffer.
The default <em>offset</em> for binding point 2 will be post incremented by 4 (the
size of an atomic counter).</p>
</div>
<div class="paragraph">
<p>A subsequent atomic counter declaration will inherit the previous (post
incremented) offset.
For example, a subsequent declaration of</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>) uniform atomic_uint bar;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the atomic counter <em>bar</em> has a binding to buffer binding
point 2 at an offset of 8 basic machine units into that buffer.
The offset for binding point 2 will again be post-incremented by 4 (the size
of an atomic counter).</p>
</div>
<div class="paragraph">
<p>When multiple variables are listed in a layout declaration, the effect will
be the same as if they were declared one at a time, in order from left to
right.</p>
</div>
<div class="paragraph">
<p>Binding points are not inherited, only offsets.
Each binding point tracks its own current default <em>offset</em> for inheritance
of subsequent variables using the same <strong>binding</strong>.
The initial state of compilation is that all <strong>binding</strong> points have an
<em>offset</em> of 0.
The <em>offset</em> can be set per binding point at global scope (without declaring
a variable).
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>, offset = <span class="integer">4</span>) uniform atomic_uint;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Establishes that the next <strong>atomic_uint</strong> declaration for binding point 2 will
inherit <em>offset</em> 4 (but does not establish a default <strong>binding</strong>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>) uniform atomic_uint bar; <span class="comment">// offset is 4</span>
layout(offset = <span class="integer">8</span>) uniform atomic_uint bar; <span class="comment">// error, no default binding</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Atomic counters may share the same binding point, but if a binding is
shared, their offsets must be either explicitly or implicitly (from
inheritance) unique and non overlapping.</p>
</div>
<div class="paragraph">
<p>Example valid uniform declarations, assuming top of shader:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(binding=<span class="integer">3</span>, offset=<span class="integer">4</span>) uniform atomic_uint a; <span class="comment">// offset = 4</span>
layout(binding=<span class="integer">2</span>) uniform atomic_uint b; <span class="comment">// offset = 0</span>
layout(binding=<span class="integer">3</span>) uniform atomic_uint c; <span class="comment">// offset = 8</span>
layout(binding=<span class="integer">2</span>) uniform atomic_uint d; <span class="comment">// offset = 4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Example of an invalid uniform declaration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(offset=<span class="integer">4</span>) ... <span class="comment">// error, must include binding</span>
layout(binding=<span class="integer">1</span>, offset=<span class="integer">0</span>) ... a; <span class="comment">// okay</span>
layout(binding=<span class="integer">2</span>, offset=<span class="integer">0</span>) ... b; <span class="comment">// okay</span>
layout(binding=<span class="integer">1</span>, offset=<span class="integer">0</span>) ... c; <span class="comment">// error, offsets must not be shared</span>
<span class="comment">// between a and c</span>
layout(binding=<span class="integer">1</span>, offset=<span class="integer">2</span>) ... d; <span class="comment">// error, overlaps offset 0 of a</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>It is a compile-time error to bind an atomic counter with a binding value
greater than or equal to <em>gl_MaxAtomicCounterBindings</em>.
It is a compile-time error to declare an unsized array of <strong>atomic_uint</strong>.</p>
</div>
</div>
<div class="sect3">
<h4 id="format-layout-qualifiers">4.4.8. Format Layout Qualifiers</h4>
<div class="paragraph">
<p>Format layout qualifiers can be used on image variable declarations (those
declared with a basic type having &#8220;<strong>image</strong>&#8221; in its keyword).
The format layout qualifier identifiers for image variable declarations are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>layout-qualifier-id</em> : </dt>
<dd>
<p><em>float-image-format-qualifier</em><br>
<em>int-image-format-qualifier</em><br>
<em>uint-image-format-qualifier</em><br>
<strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>float-image-format-qualifier</em> : </dt>
<dd>
<p><strong>rgba32f</strong><br>
<strong>rgba16f</strong><br>
<strong>rg32f</strong><br>
<strong>rg16f</strong><br>
<strong>r11f_g11f_b10f</strong><br>
<strong>r32f</strong><br>
<strong>r16f</strong><br>
<strong>rgba16</strong><br>
<strong>rgb10_a2</strong><br>
<strong>rgba8</strong><br>
<strong>rg16</strong><br>
<strong>rg8</strong><br>
<strong>r16</strong><br>
<strong>r8</strong><br>
<strong>rgba16_snorm</strong><br>
<strong>rgba8_snorm</strong><br>
<strong>rg16_snorm</strong><br>
<strong>rg8_snorm</strong><br>
<strong>r16_snorm</strong><br>
<strong>r8_snorm</strong></p>
</dd>
<dt class="hdlist1"><em>int-image-format-qualifier</em> : </dt>
<dd>
<p><strong>rgba32i</strong><br>
<strong>rgba16i</strong><br>
<strong>rgba8i</strong><br>
<strong>rg32i</strong><br>
<strong>rg16i</strong><br>
<strong>rg8i</strong><br>
<strong>r32i</strong><br>
<strong>r16i</strong><br>
<strong>r8i</strong></p>
</dd>
<dt class="hdlist1"><em>uint-image-format-qualifier</em> : </dt>
<dd>
<p><strong>rgba32ui</strong><br>
<strong>rgba16ui</strong><br>
<strong>rgb10_a2ui</strong><br>
<strong>rgba8ui</strong><br>
<strong>rg32ui</strong><br>
<strong>rg16ui</strong><br>
<strong>rg8ui</strong><br>
<strong>r32ui</strong><br>
<strong>r16ui</strong><br>
<strong>r8ui</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>A format layout qualifier specifies the image format associated with a
declared image variable.
Only one format qualifier may be specified for any image variable
declaration.
For image variables with floating-point component types (keywords starting
with &#8220;<strong>image</strong>&#8221;), signed integer component types (keywords starting with
&#8220;<strong>iimage</strong>&#8221;), or unsigned integer component types (keywords starting with
&#8220;<strong>uimage</strong>&#8221;), the format qualifier used must match the
<em>float-image-format-qualifier</em>, <em>int-image-format-qualifier</em>, or
<em>uint-image-format-qualifier</em> grammar rules, respectively.
It is a compile-time error to declare an image variable where the format
qualifier does not match the image variable type.</p>
</div>
<div class="paragraph">
<p>Any image variable used for image loads or atomic operations must specify a
format layout qualifier; it is a compile-time error to pass an image uniform
variable or function parameter declared without a format layout qualifier to
an image load or atomic function.</p>
</div>
<div class="paragraph">
<p>Uniforms not qualified with <strong>writeonly</strong> must have a format layout qualifier.
Note that an image variable passed to a function for read access cannot be
declared as <strong>writeonly</strong> and hence must have been declared with a format
layout qualifier.</p>
</div>
<div class="paragraph">
<p>The <strong>binding</strong> qualifier was described in
&#8220;<a href="#opaque-uniform-layout-qualifiers">Opaque Uniform Layout Qualifiers</a>&#8221;.</p>
</div>
</div>
<div class="sect3">
<h4 id="_subpass_input_qualifier">4.4.9. Subpass Input Qualifier</h4>
<div class="paragraph">
<p>Subpass inputs are only available when targeting Vulkan.</p>
</div>
<div class="paragraph">
<p>Subpass inputs are declared with the basic <strong>subpassInput</strong> types.
They must be declared with the layout qualifier
<strong>input_attachment_index</strong>, or a compile-time error results.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(input_attachment_index = <span class="integer">2</span>) uniform subpassInput t;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This selects which subpass input is being read from. The value assigned
to <strong>input_attachment_index</strong>, say <em>i</em> (<code>input_attachment_index = i</code>), selects
that entry (<em>i</em> th entry) in the input list for the pass. See the API
documentation for more detail about passes and the input list.</p>
</div>
<div class="paragraph">
<p>If an array of size <em>N</em> is declared, it consumes <em>N</em> consecutive
<strong>input_attachment_index</strong> values, starting with the one provided.</p>
</div>
<div class="paragraph">
<p>It is a compile-time or link-time error to have different variables
declared with the same <strong>input_attachment_index</strong>.
This includes any overlap in the implicit <strong>input_attachment_index</strong> consumed by
array declarations.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error if the value assigned to an <strong>input_attachment_index</strong>
is greater than or equal to <em>gl_MaxInputAttachments</em>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="interpolation-qualifiers">4.5. Interpolation Qualifiers</h3>
<div class="paragraph">
<p>Inputs and outputs that could be interpolated can be further qualified by at
most one of the following interpolation qualifiers:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>smooth</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">perspective correct interpolation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>flat</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">no interpolation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>noperspective</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">linear interpolation</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The presence of and type of interpolation is controlled by the above
interpolation qualifiers as well as the auxiliary storage qualifiers
<strong>centroid</strong> and <strong>sample</strong>.
When no interpolation qualifier is present, smooth interpolation is used.
It is a compile-time error to use more than one interpolation qualifier.
The auxiliary storage qualifier <strong>patch</strong> is not used for interpolation; it is
a compile-time error to use interpolation qualifiers with <strong>patch</strong>.</p>
</div>
<div class="paragraph">
<p>A variable qualified as <strong>flat</strong> will not be interpolated.
Instead, it will have the same value for every fragment within a primitive.
This value will come from a single provoking vertex, as described by the
<a href="#references">API</a>.
A variable qualified as <strong>flat</strong> may also be qualified as <strong>centroid</strong> or
<strong>sample</strong>, which will mean the same thing as qualifying it only as <strong>flat</strong>.</p>
</div>
<div class="paragraph">
<p>A variable qualified as <strong>smooth</strong> will be interpolated in a
perspective-correct manner over the primitive being rendered.
Interpolation in a perspective correct manner is specified in equation 14.7
of the <a href="#references">OpenGL Specification</a>, section 14.5 &#8220;Line Segments&#8221;.</p>
</div>
<div class="paragraph">
<p>A variable qualified as <strong>noperspective</strong> must be interpolated linearly in
screen space, as described in equation 3.7 of the <a href="#references">OpenGL Specification</a>,
section 3.5 &#8220;Line Segments&#8221;.</p>
</div>
<div class="paragraph">
<p>When multisample rasterization is disabled, or for fragment shader input
variables qualified with neither <strong>centroid</strong> nor <strong>sample</strong>, the value of the
assigned variable may be interpolated anywhere within the pixel and a single
value may be assigned to each sample within the pixel, to the extent
permitted by the <a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>When multisample rasterization is enabled, <strong>centroid</strong> and <strong>sample</strong> may be
used to control the location and frequency of the sampling of the qualified
fragment shader input.
If a fragment shader input is qualified with <strong>centroid</strong>, a single value may
be assigned to that variable for all samples in the pixel, but that value
must be interpolated at a location that lies in both the pixel and in the
primitive being rendered, including any of the pixel&#8217;s samples covered by
the primitive.
Because the location at which the variable is interpolated may be different
in neighboring pixels, and derivatives may be computed by computing
differences between neighboring pixels, derivatives of centroid-sampled
inputs may be less accurate than those for non-centroid interpolated
variables.
If a fragment shader input is qualified with <strong>sample</strong>, a separate value must
be assigned to that variable for each covered sample in the pixel, and that
value must be sampled at the location of the individual sample.</p>
</div>
<div class="paragraph">
<p>It is a link-time error if, within the same stage, the interpolation
qualifiers of variables of the same name do not match.</p>
</div>
<div class="sect3">
<h4 id="redeclaring-built-in-interpolation-variables-in-the-compatibility-profile">4.5.1. Redeclaring Built-In Interpolation Variables in the Compatibility Profile</h4>
<div class="paragraph">
<p>The following predeclared variables can be redeclared with an interpolation
qualifier when using the compatibility profile:</p>
</div>
<div class="paragraph">
<p>Vertex, tessellation control, tessellation evaluation, and geometry
languages:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_FrontColor
gl_BackColor
gl_FrontSecondaryColor
gl_BackSecondaryColor</code></pre>
</div>
</div>
<div class="paragraph">
<p>Fragment language:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_Color
gl_SecondaryColor</code></pre>
</div>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_Color; <span class="comment">// predeclared by the fragment language</span>
flat in vec4 gl_Color; <span class="comment">// redeclared by user to be flat</span>
flat in vec4 gl_FrontColor; <span class="comment">// input to geometry shader, no &quot;gl_in[]&quot;</span>
flat out vec4 gl_FrontColor; <span class="comment">// output from geometry shader</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Ideally, these are redeclared as part of the redeclaration of an interface
block, as described in
&#8220;<a href="#compatibility-profile-built-in-language-variables">Compatibility Profile
Built-In Language Variables</a>&#8221;.
However, for the above purpose, they can be redeclared as individual
variables at global scope, outside an interface block.
Such redeclarations also allow adding the transform-feedback qualifiers
<strong>xfb_buffer</strong>, <strong>xfb_stride</strong>, and <strong>xfb_offset</strong> to output variables.
(Using <strong>xfb_buffer</strong> on a variable does not change the global default
buffer.) A compile-time error will result if a shader has both an interface
block redeclaration and a separate redeclaration of a member of that
interface block outside the interface block redeclaration.</p>
</div>
<div class="paragraph">
<p>If <em>gl_Color</em> is redeclared with an interpolation qualifier, then
<em>gl_FrontColor</em> and <em>gl_BackColor</em> (if they are written to) must also be
redeclared with the same interpolation qualifier, and vice versa.
If <em>gl_SecondaryColor</em> is redeclared with an interpolation qualifier, then
<em>gl_FrontSecondaryColor</em> and _gl_BackSecondaryColor _(if they are written
to) must also be redeclared with the same interpolation qualifier, and vice
versa.
This qualifier matching on predeclared variables is only required for
variables that are statically used within the shaders in a program.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="parameter-qualifiers">4.6. Parameter Qualifiers</h3>
<div class="paragraph">
<p>In addition to precision qualifiers and memory qualifiers, parameters can
have these parameter qualifiers.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;none: default&gt;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">same as <strong>in</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>const</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters that cannot be written to</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed into a function</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>out</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed back out of a function,
but not initialized for use when passed in</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>inout</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed both into and out of a
function</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Parameter qualifiers are discussed in more detail in
&#8220;<a href="#function-calling-conventions">Function Calling Conventions</a>&#8221;.</p>
</div>
</div>
<div class="sect2">
<h3 id="precision-and-precision-qualifiers">4.7. Precision and Precision Qualifiers</h3>
<div class="paragraph">
<p>When not targeting Vulkan:
Precision qualifiers are added for code portability with OpenGL ES, not for
functionality.
They have the same syntax as in OpenGL ES, as described below, but they have
no semantic meaning, which includes no effect on the precision used to store
or operate on variables.
If an extension adds in the same semantics and functionality in the OpenGL
ES 2.0 specification for precision qualifiers, then the extension is allowed
to reuse the keywords below for that purpose.</p>
</div>
<div class="paragraph">
<p>When targeting Vulkan:
For interface matching, uniform variables and uniform and buffer block
members must have the same precision qualification.
Global variables declared in different compilation units linked into the
same shader stage must be declared with the same precision qualification.</p>
</div>
<div class="paragraph">
<p>For the purposes of determining if an output from one shader stage matches
an input of the next stage, the precision qualifier need not match.</p>
</div>
<div class="sect3">
<h4 id="range-and-precision">4.7.1. Range and Precision</h4>
<div class="paragraph">
<p>The precision of <strong>highp</strong>
single- and double-precision
floating-point variables is defined by the IEEE 754 standard for
32-bit
and 64-bit
floating-point numbers.</p>
</div>
<div class="paragraph">
<p>This includes support for NaNs (Not a Number) and Infs (positive or negative
infinities) and positive and negative zeros.</p>
</div>
<div class="paragraph">
<p>The following rules apply to <strong>highp</strong>
for both single and double-precision
operations:
Signed infinities and zeros are generated as dictated by IEEE, but subject
to the precisions allowed in the following table.
Any subnormal (denormalized) value input into a shader or potentially
generated by any operation in a shader can be flushed to 0.
The rounding mode cannot be set and is undefined but must not affect the
result by more than 1 ULP.
NaNs are not required to be generated.
Support for signaling NaNs is not required and exceptions are never raised.
Operations including built-in functions that operate on a NaN are not
required to return a NaN as the result.
However if NaNs are generated, <strong>isnan</strong>() must return the correct value.</p>
</div>
<div class="paragraph">
<p>Precisions are expressed in terms of maximum relative error in units of ULP
(units in the last place), unless otherwise noted.</p>
</div>
<div class="paragraph">
<p>For single precision operations, precisions are required as follows:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Operation</th>
<th class="tableblock halign-left valign-top">Precision</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>a</em> + <em>b</em>, <em>a</em> - <em>b</em>, <em>a</em> * <em>b</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;, &lt;=, ==, &gt;, &gt;=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Correct result.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>a</em> / <em>b</em>, 1.0 / <em>b</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2.5 ULP for <span class="eq">|b|</span> in the range <span class="eq">[2<sup>-126</sup>, 2<sup>126</sup>]</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>a</em> * <em>b</em> + <em>c</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded single operation or
sequence of two correctly rounded operations.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>fma</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Inherited from <em>a</em> * <em>b</em> + <em>c</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>pow</strong>(<em>x</em>, <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Inherited from <strong>exp2</strong>(<em>y</em> * <strong>log2</strong>(<em>x</em>)).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>exp</strong>(<em>x</em>), <strong>exp2</strong>(<em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">(3 + 2 · |x|)</span> ULP.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>log</strong>(), <strong>log2</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">3 ULP outside the range <span class="eq">[0.5,2.0]</span>.<br>
Absolute error &lt; 2<sup>-21</sup> inside the range
<span class="eq">[0.5,2.0]</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sqrt</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Inherited from 1.0 / <strong>inversesqrt</strong>().</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>inversesqrt</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2 ULP.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">implicit and explicit
conversions between types</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Built-in functions defined in the specification with an equation built from
the above operations inherit the above errors.
These include, for example, the geometric functions, the common functions,
and many of the matrix functions.
Built-in functions not listed above and not defined as equations of the
above have undefined precision.
These include, for example, the trigonometric functions and determinant.</p>
</div>
<div class="paragraph">
<p>The precision of double-precision operations is at least that of single
precision.</p>
</div>
</div>
<div class="sect3">
<h4 id="precision-qualifiers">4.7.2. Precision Qualifiers</h4>
<div class="paragraph">
<p>Any
single-precision
floating-point, integer, or opaque-type declaration can have the type
preceded by one of these precision qualifiers:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>highp</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">32-bit two&#8217;s complement for integers,
32-bit IEEE 754 floating-point for <strong>float</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mediump</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SPIR-V <strong>RelaxedPrecision</strong> when targeting Vulkan, otherwise none.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lowp</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SPIR-V <strong>RelaxedPrecision</strong> when targeting Vulkan, otherwise none.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">lowp <span class="predefined-type">float</span> color;
out mediump vec2 P;
lowp ivec2 foo(lowp mat3);
highp mat4 m;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Literal constants do not have precision qualifiers.
Neither do Boolean variables.
Neither do constructors.</p>
</div>
<div class="paragraph">
<p>For this paragraph, &#8220;operation&#8221; includes operators, built-in functions,
and constructors, and &#8220;operand&#8221; includes function arguments and
constructor arguments.
The precision used to internally evaluate an operation, and the precision
qualification subsequently associated with any resulting intermediate
values, must be at least as high as the highest precision qualification of
the operands consumed by the operation.</p>
</div>
<div class="paragraph">
<p>In cases where operands do not have a precision qualifier, the precision
qualification will come from the other operands.
If no operands have a precision qualifier, then the precision qualifications
of the operands of the next consuming operation in the expression will be
used.
This rule can be applied recursively until a precision qualified operand is
found.
If necessary, it will also include the precision qualification of l-values
for assignments, of the declared variable for initializers, of formal
parameters for function call arguments, or of function return types for
function return values.
If the precision cannot be determined by this method e.g. if an entire
expression is composed only of operands with no precision qualifier, and the
result is not assigned or passed as an argument, then it is evaluated at the
default precision of the type or greater.
When this occurs in the fragment shader, the default precision must be
defined.</p>
</div>
<div class="paragraph">
<p>For example, consider the statements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">uniform highp <span class="predefined-type">float</span> h1;
highp <span class="predefined-type">float</span> h2 = <span class="float">2</span><span class="float">.3</span> * <span class="float">4</span><span class="float">.7</span>; <span class="comment">// operation and result are highp</span>
precision
mediump <span class="predefined-type">float</span> m;
m = <span class="float">3</span><span class="float">.7</span> * h1 * h2; <span class="comment">// all operations are highp precision</span>
h2 = m * h1; <span class="comment">// operation is highp precision</span>
m = h2 - h1; <span class="comment">// operation is highp precision</span>
h2 = m + m; <span class="comment">// addition and result at mediump precision</span>
<span class="directive">void</span> f(highp <span class="predefined-type">float</span> p);
f(<span class="float">3</span><span class="float">.3</span>); <span class="comment">// 3.3 will be passed in at highp precision</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Precision qualifiers, as with other qualifiers, do not affect the basic type
of the variable.
In particular, there are no constructors for precision conversions;
constructors only convert types.
Similarly, precision qualifiers, as with other qualifiers, do not contribute
to function overloading based on parameter types.
As discussed in &#8220;<a href="#function-calling-conventions">Function Calling
Conventions</a>&#8221;, function input and output is done through copies, and
therefore qualifiers do not have to match.</p>
</div>
<div class="paragraph">
<p>The precision of a variable is determined when the variable is declared and
cannot be subsequently changed.</p>
</div>
<div class="paragraph">
<p>Where the precision of a constant integral or constant floating-point
expression is not specified, evaluation is performed at <strong>highp</strong>.
This rule does not affect the precision qualification of the expression.</p>
</div>
<div class="paragraph">
<p>The evaluation of constant expressions must be invariant and will usually be
performed at compile time.</p>
</div>
</div>
<div class="sect3">
<h4 id="default-precision-qualifiers">4.7.3. Default Precision Qualifiers</h4>
<div class="paragraph">
<p>The precision statement</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">precision precision-qualifier type;</code></pre>
</div>
</div>
<div class="paragraph">
<p>can be used to establish a default precision qualifier.
The <em>type</em> field can be either <strong>int</strong>, <strong>float</strong>, or any of the opaque types,
and the <em>precision-qualifier</em> can be <strong>lowp</strong>, <strong>mediump</strong>, or <strong>highp</strong>.</p>
</div>
<div class="paragraph">
<p>Any other types or qualifiers will result in a compile-time error.
If <em>type</em> is <strong>float</strong>, the directive applies to non-precision-qualified
single-precision
floating-point type (scalar, vector, and matrix) declarations.
If <em>type</em> is <strong>int</strong>, the directive applies to all non-precision-qualified
integer type (scalar, vector, signed, and unsigned) declarations.
This includes global variable declarations, function return declarations,
function parameter declarations, and local variable declarations.</p>
</div>
<div class="paragraph">
<p>Non-precision qualified declarations will use the precision qualifier
specified in the most recent <strong>precision</strong> statement that is still in scope.
The <strong>precision</strong> statement has the same scoping rules as variable
declarations.
If it is declared inside a compound statement, its effect stops at the end
of the inner-most statement it was declared in.
Precision statements in nested scopes override precision statements in outer
scopes.
Multiple precision statements for the same basic type can appear inside the
same scope, with later statements overriding earlier statements within that
scope.</p>
</div>
<div class="paragraph">
<p>For any type that accepts a precision qualifier,
the default precision qualification will be <strong>highp</strong>.
Because all types requiring a precision qualifier have a default precision,
there are no errors for omission of a precision qualifier.</p>
</div>
</div>
<div class="sect3">
<h4 id="available-precision-qualifiers">4.7.4. Available Precision Qualifiers</h4>
<div class="paragraph">
<p>The built-in macro GL_FRAGMENT_PRECISION_HIGH is defined to one:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_FRAGMENT_PRECISION_HIGH <span class="integer">1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This macro is available in all languages except compute.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="variance-and-the-invariant-qualifier">4.8. Variance and the Invariant Qualifier</h3>
<div class="paragraph">
<p>In this section, <em>variance</em> refers to the possibility of getting different
values from the same expression in different programs.
For example, consider the situation where two vertex shaders, in different
programs, each set <em>gl_Position</em> with the same expression, and the input
values into that expression are the same when both shaders run.
It is possible, due to independent compilation of the two shaders, that the
values assigned to <em>gl_Position</em> are not exactly the same when the two
shaders run.
In this example, this can cause problems with alignment of geometry in a
multi-pass algorithm.</p>
</div>
<div class="paragraph">
<p>In general, such variance between shaders is allowed.
When such variance does not exist for a particular output variable, that
variable is said to be <em>invariant</em>.</p>
</div>
<div class="sect3">
<h4 id="the-invariant-qualifier">4.8.1. The Invariant Qualifier</h4>
<div class="paragraph">
<p>To ensure that a particular output variable is invariant, it is necessary to
use the <strong>invariant</strong> qualifier.
It can either be used to qualify a previously declared variable as being
invariant:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">invariant gl_Position; <span class="comment">// make existing gl_Position be invariant</span>
out vec3 Color;
invariant Color; <span class="comment">// make existing Color be invariant</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>or as part of a declaration when a variable is declared:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">invariant centroid out vec3 Color;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Only variables output from a shader can be candidates for invariance.
This includes user-defined output variables and the built-in output
variables.
As only outputs can be declared as invariant, an output from one shader
stage will still match an input of a subsequent stage without the input
being declared as invariant.</p>
</div>
<div class="paragraph">
<p>Input or output instance names on blocks are not used when redeclaring
built-in variables.</p>
</div>
<div class="paragraph">
<p>The <strong>invariant</strong> keyword can be followed by a comma separated list of
previously declared identifiers.
All uses of <strong>invariant</strong> must be at global scope or on block
members, and before any use of the variables being declared as invariant.</p>
</div>
<div class="paragraph">
<p>To guarantee invariance of a particular output variable across two programs,
the following must also be true:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The output variable is declared as invariant in both programs.</p>
</li>
<li>
<p>The same values must be input to all shader input variables consumed by
expressions and control flow contributing to the value assigned to the
output variable.</p>
</li>
<li>
<p>The texture formats, texel values, and texture filtering are set the
same way for any texture function calls contributing to the value of the
output variable.</p>
</li>
<li>
<p>All input values are all operated on in the same way.
All operations in the consuming expressions and any intermediate
expressions must be the same, with the same order of operands and same
associativity, to give the same order of evaluation.
Intermediate variables and functions must be declared as the same type
with the same explicit or implicit precision
qualifiers.
Any control flow affecting the output value must be the same, and any
expressions consumed to determine this control flow must also follow
these invariance rules.</p>
</li>
<li>
<p>All the data flow and control flow leading to setting the invariant
output variable reside in a single compilation unit.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Essentially, all the data flow and control flow leading to an invariant
output must match.</p>
</div>
<div class="paragraph">
<p>Initially, by default, all output variables are allowed to be variant.
To force all output variables to be invariant, use the pragma</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> STDGL invariant(all)</code></pre>
</div>
</div>
<div class="paragraph">
<p>before all declarations in a shader.
If this pragma is used after the declaration of any variables or functions,
then the set of outputs that behave as invariant is undefined.</p>
</div>
<div class="paragraph">
<p>Generally, invariance is ensured at the cost of flexibility in optimization,
so performance can be degraded by use of invariance.
Hence, use of this pragma is intended as a debug aid, to avoid individually
declaring all output variables as invariant.</p>
</div>
</div>
<div class="sect3">
<h4 id="invariance-of-constant-expressions">4.8.2. Invariance of Constant Expressions</h4>
<div class="paragraph">
<p>Invariance must be guaranteed for constant expressions.
A particular constant expression must evaluate to the same result if it
appears again in the same shader or a different shader.
This includes the same expression appearing in two shaders of the same
language or shaders of two different languages.</p>
</div>
<div class="paragraph">
<p>Constant expressions must evaluate to the same result when operated on as
already described above for invariant variables.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="the-precise-qualifier">4.9. The Precise Qualifier</h3>
<div class="paragraph">
<p>Some algorithms require floating-point computations to exactly follow the
order of operations specified in the source code and to treat all operations
consistently, even if the implementation supports optimizations that could
produce nearly equivalent results with higher performance.
For example, many GL implementations support a &#8220;multiply-add&#8221; instruction
that can compute a floating-point expression such as</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">result = (a * b) + (c * d);</code></pre>
</div>
</div>
<div class="paragraph">
<p>in two operations instead of three operations; one multiply and one
multiply-add instead of two multiplies and one add.
The result of a floating-point multiply-add might not always be identical to
first doing a multiply yielding a floating-point result and then doing a
floating-point add.
Hence, in this example, the two multiply operations would not be treated
consistently; the two multiplies could effectively appear to have differing
precisions.</p>
</div>
<div class="paragraph">
<p>The key computation that needs to be made consistent appears when
tessellating, where intermediate points for subdivision are synthesized in
different directions, yet need to yield the same result, as shown in the
diagram below.</p>
</div>
<div id="img-precise" class="imageblock">
<div class="content">
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KCjxzdmcgdmVyc2lvbj0iMS4yIiBiYXNlUHJvZmlsZT0idGlueSIgd2lkdGg9IjIxMG1tIiBoZWlnaHQ9IjI5N21tIiB2aWV3Qm94PSIwIDAgMjEwMDAgMjk3MDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcGF0aD0idXJsKCNwcmVzZW50YXRpb25fY2xpcF9wYXRoKSIgc3Ryb2tlLXdpZHRoPSIyOC4yMjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6b29vPSJodHRwOi8veG1sLm9wZW5vZmZpY2Uub3JnL3N2Zy9leHBvcnQiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KIDxkZWZzIGNsYXNzPSJDbGlwUGF0aEdyb3VwIj4KICA8Y2xpcFBhdGggaWQ9InByZXNlbnRhdGlvbl9jbGlwX3BhdGgiIGNsaXBQYXRoVW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIxMDAwIiBoZWlnaHQ9IjI5NzAwIi8+CiAgPC9jbGlwUGF0aD4KIDwvZGVmcz4KIDxkZWZzPgogIDxmb250IGlkPSJFbWJlZGRlZEZvbnRfMSIgaG9yaXotYWR2LXg9IjIwNDgiPgogICA8Zm9udC1mYWNlIGZvbnQtZmFtaWx5PSJMaWJlcmF0aW9uIFNhbnMgZW1iZWRkZWQiIHVuaXRzLXBlci1lbT0iMjA0OCIgZm9udC13ZWlnaHQ9Im5vcm1hbCIgZm9udC1zdHlsZT0ibm9ybWFsIiBhc2NlbnQ9IjE4NTIiIGRlc2NlbnQ9IjQyMyIvPgogICA8bWlzc2luZy1nbHlwaCBob3Jpei1hZHYteD0iMjA0OCIgZD0iTSAwLDAgTCAyMDQ3LDAgMjA0NywyMDQ3IDAsMjA0NyAwLDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0idyIgaG9yaXotYWR2LXg9IjE1MDkiIGQ9Ik0gMTE3NCwwIEwgOTY1LDAgNzkyLDY5OCBDIDc4Nyw3MTYgNzgxLDczOCA3NzYsNzY1IDc3MCw3OTIgNzY0LDgxOCA3NTksODQzIDc1Miw4NzIgNzQ2LDkwMyA3NDAsOTM0IDczNCw5MDQgNzI4LDg3NCA3MjEsODQ1IDcxNiw4MjAgNzEwLDc5MyA3MDQsNzY2IDY5Nyw3MzkgNjkxLDcxNSA2ODYsNjk0IEwgNTA4LDAgMzAwLDAgLTMsMTA4MiAxNzUsMTA4MiAzNTgsMzQ3IEMgMzYzLDMzMiAzNjcsMzEzIDM3MiwyOTEgMzc3LDI2OCAzODEsMjQ2IDM4NiwyMjUgMzkxLDIwMCAzOTYsMTc1IDQwMSwxNDkgNDA2LDE3NCA0MTIsMTk5IDQxOCwyMjMgNDIzLDI0NCA0MjksMjY1IDQzNCwyODYgNDM5LDMwNyA0NDQsMzI1IDQ0OCwzMzkgTCA2NDQsMTA4MiA4MzcsMTA4MiAxMDI2LDMzOSBDIDEwMzEsMzIyIDEwMzYsMzAyIDEwNDEsMjgwIDEwNDYsMjU4IDEwNTEsMjM3IDEwNTYsMjE4IDEwNjEsMTk1IDEwNjcsMTcyIDEwNzIsMTQ5IDEwNzcsMTc0IDEwODMsMTk5IDEwODgsMjIzIDEwOTMsMjQ0IDEwOTgsMjY1IDExMDMsMjg4IDExMDgsMzEwIDExMTIsMzMwIDExMTcsMzQ3IEwgMTMwOCwxMDgyIDE0ODQsMTA4MiAxMTc0LDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0idiIgaG9yaXotYWR2LXg9IjEwMzMiIGQ9Ik0gNjEzLDAgTCA0MDAsMCA3LDEwODIgMTk5LDEwODIgNDM3LDM3OCBDIDQ0MiwzNjMgNDQ3LDM0NiA0NTQsMzI1IDQ2MCwzMDQgNDY2LDI4MiA0NzMsMjU5IDQ4MCwyMzYgNDg2LDIxNSA0OTIsMTk0IDQ5NywxNzMgNTAyLDE1NSA1MDYsMTQxIDUxMCwxNTUgNTE1LDE3MyA1MjIsMTk0IDUyOCwyMTUgNTM0LDIzNiA1NDEsMjU4IDU0OCwyODAgNTU1LDMwMiA1NjIsMzIzIDU2OSwzNDQgNTc1LDM2MSA1ODAsMzc2IEwgODI2LDEwODIgMTAxNywxMDgyIDYxMywwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InUiIGhvcml6LWFkdi14PSI4NzQiIGQ9Ik0gMzE0LDEwODIgTCAzMTQsMzk2IEMgMzE0LDM0MyAzMTgsMjk5IDMyNiwyNjQgMzMzLDIyOSAzNDYsMjAwIDM2MywxNzkgMzgwLDE1NyA0MDMsMTQyIDQzMiwxMzMgNDYwLDEyNCA0OTUsMTE5IDUzNywxMTkgNTgwLDExOSA2MTgsMTI3IDY1MywxNDIgNjg3LDE1NyA3MTYsMTc4IDc0MSwyMDcgNzY1LDIzNSA3ODQsMjcwIDc5NywzMTIgODEwLDM1MyA4MTcsNDAxIDgxNyw0NTUgTCA4MTcsMTA4MiA5OTcsMTA4MiA5OTcsMjMxIEMgOTk3LDIwOCA5OTcsMTg1IDk5OCwxNjAgOTk4LDEzNSA5OTgsMTExIDk5OSw4OSAxMDAwLDY2IDEwMDAsNDcgMTAwMSwzMSAxMDAyLDE1IDEwMDIsNSAxMDAzLDAgTCA4MzMsMCBDIDgzMiwzIDgzMiwxMiA4MzEsMjcgODMwLDQyIDgzMCw1OSA4MjksNzggODI4LDk3IDgyNywxMTYgODI2LDEzNiA4MjUsMTU1IDgyNSwxNzIgODI1LDE4NSBMIDgyMiwxODUgQyA4MDUsMTU0IDc4NiwxMjUgNzY1LDEwMCA3NDQsNzUgNzIwLDUzIDY5MywzNiA2NjYsMTggNjM0LDQgNTk5LC02IDU2NCwtMTUgNTIzLC0yMCA0NzYsLTIwIDQxNiwtMjAgMzY0LC0xMyAzMjEsMiAyNzgsMTcgMjQyLDM5IDIxNCw3MCAxODYsMTAxIDE2NiwxNDAgMTUzLDE4OCAxNDAsMjM2IDEzMywyOTQgMTMzLDM2MSBMIDEzMywxMDgyIDMxNCwxMDgyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InQiIGhvcml6LWFkdi14PSI1MzEiIGQ9Ik0gNTU0LDggQyA1MjcsMSA0OTksLTUgNDcxLC0xMCA0NDIsLTE0IDQwOSwtMTYgMzcyLC0xNiAyMjgsLTE2IDE1Niw2NiAxNTYsMjI5IEwgMTU2LDk1MSAzMSw5NTEgMzEsMTA4MiAxNjMsMTA4MiAyMTYsMTMyNCAzMzYsMTMyNCAzMzYsMTA4MiA1MzYsMTA4MiA1MzYsOTUxIDMzNiw5NTEgMzM2LDI2OCBDIDMzNiwyMTYgMzQ1LDE4MCAzNjIsMTU5IDM3OSwxMzggNDA4LDEyNyA0NTAsMTI3IDQ2NywxMjcgNDg0LDEyOCA1MDEsMTMxIDUxNywxMzQgNTM1LDEzNyA1NTQsMTQxIEwgNTU0LDggWiIvPgogICA8Z2x5cGggdW5pY29kZT0icyIgaG9yaXotYWR2LXg9IjkwMSIgZD0iTSA5NTAsMjk5IEMgOTUwLDI0OCA5NDAsMjAzIDkyMSwxNjQgOTAxLDEyNCA4NzIsOTEgODM1LDY0IDc5OCwzNyA3NTIsMTYgNjk4LDIgNjQzLC0xMyA1ODEsLTIwIDUxMSwtMjAgNDQ4LC0yMCAzOTIsLTE1IDM0MiwtNiAyOTEsNCAyNDcsMjAgMjA5LDQxIDE3MSw2MiAxMzksOTEgMTE0LDEyNiA4OCwxNjEgNjksMjAzIDU3LDI1NCBMIDIxNiwyODUgQyAyMzEsMjI3IDI2MywxODUgMzExLDE1OCAzNTksMTMxIDQyNiwxMTcgNTExLDExNyA1NTAsMTE3IDU4NSwxMjAgNjE4LDEyNSA2NTAsMTMwIDY3OCwxNDAgNzAxLDE1MyA3MjQsMTY2IDc0MywxODMgNzU2LDIwNSA3NjksMjI2IDc3NSwyNTMgNzc1LDI4NSA3NzUsMzE4IDc2NywzNDUgNzUyLDM2NiA3MzcsMzg3IDcxNSw0MDQgNjg4LDQxOCA2NjEsNDMyIDYyOCw0NDQgNTg5LDQ1NSA1NTAsNDY1IDUwNyw0NzYgNDYwLDQ4OSA0MTcsNTAwIDM3NCw1MTMgMzMxLDUyNyAyODgsNTQxIDI1MCw1NjAgMjE2LDU4MyAxODEsNjA2IDE1Myw2MzQgMTMyLDY2OCAxMTEsNzAyIDEwMCw3NDUgMTAwLDc5NiAxMDAsODk1IDEzNSw5NzAgMjA2LDEwMjIgMjc2LDEwNzMgMzc4LDEwOTkgNTEzLDEwOTkgNjMyLDEwOTkgNzI3LDEwNzggNzk4LDEwMzYgODY4LDk5NCA5MTIsOTI3IDkzMSw4MzQgTCA3NjksODE0IEMgNzYzLDg0MiA3NTIsODY2IDczNiw4ODUgNzIwLDkwNCA3MDEsOTE5IDY3OCw5MzEgNjU1LDk0MiA2MzAsOTUxIDYwMiw5NTYgNTczLDk2MSA1NDQsOTYzIDUxMyw5NjMgNDMyLDk2MyAzNzIsOTUxIDMzMyw5MjYgMjk0LDkwMSAyNzUsODY0IDI3NSw4MTQgMjc1LDc4NSAyODIsNzYxIDI5Nyw3NDIgMzExLDcyMyAzMzEsNzA3IDM1Nyw2OTQgMzgyLDY4MSA0MTMsNjY5IDQ0OSw2NjAgNDg1LDY1MCA1MjUsNjQwIDU2OCw2MjkgNTk3LDYyMiA2MjYsNjE0IDY1Niw2MDYgNjg2LDU5NyA3MTUsNTg3IDc0NCw1NzYgNzcyLDU2NCA3OTksNTUwIDgyNCw1MzUgODQ5LDUxOSA4NzAsNTAwIDg4OSw0NzggOTA4LDQ1NiA5MjMsNDMwIDkzNCw0MDEgOTQ1LDM3MiA5NTAsMzM4IDk1MCwyOTkgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iciIgaG9yaXotYWR2LXg9IjUzMCIgZD0iTSAxNDIsMCBMIDE0Miw4MzAgQyAxNDIsODUzIDE0Miw4NzYgMTQyLDkwMCAxNDEsOTIzIDE0MSw5NDYgMTQwLDk2OCAxMzksOTkwIDEzOSwxMDExIDEzOCwxMDMwIDEzNywxMDQ5IDEzNywxMDY3IDEzNiwxMDgyIEwgMzA2LDEwODIgQyAzMDcsMTA2NyAzMDgsMTA0OSAzMDksMTAzMCAzMTAsMTAxMCAzMTEsOTkwIDMxMiw5NjkgMzEzLDk0OCAzMTMsOTI5IDMxNCw5MTAgMzE0LDg5MSAzMTQsODc0IDMxNCw4NjEgTCAzMTgsODYxIEMgMzMxLDkwMiAzNDQsOTM4IDM1OSw5NjkgMzczLDk5OSAzOTAsMTAyNCA0MDksMTA0NCA0MjgsMTA2MyA0NTEsMTA3OCA0NzgsMTA4OCA1MDUsMTA5NyA1MzcsMTEwMiA1NzUsMTEwMiA1OTAsMTEwMiA2MDQsMTEwMSA2MTcsMTA5OSA2MzAsMTA5NiA2NDEsMTA5NCA2NDgsMTA5MiBMIDY0OCw5MjcgQyA2MzYsOTMwIDYyMiw5MzMgNjA2LDkzNSA1OTAsOTM2IDU3Miw5MzcgNTUyLDkzNyA1MTEsOTM3IDQ3Niw5MjggNDQ3LDkwOSA0MTgsODkwIDM5NCw4NjUgMzc2LDgzMiAzNTcsNzk5IDM0NCw3NTkgMzM1LDcxNCAzMjYsNjY4IDMyMiw2MTggMzIyLDU2NCBMIDMyMiwwIDE0MiwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InAiIGhvcml6LWFkdi14PSI5NTMiIGQ9Ik0gMTA1Myw1NDYgQyAxMDUzLDQ2NCAxMDQ2LDM4OCAxMDMzLDMxOSAxMDIwLDI1MCA5OTgsMTkwIDk2NywxNDAgOTM2LDkwIDg5NSw1MSA4NDQsMjMgNzkzLC02IDczMCwtMjAgNjU1LC0yMCA1NzgsLTIwIDUxMCwtNSA0NTIsMjQgMzk0LDUzIDM1MCwxMDEgMzE5LDE2OCBMIDMxNCwxNjggQyAzMTUsMTY3IDMxNSwxNjEgMzE2LDE1MCAzMTYsMTM5IDMxNiwxMjYgMzE3LDExMCAzMTcsOTQgMzE3LDc2IDMxOCw1NyAzMTgsMzcgMzE4LDE3IDMxOCwtMiBMIDMxOCwtNDI1IDEzOCwtNDI1IDEzOCw4NjEgQyAxMzgsODg3IDEzOCw5MTIgMTM4LDkzNiAxMzcsOTYwIDEzNyw5ODIgMTM2LDEwMDIgMTM1LDEwMjEgMTM1LDEwMzggMTM0LDEwNTIgMTMzLDEwNjYgMTMzLDEwNzYgMTMyLDEwODIgTCAzMDYsMTA4MiBDIDMwNywxMDgwIDMwOCwxMDczIDMwOSwxMDYxIDMxMCwxMDQ5IDMxMSwxMDM1IDMxMiwxMDE4IDMxMywxMDAxIDMxNCw5ODIgMzE1LDk2MyAzMTYsOTQ0IDMxNiw5MjUgMzE2LDkwOCBMIDMyMCw5MDggQyAzMzcsOTQzIDM1Niw5NzIgMzc3LDk5NyAzOTgsMTAyMSA0MjMsMTA0MSA0NTAsMTA1NyA0NzcsMTA3MiA1MDgsMTA4NCA1NDIsMTA5MSA1NzUsMTA5OCA2MTMsMTEwMSA2NTUsMTEwMSA3MzAsMTEwMSA3OTMsMTA4OCA4NDQsMTA2MSA4OTUsMTAzNCA5MzYsOTk3IDk2Nyw5NDkgOTk4LDkwMCAxMDIwLDg0MiAxMDMzLDc3NCAxMDQ2LDcwNSAxMDUzLDYyOSAxMDUzLDU0NiBaIE0gODY0LDU0MiBDIDg2NCw2MDkgODYwLDY2OCA4NTIsNzIwIDg0NCw3NzIgODMwLDgxNiA4MTEsODUyIDc5MSw4ODggNzY1LDkxNSA3MzIsOTM0IDY5OSw5NTMgNjU4LDk2MiA2MDksOTYyIDU2OSw5NjIgNTMxLDk1NiA0OTYsOTQ1IDQ2MSw5MzQgNDMwLDkxMiA0MDQsODgwIDM3Nyw4NDggMzU2LDgwNCAzNDEsNzQ4IDMyNiw2OTEgMzE4LDYxOCAzMTgsNTI4IDMxOCw0NTEgMzI0LDM4NyAzMzcsMzM0IDM1MCwyODEgMzY4LDIzOCAzOTMsMjA1IDQxNywxNzIgNDQ3LDE0OSA0ODMsMTM1IDUxOSwxMjAgNTYwLDExMyA2MDcsMTEzIDY1NywxMTMgNjk5LDEyMyA3MzIsMTQyIDc2NSwxNjEgNzkxLDE4OSA4MTEsMjI2IDgzMCwyNjMgODQ0LDMwOCA4NTIsMzYxIDg2MCw0MTQgODY0LDQ3NCA4NjQsNTQyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9Im8iIGhvcml6LWFkdi14PSI5ODAiIGQ9Ik0gMTA1Myw1NDIgQyAxMDUzLDM1MyAxMDExLDIxMiA5MjgsMTE5IDg0NSwyNiA3MjQsLTIwIDU2NSwtMjAgNDkwLC0yMCA0MjIsLTkgMzYzLDE0IDMwNCwzNyAyNTQsNzEgMjEzLDExOCAxNzIsMTY1IDE0MCwyMjMgMTE5LDI5NCA5NywzNjQgODYsNDQ3IDg2LDU0MiA4Niw5MTUgMjQ4LDExMDIgNTcxLDExMDIgNjU1LDExMDIgNzI4LDEwOTAgNzg5LDEwNjcgODUwLDEwNDQgOTAwLDEwMDkgOTM5LDk2MiA5NzgsOTE1IDEwMDYsODU3IDEwMjUsNzg3IDEwNDQsNzE3IDEwNTMsNjM1IDEwNTMsNTQyIFogTSA4NjQsNTQyIEMgODY0LDYyNiA4NTgsNjk1IDg0NSw3NTAgODMyLDgwNSA4MTMsODQ4IDc4OCw4ODEgNzYzLDkxNCA3MzIsOTM3IDY5Niw5NTAgNjYwLDk2MyA2MTksOTY5IDU3NCw5NjkgNTI4LDk2OSA0ODcsOTYyIDQ1MCw5NDkgNDEzLDkzNSAzODEsOTEyIDM1NSw4NzkgMzI5LDg0NiAzMDksODAyIDI5Niw3NDcgMjgyLDY5MiAyNzUsNjI0IDI3NSw1NDIgMjc1LDQ1OCAyODIsMzg5IDI5NywzMzQgMzEyLDI3OSAzMzIsMjM1IDM1OCwyMDIgMzgzLDE2OSA0MTQsMTQ2IDQ0OSwxMzMgNDg0LDEyMCA1MjIsMTEzIDU2MywxMTMgNjA5LDExMyA2NTEsMTIwIDY4OCwxMzMgNzI1LDE0NiA3NTcsMTY4IDc4MywyMDEgODA5LDIzNCA4MjksMjc4IDg0MywzMzMgODU3LDM4OCA4NjQsNDU4IDg2NCw1NDIgWiIvPgogICA8Z2x5cGggdW5pY29kZT0ibiIgaG9yaXotYWR2LXg9Ijg3NCIgZD0iTSA4MjUsMCBMIDgyNSw2ODYgQyA4MjUsNzM5IDgyMSw3ODMgODE0LDgxOCA4MDYsODUzIDc5Myw4ODIgNzc2LDkwNCA3NTksOTI1IDczNiw5NDEgNzA4LDk1MCA2NzksOTU5IDY0NCw5NjMgNjAyLDk2MyA1NTksOTYzIDUyMSw5NTYgNDg3LDk0MSA0NTIsOTI2IDQyMyw5MDQgMzk5LDg3NiAzNzQsODQ3IDM1NSw4MTIgMzQyLDc3MSAzMjksNzI5IDMyMiw2ODEgMzIyLDYyNyBMIDMyMiwwIDE0MiwwIDE0Miw4NTEgQyAxNDIsODc0IDE0Miw4OTggMTQyLDkyMyAxNDEsOTQ4IDE0MSw5NzEgMTQwLDk5NCAxMzksMTAxNiAxMzksMTAzNSAxMzgsMTA1MSAxMzcsMTA2NyAxMzcsMTA3NyAxMzYsMTA4MiBMIDMwNiwxMDgyIEMgMzA3LDEwNzkgMzA3LDEwNzAgMzA4LDEwNTUgMzA5LDEwNDAgMzEwLDEwMjQgMzExLDEwMDUgMzEyLDk4NiAzMTIsOTY2IDMxMyw5NDcgMzE0LDkyNyAzMTQsOTEwIDMxNCw4OTcgTCAzMTcsODk3IEMgMzM0LDkyOCAzNTMsOTU3IDM3NCw5ODIgMzk1LDEwMDcgNDE5LDEwMjkgNDQ2LDEwNDcgNDczLDEwNjQgNTA1LDEwNzggNTQwLDEwODggNTc1LDEwOTcgNjE2LDExMDIgNjYzLDExMDIgNzIzLDExMDIgNzc1LDEwOTUgODE4LDEwODAgODYxLDEwNjUgODk3LDEwNDMgOTI1LDEwMTIgOTUzLDk4MSA5NzQsOTQyIDk4Nyw4OTQgMTAwMCw4NDUgMTAwNiw3ODggMTAwNiw3MjEgTCAxMDA2LDAgODI1LDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0ibSIgaG9yaXotYWR2LXg9IjE0NTciIGQ9Ik0gNzY4LDAgTCA3NjgsNjg2IEMgNzY4LDczOSA3NjUsNzgzIDc1OCw4MTggNzUxLDg1MyA3NDAsODgyIDcyNSw5MDQgNzA5LDkyNSA2ODgsOTQxIDY2Myw5NTAgNjM4LDk1OSA2MDcsOTYzIDU3MCw5NjMgNTMyLDk2MyA0OTgsOTU2IDQ2Nyw5NDEgNDM2LDkyNiA0MTAsOTA0IDM4OSw4NzYgMzY3LDg0NyAzNTAsODEyIDMzOSw3NzEgMzI3LDcyOSAzMjEsNjgxIDMyMSw2MjcgTCAzMjEsMCAxNDIsMCAxNDIsODUxIEMgMTQyLDg3NCAxNDIsODk4IDE0Miw5MjMgMTQxLDk0OCAxNDEsOTcxIDE0MCw5OTQgMTM5LDEwMTYgMTM5LDEwMzUgMTM4LDEwNTEgMTM3LDEwNjcgMTM3LDEwNzcgMTM2LDEwODIgTCAzMDYsMTA4MiBDIDMwNywxMDc5IDMwNywxMDcwIDMwOCwxMDU1IDMwOSwxMDQwIDMxMCwxMDI0IDMxMSwxMDA1IDMxMiw5ODYgMzEyLDk2NiAzMTMsOTQ3IDMxNCw5MjcgMzE0LDkxMCAzMTQsODk3IEwgMzE3LDg5NyBDIDMzMyw5MjggMzUwLDk1NyAzNjksOTgyIDM4OCwxMDA3IDQxMCwxMDI5IDQzNSwxMDQ3IDQ2MCwxMDY0IDQ4OCwxMDc4IDUyMSwxMDg4IDU1MywxMDk3IDU5MCwxMTAyIDYzMywxMTAyIDcxNSwxMTAyIDc4MCwxMDg2IDgyOCwxMDUzIDg3NSwxMDIwIDkwOCw5NjggOTI3LDg5NyBMIDkzMCw4OTcgQyA5NDYsOTI4IDk2NCw5NTcgOTg0LDk4MiAxMDA0LDEwMDcgMTAyNywxMDI5IDEwNTQsMTA0NyAxMDgxLDEwNjQgMTExMSwxMDc4IDExNDQsMTA4OCAxMTc3LDEwOTcgMTIxNSwxMTAyIDEyNTgsMTEwMiAxMzEzLDExMDIgMTM2MCwxMDk1IDE0MDAsMTA4MCAxNDM5LDEwNjUgMTQ3MiwxMDQzIDE0OTcsMTAxMiAxNTIyLDk4MSAxNTQxLDk0MiAxNTUzLDg5NCAxNTY1LDg0NSAxNTcxLDc4OCAxNTcxLDcyMSBMIDE1NzEsMCAxMzkzLDAgMTM5Myw2ODYgQyAxMzkzLDczOSAxMzkwLDc4MyAxMzgzLDgxOCAxMzc2LDg1MyAxMzY1LDg4MiAxMzUwLDkwNCAxMzM0LDkyNSAxMzEzLDk0MSAxMjg4LDk1MCAxMjYzLDk1OSAxMjMyLDk2MyAxMTk1LDk2MyAxMTU3LDk2MyAxMTIzLDk1NiAxMDkyLDk0MiAxMDYxLDkyNyAxMDM1LDkwNiAxMDE0LDg3OCA5OTIsODUwIDk3NSw4MTUgOTY0LDc3MyA5NTIsNzMxIDk0Niw2ODIgOTQ2LDYyNyBMIDk0NiwwIDc2OCwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImwiIGhvcml6LWFkdi14PSIxODciIGQ9Ik0gMTM4LDAgTCAxMzgsMTQ4NCAzMTgsMTQ4NCAzMTgsMCAxMzgsMCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJrIiBob3Jpei1hZHYteD0iOTAxIiBkPSJNIDgxNiwwIEwgNDUwLDQ5NCAzMTgsMzg1IDMxOCwwIDEzOCwwIDEzOCwxNDg0IDMxOCwxNDg0IDMxOCw1NTcgNzkzLDEwODIgMTAwNCwxMDgyIDU2NSw2MTcgMTAyNywwIDgxNiwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImkiIGhvcml6LWFkdi14PSIxODciIGQ9Ik0gMTM3LDEzMTIgTCAxMzcsMTQ4NCAzMTcsMTQ4NCAzMTcsMTMxMiAxMzcsMTMxMiBaIE0gMTM3LDAgTCAxMzcsMTA4MiAzMTcsMTA4MiAzMTcsMCAxMzcsMCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJoIiBob3Jpei1hZHYteD0iODc0IiBkPSJNIDMxNyw4OTcgQyAzMzcsOTM0IDM1OSw5NjUgMzgyLDk5MSA0MDUsMTAxNiA0MzEsMTAzNyA0NTksMTA1NCA0ODcsMTA3MSA1MTgsMTA4MyA1NTEsMTA5MSA1ODQsMTA5OCA2MjIsMTEwMiA2NjMsMTEwMiA3MzIsMTEwMiA3ODksMTA5MyA4MzQsMTA3NCA4NzgsMTA1NSA5MTMsMTAyOSA5MzksOTk2IDk2NCw5NjIgOTgyLDkyMiA5OTIsODc1IDEwMDEsODI4IDEwMDYsNzc3IDEwMDYsNzIxIEwgMTAwNiwwIDgyNSwwIDgyNSw2ODYgQyA4MjUsNzMyIDgyMiw3NzIgODE3LDgwNyA4MTEsODQyIDgwMCw4NzEgNzg0LDg5NCA3NjgsOTE3IDc0NSw5MzQgNzE2LDk0NiA2ODcsOTU3IDY0OSw5NjMgNjAyLDk2MyA1NTksOTYzIDUyMSw5NTUgNDg3LDk0MCA0NTIsOTI1IDQyMyw5MDMgMzk5LDg3NSAzNzQsODQ3IDM1NSw4MTMgMzQyLDc3MyAzMjksNzMzIDMyMiw2ODggMzIyLDYzOCBMIDMyMiwwIDE0MiwwIDE0MiwxNDg0IDMyMiwxNDg0IDMyMiwxMDk4IEMgMzIyLDEwNzYgMzIyLDEwNTQgMzIxLDEwMzIgMzIwLDEwMTAgMzIwLDk5MCAzMTksOTcxIDMxOCw5NTIgMzE3LDkzNyAzMTYsOTI0IDMxNSw5MTEgMzE1LDkwMiAzMTQsODk3IEwgMzE3LDg5NyBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJnIiBob3Jpei1hZHYteD0iOTI3IiBkPSJNIDU0OCwtNDI1IEMgNDg2LC00MjUgNDMxLC00MTkgMzgzLC00MDYgMzM1LC0zOTMgMjk0LC0zNzUgMjYwLC0zNTIgMjI2LC0zMjggMTk4LC0zMDAgMTc3LC0yNjcgMTU2LC0yMzQgMTQwLC0xOTggMTMxLC0xNTggTCAzMTIsLTEzMiBDIDMyNCwtMTgyIDM1MSwtMjIwIDM5MiwtMjQ4IDQzMywtMjc0IDQ4NiwtMjg4IDU1MywtMjg4IDU5NCwtMjg4IDYzMSwtMjgyIDY2NCwtMjcxIDY5NywtMjYwIDcyNiwtMjQxIDc0OSwtMjE3IDc3MiwtMTkxIDc5MCwtMTU5IDgwMywtMTE5IDgxNiwtNzkgODIyLC0zMCA4MjIsMjcgTCA4MjIsMjAxIDgyMCwyMDEgQyA4MDcsMTc0IDc5MCwxNDggNzcxLDEyMyA3NTEsOTggNzI3LDc1IDY5OSw1NiA2NzAsMzcgNjM3LDIxIDYwMCwxMCA1NjMsLTIgNTIwLC04IDQ3MiwtOCA0MDMsLTggMzQ1LDQgMjk2LDI3IDI0Nyw1MCAyMDcsODQgMTc2LDEzMCAxNDUsMTc2IDEyMiwyMzMgMTA4LDMwMiA5MywzNzAgODYsNDQ5IDg2LDUzOSA4Niw2MjYgOTMsNzA0IDEwOCw3NzMgMTIyLDg0MiAxNDUsOTAxIDE3OCw5NTAgMjEwLDk5OCAyNTIsMTAzNSAzMDQsMTA2MSAzNTUsMTA4NiA0MTgsMTA5OSA0OTIsMTA5OSA1NjksMTA5OSA2MzUsMTA4MiA2OTIsMTA0NyA3NDgsMTAxMiA3OTEsOTYyIDgyMiw4OTcgTCA4MjQsODk3IEMgODI0LDkxNCA4MjUsOTMyIDgyNiw5NTMgODI3LDk3NCA4MjgsOTkzIDgyOSwxMDEyIDgzMCwxMDMwIDgzMSwxMDQ2IDgzMiwxMDU5IDgzMywxMDcyIDgzNSwxMDgwIDgzNiwxMDgyIEwgMTAwNywxMDgyIEMgMTAwNiwxMDc2IDEwMDYsMTA2NiAxMDA1LDEwNTIgMTAwNCwxMDM3IDEwMDQsMTAyMCAxMDAzLDEwMDAgMTAwMiw5ODAgMTAwMiw5NTggMTAwMiw5MzQgMTAwMSw5MDkgMTAwMSw4ODQgMTAwMSw4NTggTCAxMDAxLDMxIEMgMTAwMSwtMTIwIDk2NCwtMjM0IDg5MCwtMzExIDgxNSwtMzg3IDcwMSwtNDI1IDU0OCwtNDI1IFogTSA4MjIsNTQxIEMgODIyLDYxNiA4MTQsNjgxIDc5OCw3MzUgNzgxLDc4OCA3NjAsODMyIDczMyw4NjYgNzA2LDkwMCA2NzYsOTI1IDY0Miw5NDEgNjA3LDk1NyA1NzIsOTY1IDUzNiw5NjUgNDkwLDk2NSA0NTEsOTU3IDQxOCw5NDEgMzg1LDkyNSAzNTcsOTAwIDMzNiw4NjYgMzE0LDgzMSAyOTgsNzg3IDI4OCw3MzQgMjc3LDY4MCAyNzIsNjE2IDI3Miw1NDEgMjcyLDQ2MyAyNzcsMzk4IDI4OCwzNDUgMjk4LDI5MiAzMTQsMjQ5IDMzNSwyMTYgMzU2LDE4MyAzODMsMTYwIDQxNiwxNDYgNDQ5LDEzMiA0ODgsMTI1IDUzMywxMjUgNTY5LDEyNSA2MDQsMTMzIDYzOSwxNDggNjczLDE2MyA3MDQsMTg4IDczMSwyMjEgNzU4LDI1NCA3ODAsMjk3IDc5NywzNTAgODE0LDQwMyA4MjIsNDY2IDgyMiw1NDEgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iZiIgaG9yaXotYWR2LXg9IjU1NyIgZD0iTSAzNjEsOTUxIEwgMzYxLDAgMTgxLDAgMTgxLDk1MSAyOSw5NTEgMjksMTA4MiAxODEsMTA4MiAxODEsMTIwNCBDIDE4MSwxMjQzIDE4NSwxMjgwIDE5MiwxMzE0IDE5OSwxMzQ3IDIxMywxMzc3IDIzMywxNDAyIDI1MiwxNDI3IDI3OSwxNDQ2IDMxMywxNDYxIDM0NywxNDc1IDM5MSwxNDgyIDQ0NSwxNDgyIDQ2NiwxNDgyIDQ4OSwxNDgxIDUxMiwxNDc5IDUzNSwxNDc3IDU1NSwxNDc0IDU3MiwxNDcwIEwgNTcyLDEzMzMgQyA1NjEsMTMzNSA1NDgsMTMzNyA1MzMsMTMzOSA1MTgsMTM0MCA1MDQsMTM0MSA0OTIsMTM0MSA0NjUsMTM0MSA0NDQsMTMzNyA0MjcsMTMzMCA0MTAsMTMyMyAzOTYsMTMxMiAzODcsMTI5OSAzNzcsMTI4NSAzNzAsMTI2OCAzNjcsMTI0OCAzNjMsMTIyOCAzNjEsMTIwNSAzNjEsMTE3OSBMIDM2MSwxMDgyIDU3MiwxMDgyIDU3Miw5NTEgMzYxLDk1MSBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJlIiBob3Jpei1hZHYteD0iOTgwIiBkPSJNIDI3Niw1MDMgQyAyNzYsNDQ2IDI4MiwzOTQgMjk0LDM0NyAzMDUsMjk5IDMyMywyNTggMzQ4LDIyNCAzNzIsMTg5IDQwMywxNjMgNDQxLDE0NCA0NzksMTI1IDUyNSwxMTUgNTc4LDExNSA2NTYsMTE1IDcxOSwxMzEgNzY2LDE2MiA4MTMsMTkzIDg0NCwyMzMgODYxLDI4MSBMIDEwMTksMjM2IEMgMTAwOCwyMDYgOTkyLDE3NiA5NzIsMTQ2IDk1MSwxMTUgOTI0LDg4IDg5MCw2NCA4NTYsMzkgODE0LDE5IDc2Myw0IDcxMiwtMTIgNjUwLC0yMCA1NzgsLTIwIDQxOCwtMjAgMjk2LDI4IDIxMywxMjMgMTI5LDIxOCA4NywzNjAgODcsNTQ4IDg3LDY0OSAxMDAsNzM1IDEyNSw4MDYgMTUwLDg3NiAxODUsOTMzIDIyOSw5NzcgMjczLDEwMjEgMzI0LDEwNTMgMzgzLDEwNzMgNDQyLDEwOTIgNTA0LDExMDIgNTcxLDExMDIgNjYyLDExMDIgNzM4LDEwODcgNzk5LDEwNTggODYwLDEwMjkgOTA5LDk4OCA5NDYsOTM3IDk4Myw4ODUgMTAwOSw4MjQgMTAyNSw3NTQgMTA0MCw2ODQgMTA0OCw2MDggMTA0OCw1MjcgTCAxMDQ4LDUwMyAyNzYsNTAzIFogTSA4NjIsNjQxIEMgODUyLDc1NSA4MjMsODM4IDc3NSw4OTEgNzI3LDk0MyA2NTgsOTY5IDU2OCw5NjkgNTM4LDk2OSA1MDcsOTY0IDQ3NCw5NTUgNDQxLDk0NSA0MTAsOTI4IDM4Miw5MDMgMzU0LDg3OCAzMzAsODQ1IDMxMSw4MDMgMjkyLDc2MCAyODEsNzA2IDI3OCw2NDEgTCA4NjIsNjQxIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImQiIGhvcml6LWFkdi14PSI5MjciIGQ9Ik0gODIxLDE3NCBDIDc4OCwxMDUgNzQ0LDU1IDY4OSwyNSA2MzQsLTUgNTY1LC0yMCA0ODQsLTIwIDM0NywtMjAgMjQ3LDI2IDE4MywxMTggMTE4LDIxMCA4NiwzNDkgODYsNTM2IDg2LDkxMyAyMTksMTEwMiA0ODQsMTEwMiA1NjYsMTEwMiA2MzQsMTA4NyA2ODksMTA1NyA3NDQsMTAyNyA3ODgsOTc5IDgyMSw5MTQgTCA4MjMsOTE0IEMgODIzLDkyMSA4MjMsOTMxIDgyMyw5NDYgODIyLDk2MCA4MjIsOTc1IDgyMiw5OTEgODIxLDEwMDYgODIxLDEwMjEgODIxLDEwMzUgODIxLDEwNDkgODIxLDEwNTkgODIxLDEwNjUgTCA4MjEsMTQ4NCAxMDAxLDE0ODQgMTAwMSwyMjMgQyAxMDAxLDE5NyAxMDAxLDE3MiAxMDAyLDE0OCAxMDAyLDEyNCAxMDAyLDEwMiAxMDAzLDgyIDEwMDQsNjIgMTAwNCw0NSAxMDA1LDMxIDEwMDYsMTYgMTAwNiw2IDEwMDcsMCBMIDgzNSwwIEMgODM0LDcgODMzLDE2IDgzMiwyOSA4MzEsNDEgODMwLDU1IDgyOSw3MSA4MjgsODcgODI3LDEwNCA4MjYsMTIyIDgyNSwxMzkgODI1LDE1NyA4MjUsMTc0IEwgODIxLDE3NCBaIE0gMjc1LDU0MiBDIDI3NSw0NjcgMjgwLDQwMyAyODksMzUwIDI5OCwyOTcgMzEzLDI1MyAzMzQsMjE5IDM1NSwxODQgMzgxLDE1OSA0MTMsMTQzIDQ0NSwxMjcgNDg0LDExOSA1MzAsMTE5IDU3NywxMTkgNjE5LDEyNyA2NTYsMTQyIDY5MiwxNTcgNzIyLDE4MiA3NDcsMjE3IDc3MSwyNTEgNzg5LDI5NiA4MDIsMzUxIDgxNSw0MDYgODIxLDQ3NCA4MjEsNTU0IDgyMSw2MzEgODE1LDY5NiA4MDIsNzQ5IDc4OSw4MDIgNzcxLDg0NCA3NDYsODc3IDcyMSw5MTAgNjkxLDkzMyA2NTYsOTQ4IDYyMCw5NjIgNTc5LDk2OSA1MzIsOTY5IDQ4OCw5NjkgNDUwLDk2MSA0MTgsOTQ2IDM4Niw5MzEgMzU5LDkwNiAzMzgsODcyIDMxNyw4MzggMzAxLDc5NCAyOTEsNzQwIDI4MCw2ODUgMjc1LDYxOSAyNzUsNTQyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImMiIGhvcml6LWFkdi14PSI5MDEiIGQ9Ik0gMjc1LDU0NiBDIDI3NSw0ODQgMjgwLDQyNyAyODksMzc1IDI5OCwzMjMgMzEzLDI3OCAzMzQsMjQxIDM1NSwyMDMgMzg0LDE3NCA0MTksMTUzIDQ1NCwxMzIgNDk3LDEyMiA1NDgsMTIyIDYxMiwxMjIgNjY2LDEzOSA3MDksMTczIDc1MiwyMDYgNzc4LDI1OCA3ODgsMzI4IEwgOTcwLDMyOCBDIDk2NCwyODMgOTUxLDIzOSA5MzEsMTk3IDkxMSwxNTUgODg0LDExOCA4NTAsODYgODE1LDU0IDc3MywyOCA3MjQsOSA2NzUsLTEwIDYxOCwtMjAgNTUzLC0yMCA0NjgsLTIwIDM5NiwtNiAzMzcsMjMgMjc4LDUyIDIzMCw5MSAxOTMsMTQyIDE1NiwxOTIgMTI5LDI1MSAxMTIsMzIwIDk1LDM4OCA4Nyw0NjIgODcsNTQyIDg3LDYxNSA5Myw2NzkgMTA1LDczNSAxMTcsNzkwIDEzNCw4MzkgMTU2LDg4MSAxNzcsOTIyIDIwMyw5NTcgMjMyLDk4NiAyNjEsMTAxNCAyOTMsMTAzNyAzMjgsMTA1NCAzNjIsMTA3MSAzOTgsMTA4MyA0MzYsMTA5MSA0NzQsMTA5OCA1MTIsMTEwMiA1NTEsMTEwMiA2MTIsMTEwMiA2NjYsMTA5NCA3MTMsMTA3NyA3NjAsMTA2MCA4MDEsMTAzOCA4MzYsMTAwOSA4NzAsOTgwIDg5OCw5NDUgOTE5LDkwNiA5NDAsODY3IDk1NSw4MjQgOTY0LDc3OSBMIDc3OSw3NjUgQyA3NzAsODI1IDc0Niw4NzMgNzA4LDkwOCA2NzAsOTQzIDYxNiw5NjEgNTQ2LDk2MSA0OTUsOTYxIDQ1Miw5NTMgNDE4LDkzNiAzODMsOTE5IDM1NSw4OTMgMzM0LDg1OSAzMTMsODI0IDI5OCw3ODEgMjg5LDcyOSAyODAsNjc3IDI3NSw2MTYgMjc1LDU0NiBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJiIiBob3Jpei1hZHYteD0iOTUzIiBkPSJNIDEwNTMsNTQ2IEMgMTA1MywxNjkgOTIwLC0yMCA2NTUsLTIwIDU3MywtMjAgNTA1LC01IDQ1MSwyNSAzOTYsNTQgMzUyLDEwMiAzMTgsMTY4IEwgMzE2LDE2OCBDIDMxNiwxNTEgMzE2LDEzMyAzMTUsMTE0IDMxNCw5NSAzMTMsNzggMzEyLDYyIDMxMSw0NiAzMTAsMzIgMzA5LDIxIDMwOCwxMCAzMDcsMyAzMDYsMCBMIDEzMiwwIEMgMTMzLDYgMTMzLDE2IDEzNCwzMSAxMzUsNDUgMTM1LDYyIDEzNiw4MiAxMzcsMTAyIDEzNywxMjQgMTM4LDE0OCAxMzgsMTcyIDEzOCwxOTcgMTM4LDIyMyBMIDEzOCwxNDg0IDMxOCwxNDg0IDMxOCwxMDYxIEMgMzE4LDEwNDEgMzE4LDEwMjIgMzE4LDEwMDQgMzE3LDk4NSAzMTcsOTY5IDMxNiw5NTUgMzE1LDkzOCAzMTUsOTIzIDMxNCw5MDggTCAzMTgsOTA4IEMgMzUxLDk3NyAzOTYsMTAyNyA0NTEsMTA1NyA1MDYsMTA4NyA1NzQsMTEwMiA2NTUsMTEwMiA3OTIsMTEwMiA4OTIsMTA1NiA5NTcsOTY0IDEwMjEsODcyIDEwNTMsNzMzIDEwNTMsNTQ2IFogTSA4NjQsNTQwIEMgODY0LDYxNSA4NTksNjc5IDg1MCw3MzIgODQxLDc4NSA4MjYsODI5IDgwNSw4NjQgNzg0LDg5OCA3NTgsOTIzIDcyNiw5MzkgNjk0LDk1NSA2NTUsOTYzIDYwOSw5NjMgNTYyLDk2MyA1MjAsOTU1IDQ4NCw5NDAgNDQ3LDkyNSA0MTcsOTAwIDM5Myw4NjYgMzY4LDgzMiAzNTAsNzg3IDMzNyw3MzIgMzI0LDY3NyAzMTgsNjA5IDMxOCw1MjkgMzE4LDQ1MiAzMjQsMzg3IDMzNywzMzQgMzUwLDI4MSAzNjgsMjM5IDM5MywyMDYgNDE3LDE3MyA0NDcsMTQ5IDQ4MywxMzUgNTE5LDEyMCA1NjAsMTEzIDYwNywxMTMgNjUxLDExMyA2ODksMTIxIDcyMSwxMzYgNzUzLDE1MSA3ODAsMTc2IDgwMSwyMTAgODIyLDI0NCA4MzgsMjg4IDg0OSwzNDMgODU5LDM5NyA4NjQsNDYzIDg2NCw1NDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iYSIgaG9yaXotYWR2LXg9IjEwNjAiIGQ9Ik0gNDE0LC0yMCBDIDMwNSwtMjAgMjI0LDkgMTY5LDY2IDExNCwxMjQgODcsMjAzIDg3LDMwMyA4NywzNzUgMTAxLDQzNCAxMjgsNDgwIDE1NSw1MjYgMTkwLDU2MiAyMzQsNTg4IDI3Nyw2MTQgMzI3LDYzMiAzODMsNjQyIDQzOSw2NTIgNDk2LDY1NyA1NTQsNjU3IEwgNzk3LDY1NyA3OTcsNzE3IEMgNzk3LDc2MiA3OTIsODAwIDc4Myw4MzIgNzc0LDg2MyA3NTksODg5IDc0MCw5MDggNzIxLDkyOCA2OTcsOTQyIDY2OCw5NTEgNjM5LDk2MCA2MDQsOTY1IDU2NSw5NjUgNTMwLDk2NSA0OTksOTYzIDQ3MSw5NTggNDQzLDk1MyA0MTksOTQ0IDM5OCw5MzEgMzc3LDkxOCAzNjEsOTAwIDM0OCw4NzggMzM1LDg1NSAzMjcsODI3IDMyMyw3OTMgTCAxMzUsODEwIEMgMTQyLDg1MyAxNTQsODkyIDE3Myw5MjggMTkyLDk2MyAyMTgsOTk0IDI1MywxMDIwIDI4NywxMDQ2IDMzMCwxMDY2IDM4MiwxMDgxIDQzMywxMDk1IDQ5NiwxMTAyIDU2OSwxMTAyIDcwNSwxMTAyIDgwNywxMDcxIDg3NiwxMDA5IDk0NSw5NDYgOTc5LDg1NiA5NzksNzM4IEwgOTc5LDI3MiBDIDk3OSwyMTkgOTg2LDE3OSAxMDAwLDE1MiAxMDE0LDEyNSAxMDQxLDExMSAxMDgwLDExMSAxMDkwLDExMSAxMTAwLDExMiAxMTEwLDExMyAxMTIwLDExNCAxMTMwLDExNiAxMTM5LDExOCBMIDExMzksNiBDIDExMTYsMSAxMDk0LC0zIDEwNzIsLTYgMTA0OSwtOSAxMDI1LC0xMCAxMDAwLC0xMCA5NjYsLTEwIDkzNywtNSA5MTMsNCA4ODgsMTMgODY4LDI2IDg1Myw0NSA4MzgsNjMgODI2LDg2IDgxOCwxMTMgODEwLDE0MCA4MDUsMTcxIDgwMywyMDcgTCA3OTcsMjA3IEMgNzc4LDE3MiA3NTcsMTQxIDczNCwxMTMgNzExLDg1IDY4NCw2MSA2NTMsNDIgNjIyLDIyIDU4OCw3IDU0OSwtNCA1MTAsLTE1IDQ2NSwtMjAgNDE0LC0yMCBaIE0gNDU1LDExNSBDIDUxMiwxMTUgNTYzLDEyNSA2MDYsMTQ2IDY0OSwxNjcgNjg0LDE5NCA3MTMsMjI2IDc0MSwyNTkgNzYyLDI5NCA3NzYsMzMyIDc5MCwzNzEgNzk3LDQwOCA3OTcsNDQzIEwgNzk3LDUzMSA2MDAsNTMxIEMgNTU2LDUzMSA1MTQsNTI4IDQ3NSw1MjIgNDM1LDUxNyA0MDAsNTA2IDM3MCw0ODkgMzQwLDQ3MiAzMTYsNDQ5IDI5OSw0MTggMjgxLDM4OCAyNzIsMzQ5IDI3MiwzMDAgMjcyLDI0MSAyODgsMTk1IDMyMCwxNjMgMzUxLDEzMSAzOTYsMTE1IDQ1NSwxMTUgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iUyIgaG9yaXotYWR2LXg9IjExOTIiIGQ9Ik0gMTI3MiwzODkgQyAxMjcyLDMzMCAxMjYxLDI3NSAxMjM4LDIyNSAxMjE1LDE3NSAxMTc5LDEzMiAxMTMxLDk2IDEwODMsNTkgMTAyMywzMSA5NTAsMTEgODc3LC0xMCA3OTAsLTIwIDY5MCwtMjAgNTE1LC0yMCAzNzgsMTEgMjgwLDcyIDE4MiwxMzMgMTIwLDIyMiA5MywzMzggTCAyNzgsMzc1IEMgMjg3LDMzOCAzMDIsMzA1IDMyMSwyNzUgMzQwLDI0NSAzNjcsMjE5IDQwMCwxOTggNDMzLDE3NiA0NzMsMTU5IDUyMiwxNDcgNTcxLDEzNSA2MjksMTI5IDY5NywxMjkgNzU0LDEyOSA4MDYsMTM0IDg1MywxNDQgOTAwLDE1MyA5NDEsMTY4IDk3NSwxODggMTAwOSwyMDggMTAzNiwyMzQgMTA1NSwyNjYgMTA3NCwyOTcgMTA4MywzMzUgMTA4MywzNzkgMTA4Myw0MjUgMTA3Myw0NjIgMTA1Miw0OTEgMTAzMSw1MjAgMTAwMSw1NDMgOTYzLDU2MiA5MjUsNTgxIDg4MCw1OTYgODI3LDYwOSA3NzQsNjIyIDcxNiw2MzUgNjUyLDY1MCA2MTMsNjU5IDU3Myw2NjggNTM0LDY3OSA0OTQsNjg5IDQ1Niw3MDEgNDIwLDcxNiAzODMsNzMwIDM0OSw3NDcgMzE3LDc2NiAyODUsNzg1IDI1Nyw4MDkgMjM0LDgzNiAyMTEsODYzIDE5Miw4OTQgMTc5LDkzMCAxNjYsOTY1IDE1OSwxMDA2IDE1OSwxMDUzIDE1OSwxMTIwIDE3MywxMTc3IDIwMCwxMjI1IDIyNywxMjcyIDI2NCwxMzExIDMxMiwxMzQyIDM2MCwxMzczIDQxNywxMzk1IDQ4MiwxNDA5IDU0NywxNDIzIDYxOCwxNDMwIDY5NCwxNDMwIDc4MSwxNDMwIDg1NiwxNDIzIDkxOCwxNDEwIDk4MCwxMzk2IDEwMzIsMTM3NSAxMDc1LDEzNDggMTExOCwxMzIxIDExNTIsMTI4NyAxMTc4LDEyNDcgMTIwMywxMjA2IDEyMjQsMTE1OSAxMjM5LDExMDYgTCAxMDUxLDEwNzMgQyAxMDQyLDExMDcgMTAyOCwxMTM3IDEwMTEsMTE2NCA5OTMsMTE5MSA5NzAsMTIxMyA5NDEsMTIzMSA5MTIsMTI0OSA4NzgsMTI2MyA4MzcsMTI3MiA3OTYsMTI4MSA3NDcsMTI4NiA2OTIsMTI4NiA2MjcsMTI4NiA1NzIsMTI4MCA1MjgsMTI2OSA0ODMsMTI1NyA0NDgsMTI0MSA0MjEsMTIyMSAzOTQsMTIwMSAzNzQsMTE3OCAzNjMsMTE1MSAzNTEsMTEyNCAzNDUsMTA5NCAzNDUsMTA2MyAzNDUsMTAyMSAzNTYsOTg3IDM3Nyw5NjAgMzk4LDkzMyA0MjYsOTEwIDQ2Miw4OTIgNDk4LDg3NCA1NDAsODU5IDU4Nyw4NDcgNjM0LDgzNSA2ODUsODIzIDczOCw4MTEgNzgxLDgwMSA4MjUsNzkxIDg2OCw3ODEgOTExLDc3MCA5NTIsNzU4IDk5MSw3NDQgMTAzMCw3MjkgMTA2Nyw3MTIgMTEwMiw2OTMgMTEzNiw2NzQgMTE2Niw2NTAgMTE5MSw2MjIgMTIxNiw1OTQgMTIzNiw1NjEgMTI1MSw1MjMgMTI2NSw0ODUgMTI3Miw0NDAgMTI3MiwzODkgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iTyIgaG9yaXotYWR2LXg9IjE0MzAiIGQ9Ik0gMTQ5NSw3MTEgQyAxNDk1LDYwMSAxNDc5LDUwMSAxNDQ4LDQxMSAxNDE2LDMyMSAxMzcwLDI0NCAxMzEwLDE4MCAxMjUwLDExNiAxMTc3LDY3IDEwOTAsMzIgMTAwMywtMyA5MDUsLTIwIDc5NSwtMjAgNjc5LC0yMCA1NzcsLTIgNDkwLDM1IDQwMyw3MSAzMzAsMTIyIDI3MiwxODcgMjE0LDI1MiAxNzAsMzI5IDE0MSw0MTggMTEyLDUwNyA5Nyw2MDUgOTcsNzExIDk3LDgyMSAxMTIsOTIwIDE0MywxMDA5IDE3NCwxMDk4IDIxOSwxMTczIDI3OCwxMjM2IDMzNywxMjk4IDQxMSwxMzQ2IDQ5OCwxMzgwIDU4NSwxNDEzIDY4NCwxNDMwIDc5NywxNDMwIDkwOSwxNDMwIDEwMDksMTQxMyAxMDk2LDEzNzkgMTE4MywxMzQ1IDEyNTYsMTI5NyAxMzE1LDEyMzQgMTM3NCwxMTcxIDE0MTgsMTA5NiAxNDQ5LDEwMDcgMTQ4MCw5MTggMTQ5NSw4MjAgMTQ5NSw3MTEgWiBNIDEzMDAsNzExIEMgMTMwMCw3OTYgMTI4OSw4NzMgMTI2OCw5NDIgMTI0NiwxMDExIDEyMTQsMTA3MSAxMTcyLDExMjAgMTEyOSwxMTY5IDEwNzcsMTIwNyAxMDE0LDEyMzQgOTUxLDEyNjEgODc5LDEyNzQgNzk3LDEyNzQgNzEzLDEyNzQgNjM5LDEyNjEgNTc2LDEyMzQgNTEzLDEyMDcgNDYwLDExNjkgNDE4LDExMjAgMzc1LDEwNzEgMzQ0LDEwMTEgMzIzLDk0MiAzMDIsODczIDI5MSw3OTYgMjkxLDcxMSAyOTEsNjI2IDMwMiw1NDkgMzI0LDQ3OSAzNDUsNDA4IDM3NywzNDggNDIwLDI5NyA0NjIsMjQ2IDUxNSwyMDYgNTc4LDE3OCA2NDEsMTQ5IDcxMywxMzUgNzk1LDEzNSA4ODMsMTM1IDk1OSwxNDkgMTAyMywxNzggMTA4NiwyMDcgMTEzOSwyNDcgMTE4MCwyOTggMTIyMSwzNDkgMTI1MSw0MDkgMTI3MSw0ODAgMTI5MCw1NTEgMTMwMCw2MjggMTMwMCw3MTEgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iQyIgaG9yaXotYWR2LXg9IjEzMjQiIGQ9Ik0gNzkyLDEyNzQgQyA3MTIsMTI3NCA2NDEsMTI2MSA1ODAsMTIzNCA1MTgsMTIwNyA0NjYsMTE2OSA0MjUsMTEyMCAzODMsMTA3MSAzNTEsMTAxMSAzMzAsOTQyIDMwOSw4NzMgMjk4LDc5NiAyOTgsNzExIDI5OCw2MjYgMzEwLDU0OSAzMzMsNDc5IDM1Niw0MDggMzg5LDM0OCA0MzIsMjk3IDQ3NSwyNDYgNTI3LDIwNyA1OTAsMTc5IDY1MiwxNTEgNzIyLDEzNyA4MDAsMTM3IDg1NSwxMzcgOTA1LDE0NCA5NTAsMTU5IDk5NSwxNzMgMTAzNSwxOTMgMTA3MiwyMTkgMTEwOCwyNDUgMTE0MCwyNzYgMTE2OSwzMTIgMTE5OCwzNDcgMTIyMywzODcgMTI0NSw0MzAgTCAxNDAxLDM1MiBDIDEzNzYsMjk5IDEzNDQsMjUwIDEzMDcsMjA1IDEyNzAsMTYwIDEyMjYsMTIwIDExNzYsODcgMTEyNSw1NCAxMDY4LDI4IDEwMDUsOSA5NDEsLTEwIDg3MCwtMjAgNzkxLC0yMCA2NzcsLTIwIDU3NywtMiA0OTIsMzUgNDA2LDcxIDMzNCwxMjIgMjc3LDE4NyAyMTksMjUyIDE3NiwzMjkgMTQ3LDQxOCAxMTgsNTA3IDEwNCw2MDUgMTA0LDcxMSAxMDQsODIxIDExOSw5MjAgMTUwLDEwMDkgMTgwLDEwOTggMjI0LDExNzMgMjgzLDEyMzYgMzQxLDEyOTggNDEzLDEzNDYgNDk4LDEzODAgNTgzLDE0MTMgNjgxLDE0MzAgNzkwLDE0MzAgOTQwLDE0MzAgMTA2NSwxNDAxIDExNjYsMTM0MiAxMjY3LDEyODMgMTM0MSwxMTk2IDEzODgsMTA4MSBMIDEyMDcsMTAyMSBDIDExOTQsMTA1NCAxMTc2LDEwODYgMTE1MywxMTE3IDExMzAsMTE0NyAxMTAyLDExNzQgMTA2OCwxMTk3IDEwMzQsMTIyMCA5OTQsMTIzOSA5NDksMTI1MyA5MDMsMTI2NyA4NTEsMTI3NCA3OTIsMTI3NCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSIgIiBob3Jpei1hZHYteD0iNTU2Ii8+CiAgPC9mb250PgogPC9kZWZzPgogPGRlZnMgY2xhc3M9IlRleHRTaGFwZUluZGV4Ij4KICA8ZyBvb286c2xpZGU9ImlkMSIgb29vOmlkLWxpc3Q9ImlkMyBpZDQgaWQ1IGlkNiBpZDcgaWQ4IGlkOSBpZDEwIGlkMTEgaWQxMiBpZDEzIGlkMTQgaWQxNSBpZDE2IGlkMTcgaWQxOCBpZDE5Ii8+CiA8L2RlZnM+CiA8ZGVmcyBjbGFzcz0iRW1iZWRkZWRCdWxsZXRDaGFycyI+CiAgPGcgaWQ9ImJ1bGxldC1jaGFyLXRlbXBsYXRlKDU3MzU2KSIgdHJhbnNmb3JtPSJzY2FsZSgwLjAwMDQ4ODI4MTI1LC0wLjAwMDQ4ODI4MTI1KSI+CiAgIDxwYXRoIGQ9Ik0gNTgwLDExNDEgTCAxMTYzLDU3MSA1ODAsMCAtNCw1NzEgNTgwLDExNDEgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoNTczNTQpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSA4LDExMjggTCAxMTM3LDExMjggMTEzNywwIDgsMCA4LDExMjggWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAxNDYpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAxNzQsMCBMIDYwMiw3MzkgMTc0LDE0ODEgMTQ1Niw3MzkgMTc0LDAgWiBNIDEzNTgsNzM5IEwgMzA5LDEzNDYgNjU5LDczOSAxMzU4LDczOSBaIi8+CiAgPC9nPgogIDxnIGlkPSJidWxsZXQtY2hhci10ZW1wbGF0ZSgxMDEzMikiIHRyYW5zZm9ybT0ic2NhbGUoMC4wMDA0ODgyODEyNSwtMC4wMDA0ODgyODEyNSkiPgogICA8cGF0aCBkPSJNIDIwMTUsNzM5IEwgMTI3NiwwIDcxNywwIDEyNjAsNTQzIDE3NCw1NDMgMTc0LDkzNiAxMjYwLDkzNiA3MTcsMTQ4MSAxMjc0LDE0ODEgMjAxNSw3MzkgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAwMDcpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAwLC0yIEMgLTcsMTQgLTE2LDI3IC0yNSwzNyBMIDM1Niw1NjcgQyAyNjIsODIzIDIxNSw5NTIgMjE1LDk1NCAyMTUsOTc5IDIyOCw5OTIgMjU1LDk5MiAyNjQsOTkyIDI3Niw5OTAgMjg5LDk4NyAzMTAsOTkxIDMzMSw5OTkgMzU0LDEwMTIgTCAzODEsOTk5IDQ5Miw3NDggNzcyLDEwNDkgODM2LDEwMjQgODYwLDEwNDkgQyA4ODEsMTAzOSA5MDEsMTAyNSA5MjIsMTAwNiA4ODYsOTM3IDgzNSw4NjMgNzcwLDc4NCA3NjksNzgzIDcxMCw3MTYgNTk0LDU4NCBMIDc3NCwyMjMgQyA3NzQsMTk2IDc1MywxNjggNzExLDEzOSBMIDcyNywxMTkgQyA3MTcsOTAgNjk5LDc2IDY3Miw3NiA2NDEsNzYgNTcwLDE3OCA0NTcsMzgxIEwgMTY0LC03NiBDIDE0MiwtMTEwIDExMSwtMTI3IDcyLC0xMjcgMzAsLTEyNyA5LC0xMTAgOCwtNzYgMSwtNjcgLTIsLTUyIC0yLC0zMiAtMiwtMjMgLTEsLTEzIDAsLTIgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAwMDQpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAyODUsLTMzIEMgMTgyLC0zMyAxMTEsMzAgNzQsMTU2IDUyLDIyOCA0MSwzMzMgNDEsNDcxIDQxLDU0OSA1NSw2MTYgODIsNjcyIDExNiw3NDMgMTY5LDc3OCAyNDAsNzc4IDI5Myw3NzggMzI4LDc0NyAzNDYsNjg0IEwgMzY5LDUwOCBDIDM3Nyw0NDQgMzk3LDQxMSA0MjgsNDEwIEwgMTE2MywxMTE2IEMgMTE3NCwxMTI3IDExOTYsMTEzMyAxMjI5LDExMzMgMTI3MSwxMTMzIDEyOTIsMTExOCAxMjkyLDEwODcgTCAxMjkyLDk2NSBDIDEyOTIsOTI5IDEyODIsOTAxIDEyNjIsODgxIEwgNDQyLDQ3IEMgMzkwLC02IDMzOCwtMzMgMjg1LC0zMyBaIi8+CiAgPC9nPgogIDxnIGlkPSJidWxsZXQtY2hhci10ZW1wbGF0ZSg5Njc5KSIgdHJhbnNmb3JtPSJzY2FsZSgwLjAwMDQ4ODI4MTI1LC0wLjAwMDQ4ODI4MTI1KSI+CiAgIDxwYXRoIGQ9Ik0gODEzLDAgQyA2MzIsMCA0ODksNTQgMzgzLDE2MSAyNzYsMjY4IDIyMyw0MTEgMjIzLDU5MiAyMjMsNzczIDI3Niw5MTYgMzgzLDEwMjMgNDg5LDExMzAgNjMyLDExODQgODEzLDExODQgOTkyLDExODQgMTEzNiwxMTMwIDEyNDUsMTAyMyAxMzUzLDkxNiAxNDA3LDc3MiAxNDA3LDU5MiAxNDA3LDQxMiAxMzUzLDI2OCAxMjQ1LDE2MSAxMTM2LDU0IDk5MiwwIDgxMywwIFoiLz4KICA8L2c+CiAgPGcgaWQ9ImJ1bGxldC1jaGFyLXRlbXBsYXRlKDgyMjYpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAzNDYsNDU3IEMgMjczLDQ1NyAyMDksNDgzIDE1NSw1MzUgMTAxLDU4NiA3NCw2NDkgNzQsNzIzIDc0LDc5NiAxMDEsODU5IDE1NSw5MTEgMjA5LDk2MyAyNzMsOTg5IDM0Niw5ODkgNDE5LDk4OSA0ODAsOTYzIDUzMSw5MTAgNTgyLDg1OSA2MDgsNzk2IDYwOCw3MjMgNjA4LDY0OCA1ODMsNTg2IDUzMiw1MzUgNDgyLDQ4MyA0MjAsNDU3IDM0Niw0NTcgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoODIxMSkiIHRyYW5zZm9ybT0ic2NhbGUoMC4wMDA0ODgyODEyNSwtMC4wMDA0ODgyODEyNSkiPgogICA8cGF0aCBkPSJNIC00LDQ1OSBMIDExMzUsNDU5IDExMzUsNjA2IC00LDYwNiAtNCw0NTkgWiIvPgogIDwvZz4KIDwvZGVmcz4KIDxkZWZzIGNsYXNzPSJUZXh0RW1iZWRkZWRCaXRtYXBzIi8+CiA8Zz4KICA8ZyBpZD0iaWQyIiBjbGFzcz0iTWFzdGVyX1NsaWRlIj4KICAgPGcgaWQ9ImJnLWlkMiIgY2xhc3M9IkJhY2tncm91bmQiLz4KICAgPGcgaWQ9ImJvLWlkMiIgY2xhc3M9IkJhY2tncm91bmRPYmplY3RzIi8+CiAgPC9nPgogPC9nPgogPGcgY2xhc3M9IlNsaWRlR3JvdXAiPgogIDxnPgogICA8ZyBpZD0iaWQxIiBjbGFzcz0iU2xpZGUiIGNsaXAtcGF0aD0idXJsKCNwcmVzZW50YXRpb25fY2xpcF9wYXRoKSI+CiAgICA8ZyBjbGFzcz0iUGFnZSI+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLlJlY3RhbmdsZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMyI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODQ1MCw3MDAwIEwgNzAwMCw3MDAwIDcwMDAsMzAwMCA5OTAwLDMwMDAgOTkwMCw3MDAwIDg0NTAsNzAwMCBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLlJlY3RhbmdsZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkNCI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTIwNTAsNzAwMCBMIDEwMTAwLDcwMDAgMTAxMDAsMzAwMCAxNDAwMCwzMDAwIDE0MDAwLDcwMDAgMTIwNTAsNzAwMCBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkVsbGlwc2VTaGFwZSI+CiAgICAgIDxnIGlkPSJpZDUiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDg5OTksMzMwMCBDIDkxMDUsMzMxMiA5MTk1LDMzODMgOTI4OCwzNTMxIDkzODcsMzY5MCA5NDU5LDM4ODkgOTUxNiw0MTY1IDk1NzQsNDQ0MSA5NjAwLDQ3MTIgOTYwMCw1MDMxIDk2MDAsNTM1MCA5NTc0LDU2MjEgOTUxNiw1ODk3IDk0NTksNjE3MyA5NDAyLDYzMjggOTMxOSw2NDc4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiIGQ9Ik0gOTE0MSw2NzAxIEwgOTQwNSw2NTI2IDkyNDgsNjQwMyA5MTQxLDY3MDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5FbGxpcHNlU2hhcGUiPgogICAgICA8ZyBpZD0iaWQ2Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDc5NCw2NzEwIEMgMTA3NDgsNjY2OSAxMDcxMCw2NjE4IDEwNjY4LDY1NDAgMTA1ODMsNjM4MCAxMDUyMSw2MTgxIDEwNDcyLDU5MDUgMTA0MjIsNTYyOCAxMDQwMCw1MzU2IDEwNDAwLDUwMzYgMTA0MDAsNDcxNiAxMDQyMiw0NDQ0IDEwNDcyLDQxNjggMTA1MjEsMzg5MSAxMDU4MywzNjkyIDEwNjY4LDM1MzIgMTA3NDgsMzM4MyAxMDY5MCwzNDkyIDEwNzAxLDM0NzQiLz4KICAgICAgIDxwYXRoIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSIgZD0iTSAxMDkxNiwzMzAwIEwgMTA2MjIsMzQxNiAxMDc1MCwzNTY5IDEwOTE2LDMzMDAgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDciPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDk4OTksNjkwMCBDIDk5NTUsNjkwMCA5OTk5LDY5NDMgOTk5OSw2OTk5IDk5OTksNzA1NSA5OTU1LDcwOTkgOTg5OSw3MDk5IDk4NDMsNzA5OSA5ODAwLDcwNTUgOTgwMCw2OTk5IDk4MDAsNjk0MyA5ODQzLDY5MDAgOTg5OSw2OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSA5ODAwLDY5MDAgTCA5ODAwLDY5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDAxLDcxMDEgTCAxMDAwMSw3MTAxIFoiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuQ3VzdG9tU2hhcGUiPgogICAgICA8ZyBpZD0iaWQ4Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDA5OSwyOTAwIEMgMTAxNTUsMjkwMCAxMDE5OSwyOTQzIDEwMTk5LDI5OTkgMTAxOTksMzA1NSAxMDE1NSwzMDk5IDEwMDk5LDMwOTkgMTAwNDMsMzA5OSAxMDAwMCwzMDU1IDEwMDAwLDI5OTkgMTAwMDAsMjk0MyAxMDA0MywyOTAwIDEwMDk5LDI5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDAwLDI5MDAgTCAxMDAwMCwyOTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDIwMSwzMTAxIEwgMTAyMDEsMzEwMSBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkOSI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTg5OSwyOTAwIEMgOTk1NSwyOTAwIDk5OTksMjk0MyA5OTk5LDI5OTkgOTk5OSwzMDU1IDk5NTUsMzA5OSA5ODk5LDMwOTkgOTg0MywzMDk5IDk4MDAsMzA1NSA5ODAwLDI5OTkgOTgwMCwyOTQzIDk4NDMsMjkwMCA5ODk5LDI5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDk4MDAsMjkwMCBMIDk4MDAsMjkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwMDEsMzEwMSBMIDEwMDAxLDMxMDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDEwIj4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSA5ODk5LDQ5MDAgQyA5OTU1LDQ5MDAgOTk5OSw0OTQzIDk5OTksNDk5OSA5OTk5LDUwNTUgOTk1NSw1MDk5IDk4OTksNTA5OSA5ODQzLDUwOTkgOTgwMCw1MDU1IDk4MDAsNDk5OSA5ODAwLDQ5NDMgOTg0Myw0OTAwIDk4OTksNDkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTgwMCw0OTAwIEwgOTgwMCw0OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDAwMSw1MTAxIEwgMTAwMDEsNTEwMSBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTEiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDk5LDQ5MDAgQyAxMDE1NSw0OTAwIDEwMTk5LDQ5NDMgMTAxOTksNDk5OSAxMDE5OSw1MDU1IDEwMTU1LDUwOTkgMTAwOTksNTA5OSAxMDA0Myw1MDk5IDEwMDAwLDUwNTUgMTAwMDAsNDk5OSAxMDAwMCw0OTQzIDEwMDQzLDQ5MDAgMTAwOTksNDkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwMDAsNDkwMCBMIDEwMDAwLDQ5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMjAxLDUxMDEgTCAxMDIwMSw1MTAxIFoiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuQ3VzdG9tU2hhcGUiPgogICAgICA8ZyBpZD0iaWQxMiI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwOTksNjkwMCBDIDEwMTU1LDY5MDAgMTAxOTksNjk0MyAxMDE5OSw2OTk5IDEwMTk5LDcwNTUgMTAxNTUsNzA5OSAxMDA5OSw3MDk5IDEwMDQzLDcwOTkgMTAwMDAsNzA1NSAxMDAwMCw2OTk5IDEwMDAwLDY5NDMgMTAwNDMsNjkwMCAxMDA5OSw2OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDAwMCw2OTAwIEwgMTAwMDAsNjkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAyMDEsNzEwMSBMIDEwMjAxLDcxMDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDEzIj4KICAgICAgIDxwYXRoIGZpbGw9InJnYigyNTUsMjU1LDI1NSkiIHN0cm9rZT0ibm9uZSIgZD0iTSA1MTAwLDUyMDAgTCAzNTAwLDUyMDAgMzUwMCwzMDAwIDY3MDAsMzAwMCA2NzAwLDUyMDAgNTEwMCw1MjAwIFoiLz4KICAgICAgIDx0ZXh0IGNsYXNzPSJUZXh0U2hhcGUiPjx0c3BhbiBjbGFzcz0iVGV4dFBhcmFncmFwaCIgZm9udC1mYW1pbHk9IkxpYmVyYXRpb24gU2Fucywgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIzNTNweCIgZm9udC13ZWlnaHQ9IjQwMCI+PHRzcGFuIGNsYXNzPSJUZXh0UG9zaXRpb24iIHg9IjM3NTAiIHk9IjM0MzMiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPlN1YmRpdmlzaW9uIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMzc1MCIgeT0iMzgyNyI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+cG9pbnRzIG5lZWQgdG8gPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIzNzUwIiB5PSI0MjIxIj48dHNwYW4gZmlsbD0icmdiKDAsMCwwKSIgc3Ryb2tlPSJub25lIj5sYW5kIG9uIHRoZSBzYW1lIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMzc1MCIgeT0iNDYxNSI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+bG9jYXRpb24gdG8gPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIzNzUwIiB5PSI1MDA5Ij48dHNwYW4gZmlsbD0icmdiKDAsMCwwKSIgc3Ryb2tlPSJub25lIj5wcmV2ZW50IGNyYWNraW5nPC90c3Bhbj48L3RzcGFuPjwvdHNwYW4+PC90ZXh0PgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5MaW5lU2hhcGUiPgogICAgICA8ZyBpZD0iaWQxNCI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjYwMCw0MjAwIEwgNjY1MSw0MjEzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjcwMyw0MjI3IEwgNjc1NCw0MjQwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjgwNiw0MjUzIEwgNjg1Nyw0MjY2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjkwOCw0MjgwIEwgNjk2MCw0MjkzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzAxMSw0MzA2IEwgNzA2Myw0MzE5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzExNCw0MzMzIEwgNzE2NSw0MzQ2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzIxNyw0MzU5IEwgNzI2OCw0MzcyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzMyMCw0Mzg2IEwgNzM3MSw0Mzk5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzQyMyw0NDEyIEwgNzQ3NCw0NDI2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzUyNSw0NDM5IEwgNzU3Nyw0NDUyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzYyOCw0NDY1IEwgNzY4MCw0NDc5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzczMSw0NDkyIEwgNzc4Miw0NTA1Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzgzNCw0NTE4IEwgNzg4NSw0NTMyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzkzNyw0NTQ1IEwgNzk4OCw0NTU4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODAzOSw0NTcxIEwgODA5MSw0NTg1Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODE0Miw0NTk4IEwgODE5NCw0NjExIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODI0NSw0NjI1IEwgODI5Niw0NjM4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODM0OCw0NjUxIEwgODM5OSw0NjY0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODQ1MSw0Njc4IEwgODUwMiw0NjkxIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODU1Myw0NzA0IEwgODYwNSw0NzE3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODY1Niw0NzMxIEwgODcwOCw0NzQ0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODc1OSw0NzU3IEwgODgxMSw0NzcwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODg2Miw0Nzg0IEwgODkxMyw0Nzk3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODk2NSw0ODEwIEwgOTAxNiw0ODI0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTA2OCw0ODM3IEwgOTExOSw0ODUwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTE3MCw0ODYzIEwgOTIyMiw0ODc3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTI3Myw0ODkwIEwgOTMyNSw0OTAzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTM3Niw0OTE2IEwgOTQyNyw0OTMwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTQ3OSw0OTQzIEwgOTUzMCw0OTU2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTU4Miw0OTY5IEwgOTYzMyw0OTgzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTY4NCw0OTk2IEwgOTcwMCw1MDAwIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTUiPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyNjUwLDI3MDAgTCAxMDcwMCwyNzAwIDEwNzAwLDE1MDAgMTQ2MDAsMTUwMCAxNDYwMCwyNzAwIDEyNjUwLDI3MDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTA5NTAiIHk9IjIwMjQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPkNvcm5lciBwb2ludHMgc3RhcnQgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMDk1MCIgeT0iMjQxOCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+d2l0aCB0aGUgc2FtZSB2YWx1ZXM8L3RzcGFuPjwvdHNwYW4+PC90c3Bhbj48L3RleHQ+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTYiPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyODUwLDg1MDAgTCAxMDkwMCw4NTAwIDEwOTAwLDczMDAgMTQ4MDAsNzMwMCAxNDgwMCw4NTAwIDEyODUwLDg1MDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9Ijc4MjQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPkNvcm5lciBwb2ludHMgc3RhcnQgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMTE1MCIgeT0iODIxOCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+d2l0aCB0aGUgc2FtZSB2YWx1ZXM8L3RzcGFuPjwvdHNwYW4+PC90c3Bhbj48L3RleHQ+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTciPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyNDAwLDUyMDAgTCAxMDkwMCw1MjAwIDEwOTAwLDMzMDAgMTM5MDAsMzMwMCAxMzkwMCw1MjAwIDEyNDAwLDUyMDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjM3ODAiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPk9wcG9zaW5nIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjQxNzQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPmRpcmVjdGlvbnMgb2YgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMTE1MCIgeT0iNDU2OCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+ZWRnZSB3YWxraW5nIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjQ5NjIiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPmZvciBzdWJkaXZpc2lvbjwvdHNwYW4+PC90c3Bhbj48L3RzcGFuPjwvdGV4dD4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuTGluZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTgiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMzAwLDI5MDAgTCAxMDM0MSwyODY3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAzODMsMjgzNCBMIDEwNDI0LDI4MDEiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDQ2NiwyNzY3IEwgMTA1MDcsMjczNCIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNTQ5LDI3MDEgTCAxMDU5MCwyNjY4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA2MzIsMjYzNSBMIDEwNjczLDI2MDIiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDcxNSwyNTY4IEwgMTA3NTYsMjUzNSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNzk3LDI1MDIgTCAxMDgwMCwyNTAwIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkxpbmVTaGFwZSI+CiAgICAgIDxnIGlkPSJpZDE5Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDIwMCw3MTAwIEwgMTAyNDMsNzEzMSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMjg2LDcxNjIgTCAxMDMzMCw3MTkzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAzNzMsNzIyMyBMIDEwNDE2LDcyNTQiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDQ1OSw3Mjg1IEwgMTA1MDIsNzMxNiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNTQ2LDczNDcgTCAxMDU4OSw3Mzc4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA2MzIsNzQwOSBMIDEwNjc1LDc0MzkiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDcxOCw3NDcwIEwgMTA3NjIsNzUwMSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwODA1LDc1MzIgTCAxMDg0OCw3NTYzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA4OTEsNzU5NCBMIDEwOTAwLDc2MDAiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgIDwvZz4KICAgPC9nPgogIDwvZz4KIDwvZz4KPC9zdmc+" alt="precise">
</div>
</div>
<div class="paragraph">
<p>Without any qualifiers, implementations are permitted to perform
optimizations that effectively modify the order or number of operations used
to evaluate an expression, even if those optimizations may produce slightly
different results relative to unoptimized code.</p>
</div>
<div class="paragraph">
<p>The <strong>precise</strong> qualifier ensures that operations contributing to a
variable&#8217;s value are done in their stated order and with operator consistency.
The order is determined by operator precedence and parenthesis, as described in
&#8220;<a href="#operators">Operators</a>&#8221;.
Operator consistency means for each particular operator, for example the
multiply operator (<strong>*</strong>), its operation is always computed with the same
precision.
Specifically, values computed by compiler-generated code must adhere to the
following identities:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>a + b = b + a</p>
</li>
<li>
<p>a * b = b * a</p>
</li>
<li>
<p>a * b + c * d = b * a + c* d = d * c + b * a = &lt;any other mathematically
valid combination&gt;</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>While the following are prevented:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>a + (b + c) is not allowed to become (a + b) + c</p>
</li>
<li>
<p>a * (b * c) is not allowed to become (a * b) * c</p>
</li>
<li>
<p>a * b + c is not allowed to become a single operation <strong>fma</strong>(a, b, c)</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Where <em>a</em>, <em>b</em>, <em>c</em>, and <em>d</em>, are scalars or vectors, not matrices.
(Matrix multiplication generally does not commute.) It is the shader
writer&#8217;s responsibility to express the computation in terms of these rules
and the compiler&#8217;s responsibility to follow these rules.
See the description of <em>gl_TessCoord</em> for the rules the tessellation stages
are responsible for following, which in conjunction with the above allow
avoiding cracking when subdividing.</p>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">precise out vec4 position;</code></pre>
</div>
</div>
<div class="paragraph">
<p>declares that operations used to produce the value of <em>position</em> must be
performed in exactly the order specified in the source code and with all
operators being treated consistently.
As with the <strong>invariant</strong> qualifier (see &#8220;<a href="#the-invariant-qualifier">The
Invariant Qualifier</a>&#8221;), the <strong>precise</strong> qualifier may be used to qualify a
built-in or previously declared user-defined variable as being precise:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out vec3 Color;
precise Color; <span class="comment">// make existing Color be precise</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When applied to a block, a structure type, or a variable of structure type,
<strong>precise</strong> applies to each contained member, recursively.</p>
</div>
<div class="paragraph">
<p>This qualifier will affect the evaluation of an r-value in a particular
function if and only if the result is eventually consumed in the same
function by an l-value qualified as <strong>precise</strong>.
Any other expressions within a function are not affected, including return
values and output parameters not declared as <strong>precise</strong> but that are
eventually consumed outside the function by a variable qualified as
<strong>precise</strong>. Unaffected expressions also include the controlling expressions
in selection and iteration statements and the condition in ternary
operators (<strong>?:</strong>).</p>
</div>
<div class="paragraph">
<p>Some examples of the use of <strong>precise</strong>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 a, b, c, d;
precise out vec4 v;
<span class="predefined-type">float</span> func(<span class="predefined-type">float</span> e, <span class="predefined-type">float</span> f, <span class="predefined-type">float</span> g, <span class="predefined-type">float</span> h)
{
<span class="keyword">return</span> (e*f) + (g*h); <span class="comment">// no constraint on order or operator consistency</span>
}
<span class="predefined-type">float</span> func2(<span class="predefined-type">float</span> e, <span class="predefined-type">float</span> f, <span class="predefined-type">float</span> g, <span class="predefined-type">float</span> h)
{
precise <span class="predefined-type">float</span> result = (e*f) + (g*h); <span class="comment">// ensures same precision for the two multiplies</span>
<span class="keyword">return</span> result;
}
<span class="predefined-type">float</span> func3(<span class="predefined-type">float</span> i, <span class="predefined-type">float</span> j, precise out <span class="predefined-type">float</span> k)
{
k = i * i + j; <span class="comment">// precise, due to &lt;k&gt; declaration</span>
}
<span class="directive">void</span> main()
{
vec3 r = vec3(a * b); <span class="comment">// precise, used to compute v.xyz</span>
vec3 s = vec3(c * d); <span class="comment">// precise, used to compute v.xyz</span>
v.xyz = r + s; <span class="comment">// precise</span>
v.w = (a.w * b.w) + (c.w * d.w); <span class="comment">// precise</span>
v.x = func(a.x, b.x, c.x, d.x); <span class="comment">// values computed in func() are NOT precise</span>
v.x = func2(a.x, b.x, c.x, d.x); <span class="comment">// precise!</span>
func3(a.x * b.x, c.x * d.x, v.x); <span class="comment">// precise!</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>For the purposes of determining if an output from one shader stage matches
an input of the next stage, the <strong>precise</strong> qualifier need not match between
the input and the output.</p>
</div>
<div class="paragraph">
<p>All constant expressions are evaluated as if <strong>precise</strong> was present, whether
or not it is present.
However, as described in &#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221;,
there is no requirement that a compile-time constant expression evaluates to
the same value as a corresponding non-constant expression.</p>
</div>
</div>
<div class="sect2">
<h3 id="memory-qualifiers">4.10. Memory Qualifiers</h3>
<div class="paragraph">
<p>Shader storage blocks, variables declared within shader storage blocks and
variables declared as image types (the basic opaque types with &#8220;<strong>image</strong>&#8221;
in their keyword), can be further qualified with one or more of the
following memory qualifiers:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>coherent</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">memory variable where reads and writes are coherent with
reads and writes from other shader invocations</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>volatile</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">memory variable whose underlying value may be changed at any
point during shader execution by some source other than the
current shader invocation</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>restrict</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">memory variable where use of that variable is the only way
to read and write the underlying memory in the relevant
shader stage</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>readonly</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">memory variable that can be used to read the underlying
memory, but cannot be used to write the underlying memory</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>writeonly</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">memory variable that can be used to write the underlying
memory, but cannot be used to read the underlying memory</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Memory accesses to image variables declared using the <strong>coherent</strong> qualifier
are performed coherently with accesses to the same location from other
shader invocations.
In particular, when reading a variable declared as <strong>coherent</strong>, the values
returned will reflect the results of previously completed writes performed
by other shader invocations.
When writing a variable declared as <strong>coherent</strong>, the values written will be
reflected in subsequent coherent reads performed by other shader
invocations.</p>
</div>
<div class="paragraph">
<p>As described in section
7.12
&#8220;Shader Memory Access&#8221; of the
<a href="#references">OpenGL Specification</a>, shader memory reads and writes complete in a
largely undefined order.
The built-in function <strong>memoryBarrier</strong>() can be used if needed to guarantee
the completion and relative ordering of memory accesses performed by a
single shader invocation.</p>
</div>
<div class="paragraph">
<p>When accessing memory using variables not declared as <strong>coherent</strong>, the memory
accessed by a shader may be cached by the implementation to service future
accesses to the same address.
Memory stores may be cached in such a way that the values written may not be
visible to other shader invocations accessing the same memory.
The implementation may cache the values fetched by memory reads and return
the same values to any shader invocation accessing the same memory, even if
the underlying memory has been modified since the first memory read.
While variables not declared as <strong>coherent</strong> may not be useful for
communicating between shader invocations, using non-coherent accesses may
result in higher performance.</p>
</div>
<div class="paragraph">
<p>Memory accesses to image variables declared using the <strong>volatile</strong> qualifier
must treat the underlying memory as though it could be read or written at
any point during shader execution by some source other than the executing
shader invocation.
When a volatile variable is read, its value must be re-fetched from the
underlying memory, even if the shader invocation performing the read had
previously fetched its value from the same memory.
When a volatile variable is written, its value must be written to the
underlying memory, even if the compiler can conclusively determine that its
value will be overwritten by a subsequent write.
Since the external source reading or writing a <strong>volatile</strong> variable may be
another shader invocation, variables declared as <strong>volatile</strong> are
automatically treated as coherent.</p>
</div>
<div class="paragraph">
<p>Memory accesses to image variables declared using the <strong>restrict</strong> qualifier
may be compiled assuming that the variable used to perform the memory access
is the only way to access the underlying memory using the shader stage in
question.
This allows the compiler to coalesce or reorder loads and stores using
<strong>restrict</strong>-qualified image variables in ways that wouldn&#8217;t be permitted
for image variables not so qualified, because the compiler can assume that
the underlying image won&#8217;t be read or written by other code.
Applications are responsible for ensuring that image memory referenced by
variables qualified with <strong>restrict</strong> will not be referenced using other
variables in the same scope; otherwise, accesses to <strong>restrict</strong>-qualified
variables will have undefined results.</p>
</div>
<div class="paragraph">
<p>Memory accesses to image variables declared using the <strong>readonly</strong> qualifier
may only read the underlying memory, which is treated as read-only memory
and cannot be written to.
It is a compile-time error to pass an image variable qualified with
<strong>readonly</strong> to <strong>imageStore</strong>() or other built-in functions that modify image
memory.</p>
</div>
<div class="paragraph">
<p>Memory accesses to image variables declared using the <strong>writeonly</strong> qualifier
may only write the underlying memory; the underlying memory cannot be read.
It is a compile-time error to pass an image variable qualified with
<strong>writeonly</strong> to <strong>imageLoad</strong>() or other built-in functions that read image
memory.</p>
</div>
<div class="paragraph">
<p>A variable could be qualified as both <strong>readonly</strong> and <strong>writeonly</strong>, disallowing
both read and write. Such variables can still be used with some queries, for
example <strong>imageSize</strong>() and <strong>.length</strong>().</p>
</div>
<div class="paragraph">
<p>The memory qualifiers <strong>coherent</strong>, <strong>volatile</strong>, <strong>restrict</strong>, <strong>readonly</strong>, and
<strong>writeonly</strong> may be used in the declaration of buffer variables (i.e.,
members of shader storage blocks).
When a buffer variable is declared with a memory qualifier, the behavior
specified for memory accesses involving image variables described above
applies identically to memory accesses involving that buffer variable.
It is a compile-time error to assign to a buffer variable qualified with
<strong>readonly</strong> or to read from a buffer variable qualified with <strong>writeonly</strong>.
The combination <strong>readonly</strong> <strong>writeonly</strong> is allowed.</p>
</div>
<div class="paragraph">
<p>Additionally, memory qualifiers may be used at the block-level declaration
of a shader storage block, including the combination <strong>readonly</strong> <strong>writeonly</strong>.
When a block declaration is qualified with a memory qualifier, it is as if
all of its members were declared with the same memory qualifier.
For example, the block declaration</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">coherent buffer Block {
readonly vec4 member1;
vec4 member2;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">buffer Block {
coherent readonly vec4 member1;
coherent vec4 member2;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Memory qualifiers are only supported in the declarations of image variables,
buffer variables, and shader storage blocks; it is an error to use such
qualifiers in any other declarations.</p>
</div>
<div class="paragraph">
<p>When calling user-defined functions, variables qualified with <strong>coherent</strong>,
<strong>volatile</strong>, <strong>readonly</strong>, or <strong>writeonly</strong> may not be passed to functions whose
formal parameters lack such qualifiers.
(See &#8220;<a href="#function-definitions">Function Definitions</a>&#8221; for more detail on
function calling.) It is legal to have any additional memory qualifiers on a
formal parameter, but only <strong>restrict</strong> can be taken away from a calling
argument, by a formal parameter that lacks the <strong>restrict</strong> qualifier.</p>
</div>
<div class="paragraph">
<p>When a built-in function is called, the code generated is to be based on the
actual qualification of the calling argument, not on the list of memory
qualifiers specified on the formal parameter in the prototype.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 funcA(restrict image2D a) { ... }
vec4 funcB(image2D a) { ... }
layout(rgba32f) uniform image2D img1;
layout(rgba32f) coherent uniform image2D img2;
funcA(img1); <span class="comment">// OK, adding &quot;restrict&quot; is allowed</span>
funcB(img2); <span class="comment">// illegal, stripping &quot;coherent&quot; is not</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Layout qualifiers cannot be used on formal function parameters, and layout
qualification is not included in parameter matching.</p>
</div>
<div class="paragraph">
<p>Note that the use of <strong>const</strong> in an image variable declaration is qualifying
the const-ness of the variable being declared, not the image it refers to.
The qualifier <strong>readonly</strong> qualifies the image memory (as accessed through
that variable) while <strong>const</strong> qualifies the variable itself.</p>
</div>
</div>
<div class="sect2">
<h3 id="specialization-constant-qualifier">4.11. Specialization-Constant Qualifier</h3>
<div class="paragraph">
<p>Specialization constants are used only for SPIR-V and declared using the
<strong>constant_id</strong> layout qualifier.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">17</span>) <span class="directive">const</span> <span class="predefined-type">int</span> arraySize = <span class="integer">12</span>;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The above makes a specialization constant with a default value of 12.
The number 17 is an example author-chosen id by which the API or other tools
can later refer to this specific specialization constant.
If it is never changed before final lowering, it will retain the value of
12.
It is a compile-time error to use the <strong>constant_id</strong> qualifier on anything
but SPIR-V generation of a scalar <strong>bool</strong>, <strong>int</strong>, <strong>uint</strong>, <strong>float</strong>, or
<strong>double</strong>.</p>
</div>
<div class="paragraph">
<p>Built-in constants can be declared to be specialization constants.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">31</span>) gl_MaxClipDistances; <span class="comment">// add specialization_id</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The declaration uses just the name of the previously declared built-in
variable, with a <strong>constant_id</strong> layout-qualifier declaration.
It is a compile-time error to do this after the constant has been used:
Constants are strictly either non-specialization constants or specialization
constants, not both.</p>
</div>
<div class="paragraph">
<p>The built-in constant vector <em>gl_WorkGroupSize</em> can be specialized using the
<strong>local_size_{xyz}_id</strong> qualifiers, to individually give the components an id.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x_id = <span class="integer">18</span>, local_size_z_id = <span class="integer">19</span>) in;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This leaves <em>gl_WorkGroupSize.y</em> as a non-specialization constant, with
<em>gl_WorkGroupSize</em> being a partially specialized vector.
Its <em>x</em> and <em>z</em> components can be later specialized, after generating
SPIR-V, using the ids 18 and 19.
These ids are declared independently from declaring the workgroup size:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">32</span>, local_size_y = <span class="integer">32</span>) in; <span class="comment">// size is (32,32,1)</span>
layout(local_size_x_id = <span class="integer">18</span>) in; <span class="comment">// constant_id for x</span>
layout(local_size_z_id = <span class="integer">19</span>) in; <span class="comment">// constant_id for z</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Existing rules for declaring <strong>local_size_x</strong>, <strong>local_size_y</strong>, and
<strong>local_size_z</strong> are not changed.
For the local-size ids, it is a compile-time error to provide different id
values for the same local-size id, or to provide them after any use.
Otherwise, order, placement, number of statements, and replication do not
cause errors.</p>
</div>
<div class="paragraph">
<p>Two arrays sized with specialization constants are the same type only if
sized with the same symbol, and involving no operations.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">51</span>) <span class="directive">const</span> <span class="predefined-type">int</span> aSize = <span class="integer">20</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> pad = <span class="integer">2</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> total = aSize + pad; <span class="comment">// specialization constant</span>
<span class="predefined-type">int</span> a[total], b[total]; <span class="comment">// a and b have the same type</span>
<span class="predefined-type">int</span> c[<span class="integer">22</span>]; <span class="comment">// different type than a or b</span>
<span class="predefined-type">int</span> d[aSize + pad]; <span class="comment">// different type than a, b, or c</span>
<span class="predefined-type">int</span> e[aSize + <span class="integer">2</span>]; <span class="comment">// different type than a, b, c, or d</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Types containing arrays sized with a specialization constant cannot be
compared, assigned as aggregates, declared with an initializer, or used as
an initializer.
They can, however, be passed as arguments to functions having formal
parameters of the same type.
Only the outer-most dimension of a variable declared as an array of arrays
can be a specialization constant, otherwise a compile-time error results.</p>
</div>
<div class="paragraph">
<p>Arrays inside a block may be sized with a specialization constant, but the
block will have a static layout.
Changing the specialized size will not re-layout the block.
In the absence of explicit offsets, the layout will be based on the default
size of the array.</p>
</div>
</div>
<div class="sect2">
<h3 id="order-of-qualification">4.12. Order and Repetition of Qualification</h3>
<div class="paragraph">
<p>When multiple qualifiers are present in a declaration, they may appear in
any order, but they must all appear before the type.
The <strong>layout</strong> qualifier is the only qualifier that can appear more than once.
Further, a declaration can have at most one storage qualifier, at most one
auxiliary storage qualifier, and at most one interpolation qualifier.
If <strong>inout</strong> is used, neither <strong>in</strong> nor <strong>out</strong> may be used.
Multiple memory qualifiers can be used.
Any violation of these rules will cause a compile-time error.</p>
</div>
</div>
<div class="sect2">
<h3 id="empty-declarations">4.13. Empty Declarations</h3>
<div class="paragraph">
<p><em>Empty declarations</em> are declarations without a variable name, meaning no
object is instantiated by the declaration.
Generally, empty declarations are allowed.
Some are useful when declaring structures, while many others have no effect.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span>; <span class="comment">// No effect</span>
<span class="keyword">struct</span> S {<span class="predefined-type">int</span> x;}; <span class="comment">// Defines a struct S</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The combinations of qualifiers that cause compile-time or link-time errors
are the same whether or not the declaration is empty, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">invariant in <span class="predefined-type">float</span> x; <span class="comment">// Error. An input cannot be invariant.</span>
invariant in <span class="predefined-type">float</span>; <span class="comment">// Error even though no variable is declared.</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="operators-and-expressions">5. Operators and Expressions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="operators">5.1. Operators</h3>
<div class="paragraph">
<p>The OpenGL Shading Language has the following operators.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Precedence</th>
<th class="tableblock halign-left valign-top">Operator Class</th>
<th class="tableblock halign-left valign-top">Operators</th>
<th class="tableblock halign-left valign-top">Associativity</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">1 (highest)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">parenthetical grouping</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">( )</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">NA</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">array subscript<br>
function call and constructor structure<br>
field or method selector, swizzle<br>
post fix increment and decrement</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">[ ]<br>
( )<br>
.<br>
++ --</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">prefix increment and decrement<br>
unary</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">++ --<br>
+ - ~ !</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">multiplicative</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">* / %</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">additive</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">+ -</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise shift</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt;&lt; &gt;&gt;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">relational</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&lt; &gt; &lt;= &gt;=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">equality</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">== !=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">9</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise and</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&amp;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">10</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise exclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">^</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">11</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise inclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">|</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">12</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">logical and</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">&amp;&amp;</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">13</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">logical exclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">^^</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">14</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">logical inclusive or</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">||</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">15</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">selection</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">? :</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">16</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Assignment<br>
arithmetic assignments</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">=<br>
+= -=<br>
*= /=<br>
%= &lt;&lt;= &gt;&gt;=<br>
&amp;= ^= |=</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">17 (lowest)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">sequence</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">,</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>There is no address-of operator nor a dereference operator.
There is no typecast operator; constructors are used instead.</p>
</div>
</div>
<div class="sect2">
<h3 id="array-operations">5.2. Array Operations</h3>
<div class="paragraph">
<p>These are now described in &#8220;<a href="#structure-and-array-operations">Structure and
Array Operations</a>&#8221;.</p>
</div>
</div>
<div class="sect2">
<h3 id="function-calls">5.3. Function Calls</h3>
<div class="paragraph">
<p>If a function returns a value, then a call to that function may be used as
an expression, whose type will be the type that was used to declare or
define the function.</p>
</div>
<div class="paragraph">
<p>Function definitions and calling conventions are discussed in
&#8220;<a href="#function-definitions">Function Definitions</a>&#8221;.</p>
</div>
</div>
<div class="sect2">
<h3 id="constructors">5.4. Constructors</h3>
<div class="paragraph">
<p>Constructors use the function call syntax, where the function name is a
type, and the call makes an object of that type.
Constructors are used the same way in both initializers and expressions.
(See &#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221; for details.)
The parameters are used to initialize the constructed value.
Constructors can be used to request a data type conversion to change from
one scalar type to another scalar type, or to build larger types out of
smaller types, or to reduce a larger type to a smaller type.</p>
</div>
<div class="paragraph">
<p>In general, constructors are not built-in functions with predetermined
prototypes.
For arrays and structures, there must be exactly one argument in the
constructor for each element or member.
For the other types, the arguments must provide a sufficient number of
components to perform the initialization, and it is a compile-time error to
include so many arguments that they cannot all be used.
Detailed rules follow.
The prototypes actually listed below are merely a subset of examples.</p>
</div>
<div class="sect3">
<h4 id="conversion-and-scalar-constructors">5.4.1. Conversion and Scalar Constructors</h4>
<div class="paragraph">
<p>Converting between scalar types is done as the following prototypes
indicate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span>(uint) <span class="comment">// converts an unsigned integer to a signed integer</span>
<span class="predefined-type">int</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to an int</span>
<span class="predefined-type">int</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to an int</span>
<span class="predefined-type">int</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a signed integer</span>
uint(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to an unsigned integer</span>
uint(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to an unsigned integer</span>
uint(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to an unsigned integer</span>
uint(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to an unsigned integer</span>
<span class="predefined-type">bool</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a Boolean</span>
<span class="predefined-type">bool</span>(uint) <span class="comment">// converts an unsigned integer value to a Boolean value</span>
<span class="predefined-type">bool</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to a Boolean</span>
<span class="predefined-type">bool</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a Boolean</span>
<span class="predefined-type">float</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a float</span>
<span class="predefined-type">float</span>(uint) <span class="comment">// converts an unsigned integer value to a float value</span>
<span class="predefined-type">float</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to a float</span>
<span class="predefined-type">float</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a float</span>
<span class="predefined-type">double</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a double</span>
<span class="predefined-type">double</span>(uint) <span class="comment">// converts an unsigned integer value to a double</span>
<span class="predefined-type">double</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to a double</span>
<span class="predefined-type">double</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to a double</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When constructors are used to convert a floating-point type to an integer
type, the fractional part of the floating-point value is dropped.
It is undefined to convert a negative floating-point value to an <strong>uint</strong>.</p>
</div>
<div class="paragraph">
<p>Integer values having more bits of precision than a single-precision
floating-point mantissa will lose precision when converted to <strong>float</strong>.</p>
</div>
<div class="paragraph">
<p>When a constructor is used to convert any integer or floating-point type to
a <strong>bool</strong>, 0 and 0.0 are converted to <strong>false</strong>, and non-zero values are
converted to <strong>true</strong>.
When a constructor is used to convert a <strong>bool</strong> to any integer or
floating-point type, <strong>false</strong> is converted to 0 or 0.0, and <strong>true</strong> is
converted to 1 or 1.0.</p>
</div>
<div class="paragraph">
<p>The constructor <strong>int</strong>(<strong>uint</strong>) preserves the bit pattern in the argument,
which will change the argument&#8217;s value if its sign bit is set.
The constructor <strong>uint</strong>(<strong>int</strong>) preserves the bit pattern in the argument,
which will change its value if it is negative.</p>
</div>
<div class="paragraph">
<p>Identity constructors, like <strong>float</strong>(<strong>float</strong>) are also legal, but of little
use.</p>
</div>
<div class="paragraph">
<p>Scalar constructors with non-scalar parameters can be used to take the first
element from a non-scalar.
For example, the constructor <strong>float</strong>(<strong>vec3</strong>) will select the first component
of the <strong>vec3</strong> parameter.</p>
</div>
</div>
<div class="sect3">
<h4 id="vector-and-matrix-constructors">5.4.2. Vector and Matrix Constructors</h4>
<div class="paragraph">
<p>Constructors can be used to create vectors or matrices from a set of
scalars, vectors, or matrices.
This includes the ability to shorten vectors.</p>
</div>
<div class="paragraph">
<p>If there is a single scalar parameter to a vector constructor, it is used to
initialize all components of the constructed vector to that scalar&#8217;s value.
If there is a single scalar parameter to a matrix constructor, it is used to
initialize all the components on the matrix&#8217;s diagonal, with the remaining
components initialized to 0.0.</p>
</div>
<div class="paragraph">
<p>If a vector is constructed from multiple scalars, one or more vectors, or
one or more matrices, or a mixture of these, the vector&#8217;s components will be
constructed in order from the components of the arguments.
The arguments will be consumed left to right, and each argument will have
all its components consumed, in order, before any components from the next
argument are consumed.
Similarly for constructing a matrix from multiple scalars or vectors, or a
mixture of these.
Matrix components will be constructed and consumed in column major order.
In these cases, there must be enough components provided in the arguments to
provide an initializer for every component in the constructed value.
It is a compile-time error to provide extra arguments beyond this last used
argument.</p>
</div>
<div class="paragraph">
<p>If a matrix is constructed from a matrix, then each component (column <em>i</em>,
row <em>j</em>) in the result that has a corresponding component (column <em>i</em>, row
<em>j</em>) in the argument will be initialized from there.
All other components will be initialized to the identity matrix.
If a matrix argument is given to a matrix constructor, it is
a compile-time error to have any other arguments.</p>
</div>
<div class="paragraph">
<p>If the basic type (<strong>bool</strong>, <strong>int</strong>,
<strong>float</strong>, or <strong>double</strong>)
of a parameter to a
constructor does not match the basic type of the object being constructed,
the scalar construction rules (above) are used to convert the parameters.</p>
</div>
<div class="paragraph">
<p>Some useful vector constructors are as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec3(<span class="predefined-type">float</span>) <span class="comment">// initializes each component of the vec3 with the float</span>
vec4(ivec4) <span class="comment">// makes a vec4 with component-wise conversion</span>
vec4(mat2) <span class="comment">// the vec4 is column 0 followed by column 1</span>
vec2(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>) <span class="comment">// initializes a vec2 with 2 floats</span>
ivec3(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>, <span class="predefined-type">int</span>) <span class="comment">// initializes an ivec3 with 3 ints</span>
bvec4(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>) <span class="comment">// uses 4 Boolean conversions</span>
vec2(vec3) <span class="comment">// drops the third component of a vec3</span>
vec3(vec4) <span class="comment">// drops the fourth component of a vec4</span>
vec3(vec2, <span class="predefined-type">float</span>) <span class="comment">// vec3.x = vec2.x, vec3.y = vec2.y, vec3.z = float</span>
vec3(<span class="predefined-type">float</span>, vec2) <span class="comment">// vec3.x = float, vec3.y = vec2.x, vec3.z = vec2.y</span>
vec4(vec3, <span class="predefined-type">float</span>)
vec4(<span class="predefined-type">float</span>, vec3)
vec4(vec2, vec2)</code></pre>
</div>
</div>
<div class="paragraph">
<p>Some examples of these are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 color = vec4(<span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>);
vec4 rgba = vec4(<span class="float">1</span><span class="float">.0</span>); <span class="comment">// sets each component to 1.0</span>
vec3 rgb = vec3(color); <span class="comment">// drop the 4th component</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>To initialize the diagonal of a matrix with all other elements set to zero:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat2(<span class="predefined-type">float</span>)
mat3(<span class="predefined-type">float</span>)
mat4(<span class="predefined-type">float</span>)</code></pre>
</div>
</div>
<div class="paragraph">
<p>That is, <em>result[i][j]</em> is set to the <em>float</em> argument for all \(i
= j\) and set to 0 for all \(i \neq j\).</p>
</div>
<div class="paragraph">
<p>To initialize a matrix by specifying vectors or scalars, the components are
assigned to the matrix elements in column-major order.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat2(vec2, vec2); <span class="comment">// one column per argument</span>
mat3(vec3, vec3, vec3); <span class="comment">// one column per argument</span>
mat4(vec4, vec4, vec4, vec4); <span class="comment">// one column per argument</span>
mat3x2(vec2, vec2, vec2); <span class="comment">// one column per argument</span>
dmat2(dvec2, dvec2);
dmat3(dvec3, dvec3, dvec3);
dmat4(dvec4, dvec4, dvec4, dvec4);
mat2(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// second column</span>
mat3(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// second column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// third column</span>
mat4(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// second column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// third column</span>
<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// fourth column</span>
mat2x3(vec2, <span class="predefined-type">float</span>, <span class="comment">// first column</span>
vec2, <span class="predefined-type">float</span>); <span class="comment">// second column</span>
dmat2x4(dvec3, <span class="predefined-type">double</span>, <span class="comment">// first column</span>
<span class="predefined-type">double</span>, dvec3); <span class="comment">// second column</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>A wide range of other possibilities exist, to construct a matrix from
vectors and scalars, as long as enough components are present to initialize
the matrix.
To construct a matrix from a matrix:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat3x3(mat4x4); <span class="comment">// takes the upper-left 3x3 of the mat4x4</span>
mat2x3(mat4x2); <span class="comment">// takes the upper-left 2x2 of the mat4x4, last row is 0,0</span>
mat4x4(mat3x3); <span class="comment">// puts the mat3x3 in the upper-left, sets the lower right</span>
<span class="comment">// component to 1, and the rest to 0</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="structure-constructors">5.4.3. Structure Constructors</h4>
<div class="paragraph">
<p>Once a structure is defined, and its type is given a name, a constructor is
available with the same name to construct instances of that structure.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> light {
<span class="predefined-type">float</span> intensity;
vec3 position;
};
light lightVar = light(<span class="float">3</span><span class="float">.0</span>, vec3(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>));</code></pre>
</div>
</div>
<div class="paragraph">
<p>The arguments to the constructor will be used to set the structure&#8217;s
members, in order, using one argument per member.
Each argument must be the same type as the member it
sets, or be a type that can be converted to the member&#8217;s type according to
section &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Structure constructors can be used as initializers or in expressions.</p>
</div>
</div>
<div class="sect3">
<h4 id="array-constructors">5.4.4. Array Constructors</h4>
<div class="paragraph">
<p>Array types can also be used as constructor names, which can then be used in
expressions or initializers.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">float</span> c[<span class="integer">3</span>] = <span class="predefined-type">float</span>[<span class="integer">3</span>](<span class="float">5</span><span class="float">.0</span>, <span class="float">7</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>);
<span class="directive">const</span> <span class="predefined-type">float</span> d[<span class="integer">3</span>] = <span class="predefined-type">float</span>[](<span class="float">5</span><span class="float">.0</span>, <span class="float">7</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>);
<span class="predefined-type">float</span> g;
...
<span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[<span class="integer">5</span>](g, <span class="integer">1</span>, g, <span class="float">2</span><span class="float">.3</span>, g);
<span class="predefined-type">float</span> b[<span class="integer">3</span>];
b = <span class="predefined-type">float</span>[<span class="integer">3</span>](g, g + <span class="float">1</span><span class="float">.0</span>, g + <span class="float">2</span><span class="float">.0</span>);</code></pre>
</div>
</div>
<div class="paragraph">
<p>There must be exactly the same number of arguments as the size of the array
being constructed.
If no size is present in the constructor, then the array is explicitly sized
to the number of arguments provided.
The arguments are assigned in order, starting at element 0, to the elements
of the constructed array.
Each argument must be the same type as the element type of the
array, or be
a type that can be converted to the element type of the array according to
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Arrays of arrays are similarly constructed, and the size for any dimension
is <strong class="purple">optional</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 b[<span class="integer">2</span>] = ...;
vec4[<span class="integer">3</span>][<span class="integer">2</span>](b, b, b); <span class="comment">// constructor</span>
vec4[][<span class="integer">2</span>](b, b, b); <span class="comment">// constructor, valid, size deduced</span>
vec4[<span class="integer">3</span>][](b, b, b); <span class="comment">// constructor, valid, size deduced</span>
vec4[][](b, b, b); <span class="comment">// constructor, valid, both sizes deduced</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_texture_combined_sampler_constructors">5.4.5. Texture-Combined Sampler Constructors</h4>
<div class="paragraph">
<p>Texture-combined sampler constructors are only available when targeting Vulkan.</p>
</div>
<div class="paragraph">
<p>Texture-combined sampler types, like <strong>sampler2D</strong>, can be declared with an
initializer
that is a constructor of the same type, and consuming a texture and a
<strong>sampler</strong> or <strong>samplerShadow</strong>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"> layout(...) uniform sampler s; <span class="comment">// handle to filtering information</span>
layout(...) uniform texture2D t; <span class="comment">// handle to a texture</span>
layout(...) in vec2 tCoord;
...
texture(sampler2D(t, s), tCoord);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The result of a texture-combined sampler constructor cannot be assigned to a
variable:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"> ... sampler2D sConstruct = sampler2D(t, s); <span class="comment">// ERROR</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Texture-combined sampler constructors can only be consumed by a function parameter.</p>
</div>
<div class="paragraph">
<p>Texture-combined sampler constructors of arrays are illegal:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"> layout(...) uniform texture2D tArray[<span class="integer">6</span>];
...
... sampler2D[](tArray, s) ... <span class="comment">// ERROR</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Formally:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>every texture-combined sampler type can be used as a constructor</p>
</li>
<li>
<p>the type of the constructor must match the type of the variable being declared</p>
</li>
<li>
<p>the constructor&#8217;s first argument must be a texture type</p>
</li>
<li>
<p>the constructor&#8217;s second argument must be a scalar of type <strong>sampler</strong>
or <strong>samplerShadow</strong></p>
</li>
<li>
<p>the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array)
of the texture type must match that of the constructed type
(that is, the suffixes of the type of the first argument and the
type of the constructor will be spelled the same way)</p>
</li>
<li>
<p>there is no control flow construct (e.g., <code>?:</code>) that consumes any sampler type</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Note: Shadow mismatches are allowed between constructors and the second argument.
Texture-combined non-shadow samplers can be constructed from <strong>samplerShadow</strong> and
texture-combined shadow samplers can be constructed from <strong>sampler</strong>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="vector-components">5.5. Vector and Scalar Components and Length</h3>
<div class="paragraph">
<p>The names of the components of a vector
or scalar
are denoted by a single letter.
As a notational convenience, several letters are associated with each
component based on common usage of position, color or texture coordinate
vectors.
The individual components can be selected by following the variable name
with period (<strong>.</strong>) and then the component name.</p>
</div>
<div class="paragraph">
<p>The component names supported are:</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<colgroup>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ x, y, z, w }</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent points or normals</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ r, g, b, a }</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent colors</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ s, t, p, q }</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent texture coordinates</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The component names <em>x</em>, <em>r</em>, and <em>s</em> are, for example, synonyms for the
same (first) component in a vector.
They are also the names of the only component in a scalar.</p>
</div>
<div class="paragraph">
<p>Note that the third component of the texture coordinate set
has been renamed <em>p</em> so as to avoid the confusion with <em>r</em> (for
red) in a color.</p>
</div>
<div class="paragraph">
<p>Accessing components beyond those declared for the type is
a compile-time error so, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec2 pos;
<span class="predefined-type">float</span> height;
pos.x <span class="comment">// is legal</span>
pos.z <span class="comment">// is illegal</span>
height.x <span class="comment">// is legal</span>
height.y <span class="comment">// is illegal</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The component selection syntax allows multiple components to be selected by
appending their names (from the same name set) after the period (<strong>.</strong>).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 v4;
v4.rgba; <span class="comment">// is a vec4 and the same as just using v4,</span>
v4.rgb; <span class="comment">// is a vec3,</span>
v4.b; <span class="comment">// is a float,</span>
v4.xy; <span class="comment">// is a vec2,</span>
v4.xgba; <span class="comment">// is illegal - the component names do not come from the same set</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>No more than 4 components can be selected.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 v4;
v4.xyzwxy; <span class="comment">// is illegal since it has 6 components</span>
(v4.xyzwxy).xy; <span class="comment">// is illegal since the intermediate value has 6</span>
components</code></pre>
</div>
</div>
<div class="paragraph">
<p>The order of the components can be different to swizzle them, or replicated:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 pos = vec4(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>);
vec4 swiz = pos.wzyx; <span class="comment">// swiz = (4.0, 3.0, 2.0, 1.0)</span>
vec4 dup = pos.xxyy; <span class="comment">// dup = (1.0, 1.0, 2.0, 2.0)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This notation is more concise than the constructor syntax.
To form an r-value, it can be applied to any expression that results in a
vector or scalar r-value.</p>
</div>
<div class="paragraph">
<p>The component group notation can occur on the left hand side of an
expression.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 pos = vec4(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>);
pos.xw = vec2(<span class="float">5</span><span class="float">.0</span>, <span class="float">6</span><span class="float">.0</span>); <span class="comment">// pos = (5.0, 2.0, 3.0, 6.0)</span>
pos.wx = vec2(<span class="float">7</span><span class="float">.0</span>, <span class="float">8</span><span class="float">.0</span>); <span class="comment">// pos = (8.0, 2.0, 3.0, 7.0)</span>
pos.xx = vec2(<span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>); <span class="comment">// illegal - 'x' used twice</span>
pos.xy = vec3(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>); <span class="comment">// illegal - mismatch between vec2 and vec3</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>To form an l-value, swizzling must further be applied to an l-value and
contain no duplicate components. It results in an l-value of scalar or
vector type, depending on number of components specified.</p>
</div>
<div class="paragraph">
<p>Array subscripting syntax can also be applied to vectors (but not to
scalars) to provide numeric indexing.
So in</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 pos;</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>pos[2]</em> refers to the third element of <em>pos</em> and is equivalent to <em>pos.z</em>.
This allows variable indexing into a vector, as well as a generic way of
accessing components.
Any integer expression can be used as the subscript.
The first component is at index zero.
Reading from or writing to a vector using a constant integral expression
with a value that is negative or greater than or equal to the size of the
vector results in a compile-time error.
When indexing with non-constant expressions, behavior is undefined if the
index is negative, or greater than or equal to the size of the vector.</p>
</div>
<div class="paragraph">
<p>The <strong>length</strong>() method may be applied to vectors (but not scalars).
The result is the number of components in the vector.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec3 v;
<span class="directive">const</span> <span class="predefined-type">int</span> L = v.length();</code></pre>
</div>
</div>
<div class="paragraph">
<p>sets the constant <em>L</em> to 3.
The type returned by <strong>.length</strong>() on a vector is <strong>int</strong>, and the value
returned is a constant expression.</p>
</div>
</div>
<div class="sect2">
<h3 id="matrix-components">5.6. Matrix Components</h3>
<div class="paragraph">
<p>The components of a matrix can be accessed using array subscripting syntax.
Applying a single subscript to a matrix treats the matrix as an array of
column vectors, and selects a single column, whose type is a vector of the
same size as the (column size of the) matrix.
The leftmost column is column 0.
A second subscript would then operate on the resulting vector, as defined
earlier for vectors.
Hence, two subscripts select a column and then a row.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat4 m;
m[<span class="integer">1</span>] = vec4(<span class="float">2</span><span class="float">.0</span>); <span class="comment">// sets the second column to all 2.0</span>
m[<span class="integer">0</span>][<span class="integer">0</span>] = <span class="float">1</span><span class="float">.0</span>; <span class="comment">// sets the upper left element to 1.0</span>
m[<span class="integer">2</span>][<span class="integer">3</span>] = <span class="float">2</span><span class="float">.0</span>; <span class="comment">// sets the 4th element of the third column to 2.0</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Behavior is undefined when accessing a component outside the bounds of a
matrix with a non-constant expression.
It is a compile-time error to access a matrix with a constant expression
that is outside the bounds of the matrix.</p>
</div>
<div class="paragraph">
<p>The <strong>length</strong>() method may be applied to matrices.
The result is the number of columns of the matrix.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat3x4 v;
<span class="directive">const</span> <span class="predefined-type">int</span> L = v.length();</code></pre>
</div>
</div>
<div class="paragraph">
<p>sets the constant <em>L</em> to 3.
The type returned by <strong>.length</strong>() on a matrix is <strong>int</strong>, and the value
returned is a constant expression.</p>
</div>
</div>
<div class="sect2">
<h3 id="structure-and-array-operations">5.7. Structure and Array Operations</h3>
<div class="paragraph">
<p>The members of a structure and the <strong>length</strong>() method of an array are
selected using the period (<strong>.</strong>).</p>
</div>
<div class="paragraph">
<p>In total, only the following operators are allowed to operate on arrays and
structures as whole entities:</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<colgroup>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">field selector</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>.</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">equality</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>==</strong> <strong>!=</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">assignment</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>=</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ternary operator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>?:</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Sequence operator</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>,</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">indexing (arrays only)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>[</strong> <strong>]</strong></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The equality operators and assignment operator are only allowed if the two
operands are same size and type.
The operands cannot contain any opaque types.
Structure types must be of the same declared structure.
Both array operands must be
explicitly
sized.
When using the equality operators, two structures are equal if and only if
all the members are component-wise equal, and two arrays are equal if and
only if all the elements are element-wise equal.</p>
</div>
<div class="paragraph">
<p>Array elements are accessed using the array subscript operator (<strong>[ ]</strong>).
An example of accessing an array element is</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">diffuseColor += lightIntensity[<span class="integer">3</span>] * NdotL;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Array indices start at zero.
Array elements are accessed using an expression whose type is <strong>int</strong> or
<strong>uint</strong>.</p>
</div>
<div class="paragraph">
<p>Behavior is undefined if a shader subscripts an array with an index less
than 0 or greater than or equal to the size the array was declared with.</p>
</div>
<div class="paragraph">
<p>Arrays can also be accessed with the method operator (<strong>.</strong>) and the <strong>length</strong>
method to query the size of the array:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">lightIntensity.length() <span class="comment">// return the size of the array</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="assignments">5.8. Assignments</h3>
<div class="paragraph">
<p>Assignments of values to variable names are done with the assignment
operator (<strong>=</strong>):</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><em>lvalue-expression</em> = <em>rvalue-expression</em></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The <em>lvalue-expression</em> evaluates to an l-value.
The assignment operator stores the value of <em>rvalue-expression</em> into the
l-value and returns an r-value with the type and precision of
<em>lvalue-expression</em>.
The <em>lvalue-expression</em> and <em>rvalue-expression</em> must have the same
type, or the expression must have a type in the table in section
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; that converts to the type
of <em>lvalue-expression</em>, in which case an implicit conversion will be done on
the <em>rvalue-expression</em> before the assignment is done.
Any other desired type-conversions must be specified explicitly via a
constructor.
It is a compile-time error if the l-value is not writable.
Variables that are built-in types, entire structures or arrays, structure
members, l-values with the field selector (<strong>.</strong>) applied to select components
or swizzles without repeated fields, l-values within parentheses, and
l-values dereferenced with the array subscript operator (<strong>[ ]</strong>) are all
l-values.
Other binary or unary expressions, function names, swizzles with repeated
fields, and constants cannot be l-values.
The ternary operator (<strong>?:</strong>) is also not allowed as an l-value.
Using an incorrect expression as an l-value results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>Expressions on the left of an assignment are evaluated before expressions on
the right of the assignment.</p>
</div>
<div class="paragraph">
<p>The other assignment operators are</p>
</div>
<div class="ulist">
<ul>
<li>
<p>add into (<strong>+=</strong>)</p>
</li>
<li>
<p>subtract from (<strong>-=</strong>)</p>
</li>
<li>
<p>multiply into (<strong>*=</strong>)</p>
</li>
<li>
<p>divide into (<strong>/=</strong>)</p>
</li>
<li>
<p>modulus into (<strong>%=</strong>)</p>
</li>
<li>
<p>left shift by (<strong>&lt;&lt;=</strong>)</p>
</li>
<li>
<p>right shift by (<strong>&gt;&gt;=</strong>)</p>
</li>
<li>
<p>and into (<strong>&amp;=</strong>)</p>
</li>
<li>
<p>inclusive-or into (<strong>|=</strong>)</p>
</li>
<li>
<p>exclusive-or into (<strong>^=</strong>)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>where the general expression</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><em>lvalue</em> <em>op</em>= <em>expression</em></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><em>lvalue</em> = <em>lvalue</em> <em>op</em> <em>expression</em></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>where <em>lvalue</em> is the value returned by <em>lvalue-expression</em>, <em>op</em> is as
described below, and the <em>lvalue-expression</em> and <em>expression</em> must satisfy
the semantic requirements of both <em>op</em> and equals (<strong>=</strong>).</p>
</div>
<div class="paragraph">
<p>Reading a variable before writing (or initializing) it is legal, however the
value is undefined.</p>
</div>
</div>
<div class="sect2">
<h3 id="expressions">5.9. Expressions</h3>
<div class="paragraph">
<p>Expressions in the shading language are built from the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Constants of type <strong>bool</strong>, all integral types, all floating-point types,
all vector types, and all matrix types.</p>
</li>
<li>
<p>Constructors of all types.</p>
</li>
<li>
<p>Variable names of all types.</p>
</li>
<li>
<p>An array, vector, or matrix expression with the <strong>length</strong>() method
applied.</p>
</li>
<li>
<p>Subscripted arrays.</p>
</li>
<li>
<p>Function calls that return values.
In some cases, function calls returning <strong>void</strong> are also allowed in
expressions as specified below.</p>
</li>
<li>
<p>Component field selectors and array subscript results.</p>
</li>
<li>
<p>Parenthesized expressions.
Any expression, including expressions with void type can be
parenthesized.
Parentheses can be used to group operations.
Operations within parentheses are done before operations across
parentheses.</p>
</li>
<li>
<p>The arithmetic binary operators add (<strong>+</strong>), subtract (<strong>-</strong>), multiply
(<strong>*</strong>), and divide (<strong>/</strong>) operate on integer and floating-point scalars,
vectors, and matrices.
If the fundamental types in the operands do not match, then the
conversions from &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; are
applied to create matching types.
All arithmetic binary operators result in the same fundamental type
(signed integer, unsigned integer, single-precision floating-point, or
double-precision floating-point) as the operands they operate on, after
operand type conversion.
After conversion, the following cases are valid</p>
<div class="ulist">
<ul>
<li>
<p>The two operands are scalars.
In this case the operation is applied, resulting in a scalar.</p>
</li>
<li>
<p>One operand is a scalar, and the other is a vector or matrix.
In this case, the scalar operation is applied independently to each
component of the vector or matrix, resulting in the same size vector or
matrix.</p>
</li>
<li>
<p>The two operands are vectors of the same size.
In this case, the operation is done component-wise resulting in the
same size vector.</p>
</li>
<li>
<p>The operator is add (<strong>+</strong>), subtract (<strong>-</strong>), or divide (<strong>/</strong>), and the
operands are matrices with the same number of rows and the same number
of columns.
In this case, the operation is done component-wise resulting in the
same size matrix.</p>
</li>
<li>
<p>The operator is multiply (<strong>*</strong>), where both operands are matrices or one
operand is a vector and the other a matrix.
A right vector operand is treated as a column vector and a left vector
operand as a row vector.
In all these cases, it is required that the number of columns of the
left operand is equal to the number of rows of the right operand.
Then, the multiply (<strong>*</strong>) operation does a linear algebraic multiply,
yielding an object that has the same number of rows as the left operand
and the same number of columns as the right operand.
&#8220;<a href="#vector-and-matrix-operations">Vector and Matrix Operations</a>&#8221;
explains in more detail how vectors and matrices are operated on.</p>
<div class="openblock">
<div class="content">
<div class="paragraph">
<p>All other cases result in a compile-time error.</p>
</div>
<div class="paragraph">
<p>Use the built-in functions <strong>dot</strong>, <strong>cross</strong>, <strong>matrixCompMult</strong>, and
<strong>outerProduct</strong>, to get, respectively, vector dot product, vector cross
product, matrix component-wise multiplication, and the matrix product of a
column vector times a row vector.</p>
</div>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>The operator modulus (<strong>%</strong>) operates on signed or unsigned integers or
integer vectors.
If the fundamental types in the operands do not match, then the
conversions from &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; are
applied to create matching types.
The operands cannot be vectors of differing size; this is
a compile-time error.
If one operand is a scalar and the other vector, then the scalar is
applied component-wise to the vector, resulting in the same type as the
vector.
If both are vectors of the same size, the result is computed
component-wise.
The resulting value is undefined for any component computed with a
second operand that is zero, while results for other components with
non-zero second operands remain defined.
If both operands are non-negative, then the remainder is non-negative.
Results are undefined if one or both operands are negative.
The operator modulus (<strong>%</strong>) is not defined for any other data types
(non-integer types).</p>
</li>
<li>
<p>The arithmetic unary operators negate (<strong>-</strong>), post- and pre-increment and
decrement (<strong>--</strong> and <strong>++</strong>) operate on integer or floating-point values
(including vectors and matrices).
All unary operators work component-wise on their operands.
These result with the same type they operated on.
For post- and pre-increment and decrement, the expression must be a writable
l-value.
Pre-increment and pre-decrement add or subtract 1 or 1.0 to the contents
of the expression they operate on, and the value of the pre-increment or
pre-decrement expression is the resulting value of that modification.
Post-increment and post-decrement expressions add or subtract 1 or 1.0
to the contents of the expression they operate on, but the resulting
expression has the expression&#8217;s value before the post-increment or
post-decrement was executed.</p>
</li>
<li>
<p>The relational operators greater than (<strong>&gt;</strong>), less than (<strong>&lt;</strong>), greater
than or equal (<strong>&gt;=</strong>), and less than or equal (<strong>&lt;=</strong>) operate only on
scalar integer and scalar floating-point expressions.
The result is scalar Boolean.
Either the operands' types must match, or the conversions from section
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; will be applied to
obtain matching types.
To do component-wise relational comparisons on vectors, use the built-in
functions <strong>lessThan</strong>, <strong>lessThanEqual</strong>, <strong>greaterThan</strong>, and
<strong>greaterThanEqual.</strong></p>
</li>
<li>
<p>The equality operators <strong>equal</strong> (<strong>==</strong>), and not equal (<strong>!=</strong>) operate on
all types except opaque types, aggregates that contain opaque types,
subroutine uniforms, and aggregates that contain subroutine uniforms.
They result in a scalar Boolean.
If the operand types do not match, then there must be a conversion from
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; applied to one operand
that can make them match, in which case this conversion is done.
For vectors, matrices, structures, and arrays, all components, members,
or elements of one operand must equal the corresponding components,
members, or elements in the other operand for the operands to be
considered equal.
To get a vector of component-wise equality results for vectors, use the
built-in functions <strong>equal</strong> and <strong>notEqual</strong>.</p>
</li>
<li>
<p>The logical binary operators and (<strong>&amp;&amp;</strong>), or (<strong>||</strong>), and exclusive or
(<strong>^^</strong>) operate only on two Boolean expressions and result in a Boolean
expression.
And (<strong>&amp;&amp;</strong>) will only evaluate the right hand operand if the left hand
operand evaluated to <strong>true</strong>.
Or (<strong>||</strong>) will only evaluate the right hand operand if the left hand
operand evaluated to <strong>false</strong>.
Exclusive or (<strong>^^</strong>) will always evaluate both operands.</p>
</li>
<li>
<p>The logical unary operator not (<strong>!</strong>).
It operates only on a Boolean expression and results in a Boolean
expression.
To operate on a vector, use the built-in function <strong>not</strong>.</p>
</li>
<li>
<p>The sequence (<strong>,</strong>) operator that operates on expressions by returning
the type and value of the right-most expression in a comma separated
list of expressions.
All expressions are evaluated, in order, from left to right.
The operands to the sequence operator may have <strong>void</strong> type.
Opaque types cannot be used with the sequence (,) operator.</p>
</li>
<li>
<p>The ternary selection operator (<strong>?:</strong>).
It operates on three expressions (<em>exp1</em> <strong>?</strong> <em>exp2</em> <strong>:</strong> <em>exp3</em>).
This operator evaluates the first expression, which must result in a
scalar Boolean.
If the result is true, it selects to evaluate the second expression,
otherwise it selects to evaluate the third expression.
Only one of the second and third expressions is evaluated.
The second and third expressions cannot be opaque types,
or there will be a compile-time error.
Otherwise,
the second and third expressions can be any type, including <strong>void</strong>, as
long their types match, or there is a conversion in section
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; that can be applied to
one of the expressions to make their types match.
This resulting matching type is the type of the entire expression.</p>
</li>
<li>
<p>The one&#8217;s complement operator (<strong>~</strong>).
The operand must be of type signed or unsigned integer or integer
vector, and the result is the one&#8217;s complement of its operand; each bit
of each component is complemented, including any sign bits.</p>
</li>
<li>
<p>The shift operators (<strong>&lt;&lt;</strong>) and (<strong>&gt;&gt;</strong>).
For both operators, the operands must be signed or unsigned integers or
integer vectors.
One operand can be signed while the other is unsigned.
In all cases, the resulting type will be the same type as the left
operand.
If the first operand is a scalar, the second operand has to be a scalar
as well.
If the first operand is a vector, the second operand must be a scalar or
a vector with the same size as the first operand, and the result is
computed component-wise.
The result is undefined if the right operand is negative, or greater
than or equal to the number of bits in the left expression&#8217;s base type.
The value of E1 &lt;&lt; E2 is E1 (interpreted as a bit pattern) left-shifted
by E2 bits.
The value of E1 &gt;&gt; E2 is E1 right-shifted by E2 bit positions.
If E1 is a signed integer, the right-shift will extend the sign bit.
If E1 is an unsigned integer, the right-shift will zero-extend.</p>
</li>
<li>
<p>The bitwise operators and (<strong>&amp;</strong>), exclusive-or (<strong>^</strong>), and inclusive-or
(<strong>|</strong>).
The operands must be of type signed or unsigned integers or integer
vectors.
The operands cannot be vectors of differing size; this is a compile-time error.
If one operand is a scalar and the other a vector, the scalar is applied
component-wise to the vector, resulting in the same type as the vector.
If the fundamental types in the operands do not match, then the
conversions from &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; are
applied to create matching types, and this will be the resulting
fundamental type.
For and (<strong>&amp;</strong>), the result is the bitwise-and function of the operands.
For exclusive-or (<strong>^</strong>), the result is the bitwise exclusive-or function
of the operands.
For inclusive-or (<strong>|</strong>), the result is the bitwise inclusive-or function
of the operands.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For a complete specification of the syntax of expressions, see
&#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221;.</p>
</div>
</div>
<div class="sect2">
<h3 id="vector-and-matrix-operations">5.10. Vector and Matrix Operations</h3>
<div class="paragraph">
<p>With a few exceptions, operations are component-wise.
Usually, when an operator operates on a vector or matrix, it is operating
independently on each component of the vector or matrix, in a component-wise
fashion.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u;
<span class="predefined-type">float</span> f;
v = u + f;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will be equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">v.x = u.x + f;
v.y = u.y + f;
v.z = u.z + f;</code></pre>
</div>
</div>
<div class="paragraph">
<p>And</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u, w;
w = v + u;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will be equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">w.x = v.x + u.x;
w.y = v.y + u.y;
w.z = v.z + u.z;</code></pre>
</div>
</div>
<div class="paragraph">
<p>and likewise for most operators and all integer and floating-point vector
and matrix types.
The exceptions are matrix multiplied by vector, vector multiplied by matrix,
and matrix multiplied by matrix.
These do not operate component-wise, but rather perform the correct linear
algebraic multiply.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u;
mat3 m;
u = v * m;</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">u.x = dot(v, m[<span class="integer">0</span>]); <span class="comment">// m[0] is the left column of m</span>
u.y = dot(v, m[<span class="integer">1</span>]); <span class="comment">// dot(a,b) is the inner (dot) product of a and b</span>
u.z = dot(v, m[<span class="integer">2</span>]);</code></pre>
</div>
</div>
<div class="paragraph">
<p>And</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">u = m * v;</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">u.x = m[<span class="integer">0</span>].x * v.x + m[<span class="integer">1</span>].x * v.y + m[<span class="integer">2</span>].x * v.z;
u.y = m[<span class="integer">0</span>].y * v.x + m[<span class="integer">1</span>].y * v.y + m[<span class="integer">2</span>].y * v.z;
u.z = m[<span class="integer">0</span>].z * v.x + m[<span class="integer">1</span>].z * v.y + m[<span class="integer">2</span>].z * v.z;</code></pre>
</div>
</div>
<div class="paragraph">
<p>And</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat3 m, n, r;
r = m * n;</code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">r[<span class="integer">0</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">0</span>].z;
r[<span class="integer">1</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">1</span>].z;
r[<span class="integer">2</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">2</span>].z;
r[<span class="integer">0</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">0</span>].z;
r[<span class="integer">1</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">1</span>].z;
r[<span class="integer">2</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">2</span>].z;
r[<span class="integer">0</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">0</span>].z;
r[<span class="integer">1</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">1</span>].z;
r[<span class="integer">2</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">2</span>].z;</code></pre>
</div>
</div>
<div class="paragraph">
<p>and similarly for other sizes of vectors and matrices.</p>
</div>
</div>
<div class="sect2">
<h3 id="out-of-bounds-accesses">5.11. Out-of-Bounds Accesses</h3>
<div class="paragraph">
<p>In the subsections described above for array, vector, matrix and structure
accesses, any out-of-bounds access produced undefined behavior.
However, if robust buffer access is enabled via the API, such
accesses will be bound within the memory extent of the active program.
It will not be possible to access memory from other programs, and accesses
will not result in abnormal program termination.
Out-of-bounds reads return undefined values, which include values from other
variables of the active program or zero.
Out-of-bounds writes may be discarded or overwrite other variables of the
active program, depending on the value of the computed index and how this
relates to the extent of the active program&#8217;s memory.
Applications that require defined behavior for out-of-bounds accesses should
range check all computed indices before dereferencing an array.</p>
</div>
</div>
<div class="sect2">
<h3 id="specialization-constant-operations">5.12. Specialization-Constant Operations</h3>
<div class="paragraph">
<p>Specialization-constant operations are only available when targeting SPIR-V.</p>
</div>
<div class="paragraph">
<p>Only some operations discussed in this section may be applied to a
specialization constant and still yield a result that is a specialization
constant.
The operations that do so are listed below.
When a specialization constant is operated on with one of these operators
and with another constant or specialization constant, the result is
implicitly a specialization constant.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>int</strong>(), <strong>uint</strong>(), and <strong>bool</strong>() constructors for type conversions from
any of the following types to any of the following types:</p>
<div class="ulist">
<ul>
<li>
<p><strong>int</strong></p>
</li>
<li>
<p><strong>uint</strong></p>
</li>
<li>
<p><strong>bool</strong></p>
</li>
</ul>
</div>
</li>
<li>
<p>vector versions of the above conversion constructors</p>
</li>
<li>
<p>allowed implicit conversions of the above</p>
</li>
<li>
<p>swizzles (e.g. <code>foo.yx</code>)</p>
</li>
<li>
<p>the following when applied to integer or unsigned integer types:</p>
<div class="ulist">
<ul>
<li>
<p>unary negative (<strong>-</strong>)</p>
</li>
<li>
<p>binary operations (<strong>+</strong>, <strong>-</strong>, <strong>*</strong>, <strong>/</strong>, <strong>%</strong>)</p>
</li>
<li>
<p>shift (<strong>&lt;&lt;</strong>, <strong>&gt;&gt;</strong>)</p>
</li>
<li>
<p>bitwise operations (<strong>&amp;</strong>, <strong>|</strong>, <strong>^</strong>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>the following when applied to integer or unsigned integer scalar types:</p>
<div class="ulist">
<ul>
<li>
<p>comparison (<strong>==</strong>, <strong>!=</strong>, <strong>&gt;</strong>, <strong>&gt;=</strong>, <strong>&lt;</strong>, <strong>&#8656;</strong>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>The following when applied to the Boolean scalar type:</p>
<div class="ulist">
<ul>
<li>
<p>not (<strong>!</strong>)</p>
</li>
<li>
<p>logical operations (<strong>&amp;&amp;</strong>, <strong>||</strong>, <strong>^^</strong>)</p>
</li>
<li>
<p>comparison (<strong>==</strong>, <strong>!=</strong>)</p>
</li>
</ul>
</div>
</li>
<li>
<p>the ternary operator (<strong>?:</strong>)</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="statements-and-structure">6. Statements and Structure</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The fundamental building blocks of the OpenGL Shading Language are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>statements and declarations</p>
</li>
<li>
<p>function definitions</p>
</li>
<li>
<p>selection (<strong>if</strong>-<strong>else</strong> and <strong>switch</strong>-<strong>case</strong>-<strong>default</strong>)</p>
</li>
<li>
<p>iteration (<strong>for</strong>, <strong>while</strong>, and <strong>do</strong>-<strong>while</strong>)</p>
</li>
<li>
<p>jumps (<strong>discard</strong>, <strong>return</strong>, <strong>break</strong>, and <strong>continue</strong>)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The overall structure of a shader is as follows</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>translation-unit</em> : </dt>
<dd>
<p><em>global-declaration</em><br>
<em>translation-unit</em> <em>global-declaration</em></p>
</dd>
<dt class="hdlist1"><em>global-declaration</em> : </dt>
<dd>
<p><em>function-definition</em><br>
<em>declaration</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>That is, a shader is a sequence of declarations and function bodies.
Function bodies are defined as</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>function-definition</em> : </dt>
<dd>
<p><em>function-prototype</em> <strong>{</strong> <em>statement-list</em> <strong>}</strong></p>
</dd>
<dt class="hdlist1"><em>statement-list</em> : </dt>
<dd>
<p><em>statement</em><br>
<em>statement-list</em> <em>statement</em></p>
</dd>
<dt class="hdlist1"><em>statement</em> : </dt>
<dd>
<p><em>compound-statement</em><br>
<em>simple-statement</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Curly braces are used to group sequences of statements into compound
statements.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>compound-statement</em> : </dt>
<dd>
<p><strong>{</strong> <em>statement-list</em> <strong>}</strong></p>
</dd>
<dt class="hdlist1"><em>simple-statement</em> : </dt>
<dd>
<p><em>declaration-statement</em><br>
<em>expression-statement</em><br>
<em>selection-statement</em><br>
<em>iteration-statement</em><br>
<em>jump-statement</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Simple declaration, expression, and jump statements end in a semi-colon.</p>
</div>
<div class="paragraph">
<p>This above is slightly simplified, and the complete grammar specified in
&#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221; should be used as
the definitive specification.</p>
</div>
<div class="paragraph">
<p>Declarations and expressions have already been discussed.</p>
</div>
<div class="sect2">
<h3 id="function-definitions">6.1. Function Definitions</h3>
<div class="paragraph">
<p>As indicated by the grammar above, a valid shader is a sequence of global
declarations and function definitions.
A function is declared as the following example shows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// prototype</span>
returnType functionName (type0 arg0, type1 arg1, ..., typen argn);</code></pre>
</div>
</div>
<div class="paragraph">
<p>and a function is defined like</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// definition</span>
returnType functionName (type0 arg0, type1 arg1, ..., typen argn)
{
<span class="comment">// do some computation</span>
<span class="keyword">return</span> returnValue;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <em>returnType</em> must be present and cannot be void, or:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> functionName (type0 arg0, type1 arg1, ..., typen argn)
{
<span class="comment">// do some computation</span>
<span class="keyword">return</span>; <span class="comment">// optional</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If the type of <em>returnValue</em> does not match <em>returnType</em>, there must be an
implicit conversion in &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221;
that converts the type of <em>returnValue</em> to <em>returnType</em>, or a compile-time
error will result.</p>
</div>
<div class="paragraph">
<p>Each of the <em>typeN</em> must include a type and can optionally include parameter
qualifiers.
The formal argument names (<em>args</em> above) in the declarations are optional
for both the declaration and definition forms.</p>
</div>
<div class="paragraph">
<p>A function is called by using its name followed by a list of arguments in
parentheses.</p>
</div>
<div class="paragraph">
<p>Arrays are allowed as arguments and as the return type.
In both cases, the array must be
explicitly
sized.
An array is passed or returned by using just its name, without brackets, and
the size of the array must match the size specified in the function&#8217;s
declaration.</p>
</div>
<div class="paragraph">
<p>Structures are also allowed as argument types.
The return type can also be a structure.</p>
</div>
<div class="paragraph">
<p>See &#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221; for the
definitive reference on the syntax to declare and define functions.</p>
</div>
<div class="paragraph">
<p>All functions must be either declared with a prototype or defined with a
body before they are called.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> myfunc (<span class="predefined-type">float</span> f, <span class="comment">// f is an input parameter</span>
out <span class="predefined-type">float</span> g); <span class="comment">// g is an output parameter</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Functions that return no value must be declared as <strong>void</strong>.
A <strong>void</strong> function can only use <strong>return</strong> without a return argument, even if
the return argument has <strong>void</strong> type.
Return statements only accept values:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> func1() { }
<span class="directive">void</span> func2() { <span class="keyword">return</span> func1(); } <span class="comment">// illegal return statement</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Only a precision qualifier is allowed on the return type of a function.
Formal parameters can have parameter, precision, and memory qualifiers, but
no other qualifiers.</p>
</div>
<div class="paragraph">
<p>Functions that accept no input arguments need not use <strong>void</strong> in the argument
list because prototypes (or definitions) are required and therefore there is
no ambiguity when an empty argument list &#8220;( )&#8221; is declared.
The idiom &#8220;(<strong>void</strong>)&#8221; as a parameter list is provided for convenience.</p>
</div>
<div class="paragraph">
<p>Function names can be overloaded.
The same function name can be used for multiple functions, as long as the
parameter types differ.
If a function name is declared twice with the same parameter types, then the
return types and all qualifiers must also match, and it is the same function
being declared.</p>
</div>
<div class="paragraph">
<p>For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4 f(in vec4 x, out vec4 y); <span class="comment">// (A)</span>
vec4 f(in vec4 x, out uvec4 y); <span class="comment">// (B) okay, different argument type</span>
vec4 f(in ivec4 x, out dvec4 y); <span class="comment">// (C) okay, different argument type</span>
<span class="predefined-type">int</span> f(in vec4 x, out vec4 y); <span class="comment">// error, only return type differs</span>
vec4 f(in vec4 x, in vec4 y); <span class="comment">// error, only qualifier differs</span>
vec4 f(<span class="directive">const</span> in vec4 x, out vec4 y); <span class="comment">// error, only qualifier differs</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When function calls are resolved, an exact type match for all the arguments
is sought.
If an exact match is found, all other functions are ignored, and the exact
match is used.
If no exact match is found, then the implicit conversions in section
&#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221; will be applied to find a
match.
Mismatched types on input parameters (<strong>in</strong> or <strong>inout</strong> or default) <strong>must</strong>
have a conversion from the calling argument type to the formal parameter
type.
Mismatched types on output parameters (<strong>out</strong> or <strong>inout</strong>) must have a
conversion from the formal parameter type to the calling argument type.</p>
</div>
<div class="paragraph">
<p>If implicit conversions can be used to find more than one matching function,
a single best-matching function is sought.
To determine a best match, the conversions between calling argument and
formal parameter types are compared for each function argument and pair of
matching functions.
After these comparisons are performed, each pair of matching functions are
compared.
A function declaration <em>A</em> is considered a better match than function
declaration <em>B</em> if</p>
</div>
<div class="ulist">
<ul>
<li>
<p>for at least one function argument, the conversion for that argument in
<em>A</em> is better than the corresponding conversion in <em>B</em>; and</p>
</li>
<li>
<p>there is no function argument for which the conversion in <em>B</em> is better
than the corresponding conversion in <em>A</em>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If a single function declaration is considered a better match than every
other matching function declaration, it will be used.
Otherwise, a compile-time semantic error for an ambiguous overloaded
function call occurs.</p>
</div>
<div class="paragraph">
<p>To determine whether the conversion for a single argument in one match is
better than that for another match, the following rules are applied, in
order:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>An exact match is better than a match involving any implicit conversion.</p>
</li>
<li>
<p>A match involving an implicit conversion from <strong>float</strong> to <strong>double</strong> is
better than a match involving any other implicit conversion.</p>
</li>
<li>
<p>A match involving an implicit conversion from either <strong>int</strong> or <strong>uint</strong> to
<strong>float</strong> is better than a match involving an implicit conversion from
either <strong>int</strong> or <strong>uint</strong> to <strong>double</strong>.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>If none of the rules above apply to a particular pair of conversions,
neither conversion is considered better than the other.</p>
</div>
<div class="paragraph">
<p>For the example function prototypes (A), (B), and &#169; above, the following
examples show how the rules apply to different sets of calling argument
types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">f(vec4, vec4) <span class="comment">// exact match of vec4 f(in vec4 x, out vec4 y)</span>
f(vec4, uvec4) <span class="comment">// exact match of vec4 f(in vec4 x, out uvec4 y)</span>
f(vec4, ivec4) <span class="comment">// matched to vec4 f(in vec4 x, out vec4 y)</span>
<span class="comment">// (C) not relevant, can't convert vec4 to</span>
<span class="comment">// ivec4. (A) better than (B) for 2nd</span>
<span class="comment">// argument (rule 3), same on first argument.</span>
f(ivec4, vec4); <span class="comment">// NOT matched. All three match by implicit</span>
<span class="comment">// conversion. (C) is better than (A) and (B)</span>
<span class="comment">// on the first argument. (A) is better than</span>
<span class="comment">// (B) and (C).</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>User-defined functions can have multiple declarations, but only one
definition.</p>
</div>
<div class="paragraph">
<p>A shader can redefine built-in functions.
If a built-in function is redeclared in a shader (i.e., a prototype is
visible) before a call to it, then the linker will only attempt to resolve
that call within the set of shaders that are linked with it.</p>
</div>
<div class="paragraph">
<p>The function <em>main</em> is used as the entry point to a shader executable.
A shader need not contain a function named <em>main</em>, but one shader in a set
of shaders linked together to form a single shader executable must, or a
link-time error results.
This function takes no arguments, returns no value, and must be declared as
type <strong>void</strong>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> main()
{
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The function <em>main</em> can contain uses of <strong>return</strong>.
See &#8220;<a href="#jumps">Jumps</a>&#8221; for more details.</p>
</div>
<div class="paragraph">
<p>It is a compile-time or link-time error to declare or define a function
<strong>main</strong> with any other parameters or return type.</p>
</div>
<div class="sect3">
<h4 id="function-calling-conventions">6.1.1. Function Calling Conventions</h4>
<div class="paragraph">
<p>Functions are called by value-return.
This means input arguments are copied into the function at call time, and
output arguments are copied back to the caller before function exit.
Because the function works with local copies of parameters, there are no
issues regarding aliasing of variables within a function.
To control what parameters are copied in and/or out through a function
definition or declaration:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The keyword <strong>in</strong> is used as a qualifier to denote a parameter is to be
copied in, but not copied out.</p>
</li>
<li>
<p>The keyword <strong>out</strong> is used as a qualifier to denote a parameter is to be
copied out, but not copied in.
This should be used whenever possible to avoid unnecessarily copying
parameters in.</p>
</li>
<li>
<p>The keyword <strong>inout</strong> is used as a qualifier to denote the parameter is to
be both copied in and copied out.
It means the same thing as specifying both <strong>in</strong> and <strong>out</strong>.</p>
</li>
<li>
<p>A function parameter declared with no such qualifier means the same
thing as specifying <strong>in</strong>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>All arguments are evaluated at call time, exactly once, in order, from left
to right.
Evaluation of an <strong>in</strong> parameter results in a value that is copied to the
formal parameter.
Evaluation of an <strong>out</strong> parameter results in an l-value that is used to copy
out a value when the function returns.
Evaluation of an <strong>inout</strong> parameter results in both a value and an l-value;
the value is copied to the formal parameter at call time and the l-value is
used to copy out a value when the function returns.</p>
</div>
<div class="paragraph">
<p>The order in which output parameters are copied back to the caller is
undefined.</p>
</div>
<div class="paragraph">
<p>If the function matching described in the previous section required argument
type conversions, these conversions are applied at copy-in and copy-out
times.</p>
</div>
<div class="paragraph">
<p>In a function, writing to an input-only parameter is allowed.
Only the function&#8217;s copy is modified.
This can be prevented by declaring a parameter with the <strong>const</strong> qualifier.</p>
</div>
<div class="paragraph">
<p>When calling a function, expressions that do not evaluate to l-values cannot
be passed to parameters declared as <strong>out</strong> or <strong>inout</strong>, or a compile-time error
results.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>function-prototype</em> : </dt>
<dd>
<p><em>precision-qualifier</em> <em>type</em> <em>function-name</em> <strong>(</strong> <em>parameter-qualifiers</em>
<em>precision-qualifier</em> <em>type</em> <em>name</em> <em>array-specifier</em> <strong>,</strong> &#8230;&#8203;
<strong>)</strong></p>
</dd>
<dt class="hdlist1"><em>type</em> : </dt>
<dd>
<p>any basic type, array type, structure name, or structure definition</p>
</dd>
<dt class="hdlist1"><em>parameter-qualifiers</em> : </dt>
<dd>
<p><em>empty</em><br>
list of <em>parameter-qualifier</em></p>
</dd>
<dt class="hdlist1"><em>parameter-qualifier</em> : </dt>
<dd>
<p><strong>const</strong><br>
<strong>in</strong><br>
<strong>out</strong><br>
<strong>inout</strong><br>
<strong>precise</strong><br>
<em>memory-qualifier</em><br>
<em>precision-qualifier</em></p>
</dd>
<dt class="hdlist1"><em>name</em> : </dt>
<dd>
<p>empty<br>
identifier</p>
</dd>
<dt class="hdlist1"><em>array-specifier</em> : </dt>
<dd>
<p>empty<br>
<strong>[</strong> <em>integral-constant-expression</em> <strong>]</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The <strong>const</strong> qualifier cannot be used with <strong>out</strong> or <strong>inout</strong>, or
a compile-time error results.
The above is used both for function declarations (i.e., prototypes) and for
function definitions.
Hence, function definitions can have unnamed arguments.</p>
</div>
<div class="paragraph">
<p>Recursion is not allowed, not even statically.
Static recursion is present if the static function-call graph of a program
contains cycles.
This includes all potential function calls through variables declared as
<strong>subroutine</strong> <strong>uniform</strong> (described below).
It is a compile-time or link-time error if a single compilation unit
(shader) contains either static recursion or the potential for recursion
through subroutine variables.</p>
</div>
</div>
<div class="sect3">
<h4 id="subroutines">6.1.2. Subroutines</h4>
<div class="paragraph">
<p>Subroutines provide a mechanism allowing shaders to be compiled in a manner
where the target of one or more function calls can be changed at run-time
without requiring any shader recompilation.
For example, a single shader may be compiled with support for multiple
illumination algorithms to handle different kinds of lights or surface
materials.
An application using such a shader may switch illumination algorithms by
changing the value of its subroutine uniforms.
To use subroutines, a subroutine type is declared, one or more functions are
associated with that subroutine type, and a subroutine variable of that type
is declared.
The function currently assigned to the variable function is then called by
using function calling syntax replacing a function name with the name of the
subroutine variable.
Subroutine variables are uniforms, and are assigned to specific functions
only through commands (<strong>UniformSubroutinesuiv</strong>) in the OpenGL API.</p>
</div>
<div class="paragraph">
<p>Subroutine functionality is not available when generating SPIR-V.</p>
</div>
<div class="paragraph">
<p>Subroutine types are declared using a statement similar to a function
declaration, with the <strong>subroutine</strong> keyword, as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">subroutine returnType subroutineTypeName(type0 arg0, type1 arg1,
..., typen argn);</code></pre>
</div>
</div>
<div class="paragraph">
<p>As with function declarations, the formal argument names (<em>args</em> above) are
optional.
Functions are associated with subroutine types of matching declarations by
defining the function with the <strong>subroutine</strong> keyword and a list of subroutine
types the function matches:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">subroutine(subroutineTypeName0, ..., subroutineTypeNameN)
returnType functionName(type0 arg0, type1 arg1, ..., typen argn)
{ ... } <span class="comment">// function body</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>It is a compile-time error if arguments and return type don&#8217;t match between
the function and each associated subroutine type.</p>
</div>
<div class="paragraph">
<p>Functions declared with <strong>subroutine</strong> must include a body.
An overloaded function cannot be declared with <strong>subroutine</strong>; a program will
fail to compile or link if any shader or stage contains two or more
functions with the same name if the name is associated with a subroutine
type.</p>
</div>
<div class="paragraph">
<p>A function declared with <strong>subroutine</strong> can also be called directly with a
static use of <em>functionName</em>, as is done with non-subroutine function
declarations and calls.</p>
</div>
<div class="paragraph">
<p>Subroutine type variables are required to be <em>subroutine uniforms</em>, and are
declared with a specific subroutine type in a subroutine uniform variable
declaration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">subroutine uniform subroutineTypeName subroutineVarName;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Subroutine uniform variables are called the same way functions are called.
When a subroutine variable (or an element of a subroutine variable array) is
associated with a particular function, all function calls through that
variable will call that particular function.</p>
</div>
<div class="paragraph">
<p>Unlike other uniform variables, subroutine uniform variables are scoped to
the shader execution stage the variable is declared in.</p>
</div>
<div class="paragraph">
<p>Subroutine variables may be declared as explicitly-sized arrays, which can
be indexed only with dynamically uniform expressions.</p>
</div>
<div class="paragraph">
<p>It is a compile-time error to use the <strong>subroutine</strong> keyword in any places
other than (as shown above) to</p>
</div>
<div class="ulist">
<ul>
<li>
<p>declare a subroutine type at global scope,</p>
</li>
<li>
<p>declare a function as a subroutine, or</p>
</li>
<li>
<p>declare a subroutine variable at global scope.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="selection">6.2. Selection</h3>
<div class="paragraph">
<p>Conditional control flow in the shading language is done by either <strong>if</strong>,
<strong>if</strong>-<strong>else</strong>, or <strong>switch</strong> statements:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>selection-statement</em> : </dt>
<dd>
<p><strong>if</strong> <strong>(</strong> <em>bool-expression</em> <strong>)</strong> <em>statement</em><br>
<strong>if</strong> <strong>(</strong> <em>bool-expression</em> <strong>)</strong> <em>statement</em> <strong>else</strong> <em>statement</em><br>
<strong>switch</strong> <strong>(</strong> <em>init-expression</em> <strong>)</strong> <strong>{</strong> <em>switch-statement-list<sub>opt</sub></em> <strong>}</strong></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Where <em>switch-statement-list</em> is a nested scope containing a list of zero or
more <em>switch-statement</em> and other statements defined by the language, where
<em>switch-statement</em> adds some forms of labels.
That is</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>switch-statement-list</em> : </dt>
<dd>
<p><em>switch-statement</em><br>
<em>switch-statement-list</em> <em>switch-statement</em></p>
</dd>
<dt class="hdlist1"><em>switch-statement</em> : </dt>
<dd>
<p><strong>case</strong> <em>constant-expression</em> <strong>:</strong><br>
<strong>default</strong> <strong>:</strong> <em>statement</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Note the above grammar&#8217;s purpose is to aid discussion in this section; the
normative grammar is in &#8220;<a href="#shading-language-grammar">Shading Language
Grammar</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>If an <strong>if</strong>-expression evaluates to <strong>true</strong>, then the first <em>statement</em> is
executed.
If it evaluates to <strong>false</strong> and there is an <strong>else</strong> part then the second
<em>statement</em> is executed.</p>
</div>
<div class="paragraph">
<p>Any expression whose type evaluates to a Boolean can be used as the
conditional expression <em>bool-expression</em>.
Vector types are not accepted as the expression to <strong>if</strong>.</p>
</div>
<div class="paragraph">
<p>Conditionals can be nested.</p>
</div>
<div class="paragraph">
<p>The type of <em>init-expression</em> in a <strong>switch</strong> statement must be a scalar
integer.
The type of the <em>constant-expression</em> value in a case label also must be a
scalar integer.
When any pair of these values is tested for &#8220;equal value&#8221; and the types do
not match, an implicit conversion will be done to convert the <strong>int</strong> to a
<strong>uint</strong> (see &#8220;<a href="#implicit-conversions">Implicit Conversions</a>&#8221;) before the
compare is done.
If a <strong>case</strong> label has a <em>constant-expression</em> of equal value to
<em>init-expression</em>, execution will continue after that label.
Otherwise, if there is a <strong>default</strong> label, execution will continue after that
label.
Otherwise, execution skips the rest of the switch statement.
It is a compile-time error to have more than one <strong>default</strong> or a replicated
<em>constant-expression</em>.
A <strong>break</strong> statement not nested in a loop or other switch statement (either
not nested or nested only in <strong>if</strong> or <strong>if</strong>-<strong>else</strong> statements) will also skip
the rest of the switch statement.
Fall through labels are allowed, but it is a compile-time error to have no
statement between a label and the end of the switch statement.
No statements are allowed in a switch statement before the first <strong>case</strong>
statement.</p>
</div>
<div class="paragraph">
<p>The <strong>case</strong> and <strong>default</strong> labels can only appear within a <strong>switch</strong> statement.
No <strong>case</strong> or <strong>default</strong> labels can be nested inside other statements or
compound statements within their corresponding <strong>switch</strong>.</p>
</div>
</div>
<div class="sect2">
<h3 id="iteration">6.3. Iteration</h3>
<div class="paragraph">
<p>For, while, and do loops are allowed as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">for</span> (init-expression; condition-expression; loop-expression)
sub-statement
<span class="keyword">while</span> (condition-expression)
sub-statement
<span class="keyword">do</span>
statement
<span class="keyword">while</span> (condition-expression)</code></pre>
</div>
</div>
<div class="paragraph">
<p>See &#8220;<a href="#shading-language-grammar">Shading Language Grammar</a>&#8221; for the
definitive specification of loops.</p>
</div>
<div class="paragraph">
<p>The <strong>for</strong> loop first evaluates the <em>init-expression</em>, then the
<em>condition-expression</em>.
If the <em>condition-expression</em> evaluates to <strong>true</strong>, then the body of the loop
is executed.
After the body is executed, a <strong>for</strong> loop will then evaluate the
<em>loop-expression</em>, and then loop back to evaluate the
<em>condition-expression</em>, repeating until the <em>condition-expression</em> evaluates
to <strong>false</strong>.
The loop is then exited, skipping its body and skipping its
<em>loop-expression</em>.
Variables modified by the <em>loop-expression</em> maintain their value after the
loop is exited, provided they are still in scope.
Variables declared in <em>init-expression</em> or <em>condition-expression</em> are only
in scope until the end of the sub-statement of the <strong>for</strong> loop.</p>
</div>
<div class="paragraph">
<p>The <strong>while</strong> loop first evaluates the <em>condition-expression</em>.
If <strong>true</strong>, then the body is executed.
This is then repeated, until the <em>condition-expression</em> evaluates to
<strong>false</strong>, exiting the loop and skipping its body.
Variables declared in the <em>condition-expression</em> are only in scope until the
end of the sub-statement of the <strong>while</strong> loop.</p>
</div>
<div class="paragraph">
<p>The <strong>do</strong>-<strong>while</strong> loop first executes the body, then executes the
<em>condition-expression</em>.
This is repeated until <em>condition-expression</em> evaluates to <strong>false</strong>, and then
the loop is exited.</p>
</div>
<div class="paragraph">
<p>Expressions for <em>condition-expression</em> must evaluate to a Boolean.</p>
</div>
<div class="paragraph">
<p>Both the <em>condition-expression</em> and the <em>init-expression</em> can declare and
initialize a variable, except in the <strong>do</strong>-<strong>while</strong> loop, which cannot declare
a variable in its <em>condition-expression</em>.
The variable&#8217;s scope lasts only until the end of the sub-statement that
forms the body of the loop.</p>
</div>
<div class="paragraph">
<p>Loops can be nested.</p>
</div>
<div class="paragraph">
<p>Non-terminating loops are allowed.
The consequences of very long or non-terminating loops are platform
dependent.</p>
</div>
</div>
<div class="sect2">
<h3 id="jumps">6.4. Jumps</h3>
<div class="paragraph">
<p>These are the jumps:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>jump_statement</em> : </dt>
<dd>
<p><strong>continue</strong> <strong>;</strong><br>
<strong>break</strong> <strong>;</strong><br>
<strong>return</strong> <strong>;</strong><br>
<strong>return</strong> <em>expression</em> <strong>;</strong><br>
<strong>discard</strong> <strong>;</strong> // in the fragment shader language only</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>There is no &#8220;goto&#8221; or other non-structured flow of control.</p>
</div>
<div class="paragraph">
<p>The <strong>continue</strong> jump is used only in loops.
It skips the remainder of the body of the inner-most loop of which it is
inside.
For <strong>while</strong> and <strong>do</strong>-<strong>while</strong> loops, this jump is to the next evaluation of
the loop <em>condition-expression</em> from which the loop continues as previously
defined.
For <strong>for</strong> loops, the jump is to the <em>loop-expression</em>, followed by the
<em>condition-expression</em>.</p>
</div>
<div class="paragraph">
<p>The <strong>break</strong> jump can also be used only in loops and <strong>switch</strong> statements.
It is simply an immediate exit of the inner-most loop or <strong>switch</strong> statements
containing the <strong>break</strong>.
No further execution of <em>condition-expression</em>, <em>loop-expression</em>, or
<em>switch-statement</em> is done.</p>
</div>
<div class="paragraph">
<p>The <strong>discard</strong> keyword is only allowed within fragment shaders.
It can be used within a fragment shader to abandon the operation on the
current fragment.
This keyword causes the fragment to be discarded and no updates to any
buffers will occur.
Any prior writes to other buffers such as shader storage buffers are
unaffected.
Control flow exits the shader, and subsequent implicit or explicit
derivatives are undefined when this control flow is non-uniform (meaning
different fragments within the primitive take different control paths).
It would typically be used within a conditional statement, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">if</span> (intensity &lt; <span class="float">0</span><span class="float">.0</span>)
discard;</code></pre>
</div>
</div>
<div class="paragraph">
<p>A fragment shader may test a fragment&#8217;s alpha value and discard the fragment
based on that test.
However, it should be noted that coverage testing occurs after the fragment
shader runs, and the coverage test can change the alpha value.</p>
</div>
<div class="paragraph">
<p>The <strong>return</strong> jump causes immediate exit of the current function.
If it has <em>expression</em> then that is the return value for the function.</p>
</div>
<div class="paragraph">
<p>The function <em>main</em> can use <strong>return</strong>.
This simply causes <em>main</em> to exit in the same way as when the end of the
function had been reached.
It does not imply a use of <strong>discard</strong> in a fragment shader.
Using <strong>return</strong> in <em>main</em> before defining outputs will have the same behavior
as reaching the end of <em>main</em> before defining outputs.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="built-in-variables">7. Built-In Variables</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="built-in-language-variables">7.1. Built-In Language Variables</h3>
<div class="paragraph">
<p>Some operations occur outside shader functionality and need to provide
values to or receive values from shader executables.
Shaders communicate with fixed-function pipeline stages, and
optionally with other shader executables, through the use of built-in input
and output variables.</p>
</div>
<div class="sect3">
<h4 id="vertex-shader-special-variables">7.1.1. Vertex Shader Special Variables</h4>
<div class="paragraph">
<p>The built-in vertex shader variables are intrinsically declared as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in <span class="predefined-type">int</span> gl_VertexID; <span class="comment">// only present when not targeting Vulkan</span>
in <span class="predefined-type">int</span> gl_InstanceID; <span class="comment">// only present when not targeting Vulkan</span>
in <span class="predefined-type">int</span> gl_VertexIndex; <span class="comment">// only present when targeting Vulkan</span>
in <span class="predefined-type">int</span> gl_InstanceIndex; <span class="comment">// only present when targeting Vulkan</span>
in <span class="predefined-type">int</span> gl_DrawID;
in <span class="predefined-type">int</span> gl_BaseVertex;
in <span class="predefined-type">int</span> gl_BaseInstance;
out gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The variable <em>gl_Position</em> is intended for writing the homogeneous vertex
position.
It can be written at any time during shader execution.
This value will be used by primitive assembly, clipping, culling, and other
fixed functionality operations, if present, that operate on primitives after
vertex processing has occurred.
Its value is undefined after the vertex processing stage if the vertex
shader executable does not write <em>gl_Position</em>.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_PointSize</em> is intended for a shader to write the size of
the point to be rasterized.
It is measured in pixels.
If <em>gl_PointSize</em> is not written to, its value is undefined in subsequent
pipe stages.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_ClipDistance</em> is intended for writing clip distances, and
provides the forward compatible mechanism for controlling user clipping.
The element <em>gl_ClipDistance[i]</em> specifies a clip distance for each plane
<em>i</em>.
A distance of 0 means the vertex is on the plane, a positive distance means
the vertex is inside the clip plane, and a negative distance means the point
is outside the clip plane.
The clip distances will be linearly interpolated across the primitive and
the portion of the primitive with interpolated distances less than 0 will be
clipped.</p>
</div>
<div class="paragraph">
<p>The <em>gl_ClipDistance</em> array is predeclared as unsized and must be explicitly
sized by the shader either redeclaring it with a size or implicitly sized by
indexing it only with constant integral expressions.
This needs to size the array to include all the clip planes that are enabled
via the API; if the size does not include all enabled planes,
results are undefined.
The size can be at most <em>gl_MaxClipDistances</em>.
The number of varying components (see <em>gl_MaxVaryingComponents)</em> consumed by
<em>gl_ClipDistance</em> will match the size of the array, no matter how many
planes are enabled.
The shader must also set all values in <em>gl_ClipDistance</em> that have been
enabled via the API, or results are undefined.
Values written into <em>gl_ClipDistance</em> for planes that are not enabled have
no effect.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_CullDistance</em> provides a mechanism for controlling user
culling.
The element <em>gl_CullDistance[i]</em> specifies a cull distance for plane <em>i</em>.
A distance of 0 means the vertex is on the plane, a positive distance means
the vertex is inside the cull volume, and a negative distance means the
point is outside the cull volume.
Primitives whose vertices all have a negative cull distance for plane <em>i</em>
will be discarded.</p>
</div>
<div class="paragraph">
<p>The <em>gl_CullDistance</em> array is predeclared as unsized and must be sized by
the shader either redeclaring it with a size or indexing it only with
constant integral expressions.
The size determines the number and set of enabled cull distances and can be
at most <em>gl_MaxCullDistances</em>.
The number of varying components (see <em>gl_MaxVaryingComponents</em>) consumed by
<em>gl_CullDistance</em> will match the size of the array.
Shaders writing <em>gl_CullDistance</em> must write all enabled distances, or
culling results are undefined.</p>
</div>
<div class="paragraph">
<p>As an output variable, <em>gl_CullDistance</em> provides the place for the shader
to write these distances.
As an input in all but the fragment language, it reads the values written in
the previous shader stage.
In the fragment language, <em>gl_CullDistance</em> array contains linearly
interpolated values for the vertex values written by a shader to the
<em>gl_CullDistance</em> vertex output variable.</p>
</div>
<div class="paragraph">
<p>It is a compile-time or link-time error for the set of shaders forming a
program to have the sum of the sizes of the <em>gl_ClipDistance</em> and
<em>gl_CullDistance</em> arrays to be larger than
<em>gl_MaxCombinedClipAndCullDistances</em>.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_VertexID</em> is a vertex shader input variable that holds an
integer index for the vertex, as defined under &#8220;Shader Inputs&#8221; in section
11.1.3.9 &#8220;Shader Inputs&#8221; of the <a href="#references">OpenGL Specification</a>.
It is only present when not targeting Vulkan.
Even when present, the value of <em>gl_VertexID</em> is not always defined.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_InstanceID</em> is a vertex shader input variable that holds
the instance number of the current primitive in an instanced draw call (see
&#8220;Shader Inputs&#8221; in section 11.1.3.9 &#8220;Shader Inputs&#8221; of the
<a href="#references">OpenGL Specification</a>).
It is only present when not targeting Vulkan.
If the current primitive does not come from an instanced draw call, the
value of <em>gl_InstanceID</em> is zero.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_VertexIndex</em> is a vertex language input variable that
holds an integer index for the vertex, relative to a base.
It is only present when targeting Vulkan.
Even when present, the value of <em>gl_VertexIndex</em> is not always defined.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_InstanceIndex</em> is a vertex language input variable that
holds the instance number of the current primitive in an instanced draw
call, relative to a base.
It is only present when targeting Vulkan.
If the current primitive does not come from an instanced draw call,
the value of gl_InstanceIndex is zero.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_DrawID</em> is a vertex shader input variable that holds the
integer index of the drawing command to which the current vertex belongs
(see &#8220;Shader Inputs&#8221; in section 11.1.3.9 of the <a href="#references">OpenGL Specification</a>).
If the vertex is not invoked by a <strong>Multi</strong>* form of a draw command, then the
value of <em>gl_DrawID</em> is zero.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_BaseVertex</em> is a vertex shader input variable that holds
the integer value passed to the baseVertex parameter of the command that
resulted in the current shader invocation (see &#8220;Shader Inputs&#8221; in section
11.1.3.9 of the <a href="#references">OpenGL Specification</a>).</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_BaseInstance</em> is a vertex shader input variable that holds
the integer value passed to the baseInstance parameter of the command that
resulted in the current shader invocation (see &#8220;Shader Inputs&#8221; in section
11.1.3.9 of the <a href="#references">OpenGL Specification</a>).</p>
</div>
</div>
<div class="sect3">
<h4 id="tessellation-control-shader-special-variables">7.1.2. Tessellation Control Shader Special Variables</h4>
<div class="paragraph">
<p>In the tessellation control shader, built-in variables are intrinsically
declared as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
} gl_in[gl_MaxPatchVertices];
in <span class="predefined-type">int</span> gl_PatchVerticesIn;
in <span class="predefined-type">int</span> gl_PrimitiveID;
in <span class="predefined-type">int</span> gl_InvocationID;
out gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
} gl_out[];
patch out <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>];
patch out <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>];</code></pre>
</div>
</div>
<div class="sect4">
<h5 id="tessellation-control-input-variables">Tessellation Control Input Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em>
contain the values written in the previous shader stage to the corresponding
outputs.</p>
</div>
<div class="paragraph">
<p><em>gl_PatchVerticesIn</em> contains the number of vertices in the input patch
being processed by the shader.
A single shader can read patches of differing sizes, so the value of
<em>gl_PatchVerticesIn</em> may differ between patches.</p>
</div>
<div class="paragraph">
<p><em>gl_PrimitiveID</em> contains the number of primitives processed by the shader
since the current set of rendering primitives was started.</p>
</div>
<div class="paragraph">
<p><em>gl_InvocationID</em> contains the number of the output patch vertex assigned to
the tessellation control shader invocation.
It is assigned integer values in the range [0, N-1], where N is the number
of output patch vertices per primitive.</p>
</div>
</div>
<div class="sect4">
<h5 id="tessellation-control-output-variables">Tessellation Control Output Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are
used in the same fashion as the corresponding output variables in the vertex
shader.</p>
</div>
<div class="paragraph">
<p>The values written to <em>gl_TessLevelOuter</em> and <em>gl_TessLevelInner</em> are
assigned to the corresponding outer and inner tessellation levels of the
output patch.
They are used by the tessellation primitive generator to control primitive
tessellation and may be read by tessellation evaluation shaders.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="tessellation-evaluation-shader-special-variables">7.1.3. Tessellation Evaluation Shader Special Variables</h4>
<div class="paragraph">
<p>In the tessellation evaluation shader, built-in variables are intrinsically
declared as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
} gl_in[gl_MaxPatchVertices];
in <span class="predefined-type">int</span> gl_PatchVerticesIn;
in <span class="predefined-type">int</span> gl_PrimitiveID;
in vec3 gl_TessCoord;
patch in <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>];
patch in <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>];
out gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
};</code></pre>
</div>
</div>
<div class="sect4">
<h5 id="tessellation-evaluation-input-variables">Tessellation Evaluation Input Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em>
contain the values written in the previous shader stage to the corresponding
outputs.</p>
</div>
<div class="paragraph">
<p><em>gl_PatchVerticesIn</em> and <em>gl_PrimitiveID</em> are defined in the same fashion as
the corresponding input variables in the tessellation control shader.</p>
</div>
<div class="paragraph">
<p><em>gl_TessCoord</em> specifies a three-component <em>(u,v,w)</em> vector identifying the
position of the vertex being processed by the shader relative to the
primitive being tessellated.
Its values will obey the properties</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_TessCoord.x == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.x) <span class="comment">// two operations performed</span>
gl_TessCoord.y == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.y) <span class="comment">// two operations performed</span>
gl_TessCoord.z == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.z) <span class="comment">// two operations performed</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>to aid in replicating subdivision computations.</p>
</div>
<div class="paragraph">
<p>If a tessellation control shader is active, the input variables
<em>gl_TessLevelOuter</em> and <em>gl_TessLevelInner</em> are filled with the
corresponding outputs written by the tessellation control shader.
Otherwise, they are assigned with default tessellation levels specified in
section 11.2.3.3 &#8220;Tessellation Evaluation Shader Inputs&#8221; of the
<a href="#references">OpenGL Specification</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="tessellation-evaluation-output-variables">Tessellation Evaluation Output Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are
used in the same fashion as the corresponding output variables in the vertex
shader.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="geometry-shader-special-variables">7.1.4. Geometry Shader Special Variables</h4>
<div class="paragraph">
<p>In the geometry shader, built-in variables are intrinsically declared as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
} gl_in[];
in <span class="predefined-type">int</span> gl_PrimitiveIDIn;
in <span class="predefined-type">int</span> gl_InvocationID;
out gl_PerVertex {
vec4 gl_Position;
<span class="predefined-type">float</span> gl_PointSize;
<span class="predefined-type">float</span> gl_ClipDistance[];
<span class="predefined-type">float</span> gl_CullDistance[];
};
out <span class="predefined-type">int</span> gl_PrimitiveID;
out <span class="predefined-type">int</span> gl_Layer;
out <span class="predefined-type">int</span> gl_ViewportIndex;</code></pre>
</div>
</div>
<div class="sect4">
<h5 id="geometry-shader-input-variables">Geometry Shader Input Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em>
contain the values written in the previous shader stage to the corresponding
outputs.</p>
</div>
<div class="paragraph">
<p><em>gl_PrimitiveIDIn</em> contains the number of primitives processed by the shader
since the current set of rendering primitives was started.</p>
</div>
<div class="paragraph">
<p><em>gl_InvocationID</em> contains the invocation number assigned to the geometry
shader invocation.
It is assigned integer values in the range [0, N-1], where N is the number
of geometry shader invocations per primitive.</p>
</div>
</div>
<div class="sect4">
<h5 id="geometry-shader-output-variables">Geometry Shader Output Variables</h5>
<div class="paragraph">
<p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are
used in the same fashion as the corresponding output variables in the vertex
shader.</p>
</div>
<div class="paragraph">
<p><em>gl_PrimitiveID</em> is filled with a single integer that serves as a primitive
identifier to the fragment shader.
This is then available to fragment shaders, which will select the written
primitive ID from the provoking vertex of the primitive being shaded.
If a fragment shader using <em>gl_PrimitiveID</em> is active and a geometry shader
is also active, the geometry shader must write to <em>gl_PrimitiveID</em> or the
fragment shader input <em>gl_PrimitiveID</em> is undefined.
See section 11.3.4.5 &#8220;Geometry Shader Outputs&#8221; of the
<a href="#references">OpenGL Specification</a> for more information.</p>
</div>
<div class="paragraph">
<p><em>gl_Layer</em> is used to select a specific layer (or face and layer of a cube
map) of a multi-layer framebuffer attachment.
The actual layer used will come from one of the vertices in the primitive
being shaded.
Which vertex the layer comes from is determined as discussed in section
11.3.4.6 &#8220;Layer and Viewport Selection&#8221; of the <a href="#references">OpenGL Specification</a>
but may be undefined, so it is best to write the same layer value for all
vertices of a primitive.
If a shader statically assigns a value to <em>gl_Layer</em>, layered rendering mode
is enabled.
See section 11.3.4.5 &#8220;Geometry Shader Outputs&#8221; and section 9.4.9 &#8220;Layered
Framebuffers&#8221; of the <a href="#references">OpenGL Specification</a> for more information.
If a shader statically assigns a value to <em>gl_Layer</em>, and there is an
execution path through the shader that does not set <em>gl_Layer</em>, then the
value of <em>gl_Layer</em> is undefined for executions of the shader that take that
path.</p>
</div>
<div class="paragraph">
<p>The output variable <em>gl_Layer</em> takes on a special value when used with an
array of cube map textures.
Instead of only referring to the layer, it is used to select a cube map face
and a layer.
Setting <em>gl_Layer</em> to the value <em>layer*6+face</em> will render to face <em>face</em> of
the cube defined in layer <em>layer</em>.
The face values are defined in table 9.3 of section 9.4.9 &#8220;Layered
Framebuffers&#8221; of the <a href="#references">OpenGL Specification</a>,
but repeated below for clarity.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Face Value</th>
<th class="tableblock halign-left valign-top">Resulting Target</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_X</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_Y</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_Y</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_Z</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_Z</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For example, to render to the positive <em>y</em> cube map face located in the 5th
layer of the cube map array, <em>gl_Layer</em> should be set to <em>5 * 6 + 2</em>.</p>
</div>
<div class="paragraph">
<p>The output variable <em>gl_ViewportIndex</em> provides the index of the viewport to
which the next primitive emitted from the geometry shader should be drawn.
Primitives generated by the geometry shader will undergo viewport
transformation and scissor testing using the viewport transformation and
scissor rectangle selected by the value of <em>gl_ViewportIndex</em>.
The viewport index used will come from one of the vertices in the primitive
being shaded.
However, which vertex the viewport index comes from is
implementation-dependent, so it is best to use the same viewport index for
all vertices of the primitive.
If a geometry shader does not assign a value to <em>gl_ViewportIndex</em>, viewport
transform and scissor rectangle zero will be used.
If a geometry shader statically assigns a value to <em>gl_ViewportIndex</em> and
there is a path through the shader that does not assign a value to
<em>gl_ViewportIndex</em>, the value of <em>gl_ViewportIndex</em> is undefined for
executions of the shader that take that path.
See section 11.3.4.6 &#8220;Layer and Viewport Selection&#8221; of the
<a href="#references">OpenGL Specification</a> for more information.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="fragment-shader-special-variables">7.1.5. Fragment Shader Special Variables</h4>
<div class="paragraph">
<p>The built-in special variables that are accessible from a fragment shader
are intrinsically declared as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_FragCoord;
in <span class="predefined-type">bool</span> gl_FrontFacing;
in <span class="predefined-type">float</span> gl_ClipDistance[];
in <span class="predefined-type">float</span> gl_CullDistance[];
in vec2 gl_PointCoord;
in <span class="predefined-type">int</span> gl_PrimitiveID;
in <span class="predefined-type">int</span> gl_SampleID;
in vec2 gl_SamplePosition;
in <span class="predefined-type">int</span> gl_SampleMaskIn[];
in <span class="predefined-type">int</span> gl_Layer;
in <span class="predefined-type">int</span> gl_ViewportIndex;
in <span class="predefined-type">bool</span> gl_HelperInvocation;
out <span class="predefined-type">float</span> gl_FragDepth;
out <span class="predefined-type">int</span> gl_SampleMask[];</code></pre>
</div>
</div>
<div class="paragraph">
<p>The output of the fragment shader executable is processed by the fixed
function operations at the back end of the API pipeline.</p>
</div>
<div class="paragraph">
<p>The fixed functionality computed depth for a fragment may be obtained by
reading <em>gl_FragCoord.z</em>, described below.</p>
</div>
<div class="paragraph">
<p>Writing to <em>gl_FragDepth</em> will establish the depth value for the fragment
being processed.
If depth buffering is enabled, and no shader writes <em>gl_FragDepth</em>, then the
fixed function value for depth will be used as the fragment&#8217;s depth value.
If a shader statically assigns a value to <em>gl_FragDepth</em>, and there is an
execution path through the shader that does not set <em>gl_FragDepth</em>, then the
value of the fragment&#8217;s depth may be undefined for executions of the shader
that take that path.
That is, if the set of linked fragment shaders statically contain a write to
<em>gl_FragDepth</em>, then it is responsible for always writing it.</p>
</div>
<div class="paragraph">
<p>If a shader executes the <strong>discard</strong> keyword, the fragment is discarded, and
the values of any user-defined fragment outputs, <em>gl_FragDepth</em>, and
<em>gl_SampleMask</em> become irrelevant.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_FragCoord</em> is available as an input variable from within
fragment shaders and it holds the window relative coordinates (<em>x</em>, <em>y</em>,
<em>z</em>, <em>1/w</em>) values for the fragment.
If multi-sampling, this value can be for any location within the pixel, or
one of the fragment samples.
The use of <strong>centroid</strong> does not further restrict this value to be inside the
current primitive.
This value is the result of the fixed functionality that interpolates
primitives after vertex processing to generate fragments.
The <em>z</em> component is the depth value that would be used for the fragment&#8217;s
depth if no shader contained any writes to <em>gl_FragDepth</em>.
This is useful for invariance if a shader conditionally computes
<em>gl_FragDepth</em> but otherwise wants the fixed functionality fragment depth.</p>
</div>
<div class="paragraph">
<p>Fragment shaders have access to the input built-in variable
<em>gl_FrontFacing</em>, whose value is <strong>true</strong> if the fragment belongs to a
front-facing primitive.
One use of this is to emulate two-sided lighting by selecting one of two
colors calculated by a vertex or geometry shader.</p>
</div>
<div class="paragraph">
<p>The values in <em>gl_PointCoord</em> are two-dimensional coordinates indicating
where within a point primitive the current fragment is located, when point
sprites are enabled.
They range from 0.0 to 1.0 across the point.
If the current primitive is not a point, or if point sprites are not
enabled, then the values read from <em>gl_PointCoord</em> are undefined.</p>
</div>
<div class="paragraph">
<p>For both the input array <em>gl_SampleMaskIn[]</em> and the output array
<em>gl_SampleMask[]</em>, bit <em>B</em> of mask <em>M</em> (<em>gl_SampleMaskIn[M]</em> or
<em>gl_SampleMask[M]</em>) corresponds to sample <em>32*M+B</em>.
These arrays have <strong>ceil</strong>(<em>s</em>/32) elements, where <em>s</em> is the maximum number
of color samples supported by the implementation.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_SampleMaskIn</em> indicates the set of samples covered by
the primitive generating the fragment during multisample rasterization.
It has a sample bit set if and only if the sample is considered covered for
this fragment shader invocation.</p>
</div>
<div class="paragraph">
<p>The output array <em>gl_SampleMask[]</em> sets the sample mask for the fragment
being processed.
Coverage for the current fragment will become the logical AND of the
coverage mask and the output <em>gl_SampleMask</em>.
This array must be sized in the fragment shader either implicitly or
explicitly, to be no larger than the implementation-dependent maximum
sample-mask (as an array of 32bit elements), determined by the maximum
number of samples..
If the fragment shader statically assigns a value to <em>gl_SampleMask</em>, the
sample mask will be undefined for any array elements of any fragment shader
invocations that fail to assign a value.
If a shader does not statically assign a value to <em>gl_SampleMask</em>, the
sample mask has no effect on the processing of a fragment.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_SampleID</em> is filled with the sample number of the
sample currently being processed.
This variable is in the range <em>0</em> to <em>gl_NumSamples-1</em>, where
<em>gl_NumSamples</em> is the total number of samples in the framebuffer, or 1 if
rendering to a non-multisample framebuffer.
Any static use of this variable in a fragment shader causes the entire
shader to be evaluated per-sample.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_SamplePosition</em> contains the position of the current
sample within the multisample draw buffer.
The <em>x</em> and <em>y</em> components of <em>gl_SamplePosition</em> contain the sub-pixel
coordinate of the current sample and will have values in the range 0.0 to
1.0.
Any static use of this variable in a fragment shader causes the entire
shader to be evaluated per sample.</p>
</div>
<div class="paragraph">
<p>The value <em>gl_HelperInvocation</em> is <strong>true</strong> if the fragment shader invocation
is considered a <em>helper invocation</em> and is <strong>false</strong> otherwise.
A helper invocation is a fragment shader invocation that is created solely
for the purposes of evaluating derivatives for use in non-helper fragment
shader invocations.
Such derivatives are computed implicitly in the built-in function
<strong>texture</strong>() (see &#8220;<a href="#texture-functions">Texture Functions</a>&#8221;), and
explicitly in the derivative functions in
&#8220;<a href="#derivative-functions">Derivative Functions</a>&#8221;, for example <strong>dFdx</strong>() and
<strong>dFdy</strong>().</p>
</div>
<div class="paragraph">
<p>Fragment shader helper invocations execute the same shader code as
non-helper invocations, but will not have side effects that modify the
framebuffer or other shader-accessible memory.
In particular:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Fragments corresponding to helper invocations are discarded when shader
execution is complete, without updating the framebuffer.</p>
</li>
<li>
<p>Stores to image and buffer variables performed by helper invocations
have no effect on the underlying image or buffer memory.</p>
</li>
<li>
<p>Atomic operations to image, buffer, or atomic counter variables
performed by helper invocations have no effect on the underlying image
or buffer memory.
The values returned by such atomic operations are undefined.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Helper invocations may be generated for pixels not covered by a primitive
being rendered.
While fragment shader inputs qualified with <strong>centroid</strong> are normally required
to be sampled in the intersection of the pixel and the primitive, the
requirement is ignored for such pixels since there is no intersection
between the pixel and primitive.</p>
</div>
<div class="paragraph">
<p>Helper invocations may also be generated for fragments that are covered by a
primitive being rendered when the fragment is killed by early fragment tests
(using the <strong>early_fragment_tests</strong> qualifier) or where the implementation is
able to determine that executing the fragment shader would have no effect
other than assisting in computing derivatives for other fragment shader
invocations.</p>
</div>
<div class="paragraph">
<p>The set of helper invocations generated when processing any set of
primitives is implementation-dependent.</p>
</div>
<div class="paragraph">
<p><em>gl_ClipDistance</em> contains linearly interpolated values for the vertex-
pipeline values written by a shader to the <em>gl_ClipDistance</em> output
variable. Only elements in this array that have clipping enabled will
have defined values.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_PrimitiveID</em> is filled with the value written to the
<em>gl_PrimitiveID</em> geometry shader output, if a geometry shader is present.
Otherwise, it is filled with the number of primitives processed by the
shader since the current set of rendering primitives was started.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_Layer</em> is filled with the value written to the
<em>gl_Layer</em> geometry shader output, if a geometry shader is present.
If the geometry stage does not dynamically assign a value to <em>gl_Layer</em>, the
value of <em>gl_Layer</em> in the fragment stage will be undefined.
If the geometry stage makes no static assignment to <em>gl_Layer</em>, the input
value in the fragment stage will be zero.
Otherwise, the fragment stage will read the same value written by the
geometry stage, even if that value is out of range.
If a fragment shader contains a static access to <em>gl_Layer</em>, it will count
against the implementation defined limit for the maximum number of inputs to
the fragment stage.</p>
</div>
<div class="paragraph">
<p>The input variable <em>gl_ViewportIndex</em> is filled with the value written to
the output variable <em>gl_ViewportIndex</em> in the geometry stage, if a geometry
shader is present.
If the geometry stage does not dynamically assign a value to
<em>gl_ViewportIndex</em>, the value of <em>gl_ViewportIndex</em> in the fragment shader
will be undefined.
If the geometry stage makes no static assignment to <em>gl_ViewportIndex</em>, the
fragment stage will read zero.
Otherwise, the fragment stage will read the same value written by the
geometry stage, even if that value is out of range.
If a fragment shader contains a static access to <em>gl_ViewportIndex</em>, it will
count against the implementation defined limit for the maximum number of
inputs to the fragment stage.</p>
</div>
</div>
<div class="sect3">
<h4 id="compute-shader-special-variables">7.1.6. Compute Shader Special Variables</h4>
<div class="paragraph">
<p>In the compute shader, built-in variables are declared as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// workgroup dimensions</span>
in uvec3 gl_NumWorkGroups;
<span class="directive">const</span> uvec3 gl_WorkGroupSize;
<span class="comment">// workgroup and invocation IDs</span>
in uvec3 gl_WorkGroupID;
in uvec3 gl_LocalInvocationID;
<span class="comment">// derived variables</span>
in uvec3 gl_GlobalInvocationID;
in uint gl_LocalInvocationIndex;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The built-in variable <em>gl_NumWorkGroups</em> is a compute-shader input variable
containing the number of workgroups in each dimension of the dispatch that
will execute the compute shader.
Its content is equal to the values specified in the <em>num_groups_x</em>,
<em>num_groups_y</em>, and <em>num_groups_z</em> parameters passed to the
<em>DispatchCompute</em> API entry point.</p>
</div>
<div class="paragraph">
<p>The built-in constant <em>gl_WorkGroupSize</em> is a compute-shader constant
containing the workgroup size of the shader.
The size of the workgroup in the <em>X</em>, <em>Y</em>, and <em>Z</em> dimensions is stored in
the <em>x</em>, <em>y</em>, and <em>z</em> components.
The constants values in <em>gl_WorkGroupSize</em> will match those specified in the
required <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong> layout
qualifiers for the current shader.
This is a constant so that it can be used to size arrays of memory that can
be shared within the workgroup.
It is a compile-time error to use <em>gl_WorkGroupSize</em> in a shader that does
not declare a fixed workgroup size, or before that shader has declared a
fixed workgroup size, using <strong>local_size_x</strong>, <strong>local_size_y</strong>, and
<strong>local_size_z</strong>.</p>
</div>
<div class="paragraph">
<p>The built-in variable <em>gl_WorkGroupID</em> is a compute-shader input variable
containing the three-dimensional index of the workgroup that the
current invocation is executing in.
The possible values range across the parameters passed into
<em>DispatchCompute</em>, i.e., from (0, 0, 0) to (<em>gl_NumWorkGroups.x</em> - 1,
<em>gl_NumWorkGroups.y</em> - 1, <em>gl_NumWorkGroups.z</em> -1).</p>
</div>
<div class="paragraph">
<p>The built-in variable <em>gl_LocalInvocationID</em> is a compute-shader input
variable containing the three-dimensional index of the current work item
within the workgroup.
The possible values for this variable range across the workgroup
size, i.e., (0,0,0) to (<em>gl_WorkGroupSize.x</em> - 1, <em>gl_WorkGroupSize.y</em> - 1,
<em>gl_WorkGroupSize.z</em> - 1). Use of <em>gl_LocalInvocationID</em> is allowed
before declarations of <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong>.</p>
</div>
<div class="paragraph">
<p>The built-in variable <em>gl_GlobalInvocationID</em> is a compute shader input
variable containing the global index of the current work item.
This value uniquely identifies this invocation from all other invocations
across all workgroups initiated by the current <em>DispatchCompute</em> call.
This is computed as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_GlobalInvocationID =
gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The built-in variable <em>gl_LocalInvocationIndex</em> is a compute shader input
variable that contains the one-dimensional representation of the
<em>gl_LocalInvocationID</em>.
This is computed as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">gl_LocalInvocationIndex =
gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y +
gl_LocalInvocationID.y * gl_WorkGroupSize.x +
gl_LocalInvocationID.x;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Use of <em>gl_LocalInvocationIndex</em> is allowed before declarations of
<strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong>.</p>
</div>
</div>
<div class="sect3">
<h4 id="compatibility-profile-built-in-language-variables">7.1.7. Compatibility Profile Built-In Language Variables</h4>
<div class="paragraph">
<p>When using the compatibility profile, the GL can provide fixed functionality
behavior for the vertex and fragment programmable pipeline stages.
For example, mixing a fixed functionality vertex stage with a programmable
fragment stage.</p>
</div>
<div class="paragraph">
<p>The following built-in vertex, tessellation control, tessellation
evaluation, and geometry output variables are available to specify inputs
for the subsequent programmable shader stage or the fixed functionality
fragment stage.
A particular one should be written to if any functionality in a
corresponding fragment shader or fixed pipeline uses it or state derived
from it.
Otherwise, behavior is undefined.
The following members are added to the output <em>gl_PerVertex</em> block in these
languages:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex { <span class="comment">// part of the gl_PerVertex block described in 7.1</span>
<span class="comment">// in addition to other gl_PerVertex members...</span>
vec4 gl_ClipVertex;
vec4 gl_FrontColor;
vec4 gl_BackColor;
vec4 gl_FrontSecondaryColor;
vec4 gl_BackSecondaryColor;
vec4 gl_TexCoord[];
<span class="predefined-type">float</span> gl_FogFragCoord;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The output variable <em>gl_ClipVertex</em> provides a place for vertex and geometry
shaders to write the coordinate to be used with the user clipping planes.
Writing to <em>gl_ClipDistance</em> is the preferred method for user clipping.
It is a compile-time or link-time error for the set of shaders forming a
program to statically read or write both <em>gl_ClipVertex</em> and either
<em>gl_ClipDistance</em> or <em>gl_CullDistance</em>.
If neither <em>gl_ClipVertex</em> nor <em>gl_ClipDistance</em> is written, their values
are undefined and any clipping against user clip planes is also undefined.</p>
</div>
<div class="paragraph">
<p>Similarly to what was previously described for the core profile, the
<em>gl_PerVertex</em> block can be redeclared in a shader to explicitly include
these additional members.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex {
vec4 gl_Position; <span class="comment">// will use gl_Position</span>
vec4 gl_FrontColor; <span class="comment">// will consume gl_color in the fragment shader</span>
vec4 gl_BackColor;
vec4 gl_TexCoord[<span class="integer">3</span>]; <span class="comment">// 3 elements of gl_TexCoord will be used</span>
}; <span class="comment">// no other aspects of the fixed interface will be used</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The user must ensure the clip vertex and user clipping planes are defined in
the same coordinate space.
User clip planes work properly only under linear transform.
It is undefined what happens under non-linear transform.</p>
</div>
<div class="paragraph">
<p>The output variables <em>gl_FrontColor</em>, <em>glFrontSecondaryColor</em>,
<em>gl_BackColor</em>, and <em>glBackSecondaryColor</em> assign primary and secondary
colors for front and back faces of primitives containing the vertex being
processed.
The output variable <em>gl_TexCoord</em> assigns texture coordinates for the vertex
being processed.</p>
</div>
<div class="paragraph">
<p>For <em>gl_FogFragCoord</em>, the value written will be used as the &#8220;c&#8221; value in
section 16.4 &#8220;Fog&#8221; of the Compatibility profile of the
<a href="#references">OpenGL Specification</a>, by the fixed functionality pipeline.
For example, if the z-coordinate of the fragment in eye space is desired as
&#8220;c&#8221;, then that&#8217;s what the vertex shader executable should write into
<em>gl_FogFragCoord</em>.</p>
</div>
<div class="paragraph">
<p>As with all arrays, indices used to subscript <em>gl_TexCoord</em> must either be a
constant integral expressions, or this array must be redeclared by the
shader with a size.
The size can be at most <em>gl_MaxTextureCoords</em>.
Using indices close to 0 may aid the implementation in preserving varying
resources.
The redeclaration of <em>gl_TexCoord</em> can also be done at global scope as, for
example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_TexCoord[<span class="integer">3</span>];
out vec4 gl_TexCoord[<span class="integer">4</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>(This treatment is a special case for <em>gl_TexCoord[]</em>, not a general method
for redeclaring members of blocks.) It is a compile-time error to redeclare
<em>gl_TexCoord[]</em> at global scope if there is a redeclaration of the
corresponding built-in block; only one form of redeclaration is allowed
within a shader (and hence within a stage, as block redeclarations must
match across all shaders using it).</p>
</div>
<div class="paragraph">
<p>In the tessellation control, evaluation, and geometry shaders, the outputs
of the previous stage described above are also available in the input
<em>gl_PerVertex</em> block in these languages.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { <span class="comment">// part of the gl_PerVertex block described in 7.1</span>
<span class="comment">// in addition to other gl_PerVertex members...</span>
vec4 gl_ClipVertex;
vec4 gl_FrontColor;
vec4 gl_BackColor;
vec4 gl_FrontSecondaryColor;
vec4 gl_BackSecondaryColor;
vec4 gl_TexCoord[];
<span class="predefined-type">float</span> gl_FogFragCoord;
} gl_in[];</code></pre>
</div>
</div>
<div class="paragraph">
<p>These can be redeclared to establish an explicit pipeline interface, the
same way as described above for the output block <em>gl_PerVertex</em>, and the
input redeclaration must match the output redeclaration of the previous
stage.
However, when a built-in interface block with an instance name is redeclared
(e.g. <em>gl_in</em>), the instance name must be included in the redeclaration.
It is a compile-time error to not include the built-in instance name or to
change its name.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex {
vec4 gl_ClipVertex;
vec4 gl_FrontColor;
} gl_in[]; <span class="comment">// must be present and must be &quot;gl_in[]&quot;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Built-in block arrays predeclared with a size can be redeclared with unsized syntax.
This keeps their size equal to the original predeclared size.</p>
</div>
<div class="paragraph">
<p>Treatment of <em>gl_TexCoord[]</em> redeclaration is also identical to that
described for the output block <em>gl_TexCoord[]</em> redeclaration.</p>
</div>
<div class="paragraph">
<p>The following fragment input block is also available in a fragment shader
when using the compatibility profile:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in gl_PerFragment {
in <span class="predefined-type">float</span> gl_FogFragCoord;
in vec4 gl_TexCoord[];
in vec4 gl_Color;
in vec4 gl_SecondaryColor;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>The values in <em>gl_Color</em> and <em>gl_SecondaryColor</em> will be derived
automatically by the system from <em>gl_FrontColor</em>, <em>gl_BackColor</em>,
<em>gl_FrontSecondaryColor</em>, and <em>gl_BackSecondaryColor</em> based on which face is
visible in the primitive producing the fragment.
If fixed functionality is used for vertex processing, then <em>gl_FogFragCoord</em>
will either be the z-coordinate of the fragment in eye space, or the
interpolation of the fog coordinate, as described in section 16.4 &#8220;Fog&#8221; of
the Compatibility profile of the <a href="#references">OpenGL Specification</a>.
The <em>gl_TexCoord[]</em> values are the interpolated <em>gl_TexCoord[]</em> values from
a vertex shader or the texture coordinates of any fixed pipeline based
vertex functionality.</p>
</div>
<div class="paragraph">
<p>Indices to the fragment shader <em>gl_TexCoord</em> array are as described above in
the vertex shader text.</p>
</div>
<div class="paragraph">
<p>As described above for the input and output <em>gl_PerVertex</em> blocks, the
<em>gl_PerFragment</em> block can be redeclared to create an explicit interface to
another program.
When matching these interfaces between separate programs, members in the
<em>gl_PerVertex</em> output block must be declared if and only if the
corresponding fragment shader members generated from them are present in the
<em>gl_PerFragment</em> input block.
These matches are described in detail in section 7.4.1 &#8220;Shader Interface
Matching&#8221; of the <a href="#references">OpenGL Specification</a>.
If they don&#8217;t match within a program, a link-time error will result.
If the mismatch is between two programs, values passed between programs are
undefined.
Unlike with all other block matching, the order of declaration within
<em>gl_PerFragment</em> does not have to match across shaders and does not have to
correspond with order of declaration in a matching <em>gl_PerVertex</em>
redeclaration.</p>
</div>
<div class="paragraph">
<p>The following fragment output variables are available in a fragment shader
when using the compatibility profile:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out vec4 gl_FragColor;
out vec4 gl_FragData[gl_MaxDrawBuffers];</code></pre>
</div>
</div>
<div class="paragraph">
<p>Writing to <em>gl_FragColor</em> specifies the fragment color that will be used by
the subsequent fixed functionality pipeline.
If subsequent fixed functionality consumes fragment color and an execution
of the fragment shader executable does not write a value to <em>gl_FragColor</em>
then the fragment color consumed is undefined.</p>
</div>
<div class="paragraph">
<p>The variable <em>gl_FragData</em> is an array.
Writing to <em>gl_FragData[n]</em> specifies the fragment data that will be used by
the subsequent fixed functionality pipeline for data <em>n</em>.
If subsequent fixed functionality consumes fragment data and an execution of
a fragment shader executable does not write a value to it, then the fragment
data consumed is undefined.</p>
</div>
<div class="paragraph">
<p>If a shader statically assigns a value to <em>gl_FragColor</em>, it may not assign
a value to any element of <em>gl_FragData</em>.
If a shader statically writes a value to any element of <em>gl_FragData</em>, it
may not assign a value to <em>gl_FragColor</em>.
That is, a shader may assign values to either <em>gl_FragColor</em> or
<em>gl_FragData</em>, but not both.
Multiple shaders linked together must also consistently write just one of
these variables.
Similarly, if user-declared output variables are in use (statically assigned
to), then the built-in variables <em>gl_FragColor</em> and <em>gl_FragData</em> may not be
assigned to.
These incorrect usages all generate compile-time or link-time errors.</p>
</div>
<div class="paragraph">
<p>If a shader executes the <strong>discard</strong> keyword, the fragment is discarded, and
the values of <em>gl_FragDepth</em> and <em>gl_FragColor</em> become irrelevant.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="compatibility-profile-vertex-shader-built-in-inputs">7.2. Compatibility Profile Vertex Shader Built-In Inputs</h3>
<div class="paragraph">
<p>The following predeclared input names can be used from within a vertex
shader to access the current values of OpenGL state when using the
compatibility profile.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_Color;
in vec4 gl_SecondaryColor;
in vec3 gl_Normal;
in vec4 gl_Vertex;
in vec4 gl_MultiTexCoord0;
in vec4 gl_MultiTexCoord1;
in vec4 gl_MultiTexCoord2;
in vec4 gl_MultiTexCoord3;
in vec4 gl_MultiTexCoord4;
in vec4 gl_MultiTexCoord5;
in vec4 gl_MultiTexCoord6;
in vec4 gl_MultiTexCoord7;
in <span class="predefined-type">float</span> gl_FogCoord;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="built-in-constants">7.3. Built-In Constants</h3>
<div class="paragraph">
<p>The following built-in constants are declared in all shaders.
The actual values used are implementation-dependent, but must be at least
the value shown.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span>
<span class="comment">// Implementation-dependent constants. The example values below</span>
<span class="comment">// are the minimum values allowed for these maximums.</span>
<span class="comment">//</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAttribs = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexUniformVectors = <span class="integer">256</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexOutputComponents = <span class="integer">64</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingComponents = <span class="integer">60</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingVectors = <span class="integer">15</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessPatchComponents = <span class="integer">120</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxPatchVertices = <span class="integer">32</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessGenLevel = <span class="integer">64</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlInputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlOutputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlTotalOutputComponents = <span class="integer">4096</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationInputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationOutputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryInputComponents = <span class="integer">64</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryOutputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryOutputVertices = <span class="integer">256</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryTotalOutputComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryVaryingComponents = <span class="integer">64</span>; <span class="comment">// deprecated</span>
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentImageUniforms = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentInputComponents = <span class="integer">128</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentUniformVectors = <span class="integer">256</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounterBuffers = <span class="integer">1</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxDrawBuffers = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MinProgramTexelOffset = -<span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxProgramTexelOffset = <span class="integer">7</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxImageUnits = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxSamples = <span class="integer">4</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxImageSamples = <span class="integer">0</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxClipDistances = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCullDistances = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxViewports = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeImageUniforms = <span class="integer">8</span>;
<span class="directive">const</span> ivec3 gl_MaxComputeWorkGroupCount = { <span class="integer">65535</span>, <span class="integer">65535</span>, <span class="integer">65535</span> };
<span class="directive">const</span> ivec3 gl_MaxComputeWorkGroupSize = { <span class="integer">1024</span>, <span class="integer">1024</span>, <span class="integer">64</span> };
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeAtomicCounterBuffers = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedTextureImageUnits = <span class="integer">96</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedImageUniforms = <span class="integer">48</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedImageUnitsAndFragmentOutputs = <span class="integer">8</span>; <span class="comment">// deprecated</span>
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedShaderOutputResources = <span class="integer">16</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounterBuffers = <span class="integer">1</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedClipAndCullDistances = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxAtomicCounterBindings = <span class="integer">1</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxAtomicCounterBufferSize = <span class="integer">32</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTransformFeedbackBuffers = <span class="integer">4</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTransformFeedbackInterleavedComponents = <span class="integer">64</span>;
<span class="directive">const</span> highp <span class="predefined-type">int</span> gl_MaxInputAttachments = <span class="integer">1</span>; <span class="comment">// only present when targeting Vulkan</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The constant <em>gl_MaxVaryingFloats</em> is removed in the core profile, use
<em>gl_MaxVaryingComponents</em> instead.</p>
</div>
<div class="sect3">
<h4 id="compatibility-profile-built-in-constants">7.3.1. Compatibility Profile Built-In Constants</h4>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureUnits = <span class="integer">2</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureCoords = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxClipPlanes = <span class="integer">8</span>;
<span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingFloats = <span class="integer">60</span>;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="built-in-uniform-state">7.4. Built-In Uniform State</h3>
<div class="paragraph">
<p>Built-in uniform state is not available when generating SPIR-V.
Otherwise, as an aid to accessing OpenGL processing state, the following
uniform variables are built into the OpenGL Shading Language.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span>
<span class="comment">// Depth range in window coordinates,</span>
<span class="comment">// section 13.6.1 &quot;Controlling the Viewport&quot; in the</span>
<span class="comment">// OpenGL Specification.</span>
<span class="comment">//</span>
<span class="comment">// Note: Depth-range state is only for viewport 0.</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_DepthRangeParameters {
<span class="predefined-type">float</span> near; <span class="comment">// n</span>
<span class="predefined-type">float</span> far; <span class="comment">// f</span>
<span class="predefined-type">float</span> diff; <span class="comment">// f - n</span>
};
uniform gl_DepthRangeParameters gl_DepthRange;
uniform <span class="predefined-type">int</span> gl_NumSamples;</code></pre>
</div>
</div>
<div class="paragraph">
<p>These variables are only guaranteed to be available in the fragment stage.
In other stages, their presence and function is implementation-defined.</p>
</div>
<div class="sect3">
<h4 id="compatibility-profile-state">7.4.1. Compatibility Profile State</h4>
<div class="paragraph">
<p>These variables are present only in the compatibility profile.
They are not available to compute shaders, but are available to all other
shaders.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
uniform mat4 gl_ModelViewMatrix;
uniform mat4 gl_ProjectionMatrix;
uniform mat4 gl_ModelViewProjectionMatrix;
uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
uniform mat3 gl_NormalMatrix; <span class="comment">// transpose of the inverse of the</span>
<span class="comment">// upper leftmost 3x3 of gl_ModelViewMatrix</span>
uniform mat4 gl_ModelViewMatrixInverse;
uniform mat4 gl_ProjectionMatrixInverse;
uniform mat4 gl_ModelViewProjectionMatrixInverse;
uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
uniform mat4 gl_ModelViewMatrixTranspose;
uniform mat4 gl_ProjectionMatrixTranspose;
uniform mat4 gl_ModelViewProjectionMatrixTranspose;
uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
uniform mat4 gl_ModelViewMatrixInverseTranspose;
uniform mat4 gl_ProjectionMatrixInverseTranspose;
uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
uniform <span class="predefined-type">float</span> gl_NormalScale;
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_PointParameters {
<span class="predefined-type">float</span> size;
<span class="predefined-type">float</span> sizeMin;
<span class="predefined-type">float</span> sizeMax;
<span class="predefined-type">float</span> fadeThresholdSize;
<span class="predefined-type">float</span> distanceConstantAttenuation;
<span class="predefined-type">float</span> distanceLinearAttenuation;
<span class="predefined-type">float</span> distanceQuadraticAttenuation;
};
uniform gl_PointParameters gl_Point;
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_MaterialParameters {
vec4 emission; <span class="comment">// Ecm</span>
vec4 ambient; <span class="comment">// Acm</span>
vec4 diffuse; <span class="comment">// Dcm</span>
vec4 specular; <span class="comment">// Scm</span>
<span class="predefined-type">float</span> shininess; <span class="comment">// Srm</span>
};
uniform gl_MaterialParameters gl_FrontMaterial;
uniform gl_MaterialParameters gl_BackMaterial;
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_LightSourceParameters {
vec4 ambient; <span class="comment">// Acli</span>
vec4 diffuse; <span class="comment">// Dcli</span>
vec4 specular; <span class="comment">// Scli</span>
vec4 position; <span class="comment">// Ppli</span>
vec4 halfVector; <span class="comment">// Derived: Hi</span>
vec3 spotDirection; <span class="comment">// Sdli</span>
<span class="predefined-type">float</span> spotExponent; <span class="comment">// Srli</span>
<span class="predefined-type">float</span> spotCutoff; <span class="comment">// Crli</span>
<span class="comment">// (range: [0.0,90.0], 180.0)</span>
<span class="predefined-type">float</span> spotCosCutoff; <span class="comment">// Derived: cos(Crli)</span>
<span class="comment">// (range: [1.0,0.0],-1.0)</span>
<span class="predefined-type">float</span> constantAttenuation; <span class="comment">// K0</span>
<span class="predefined-type">float</span> linearAttenuation; <span class="comment">// K1</span>
<span class="predefined-type">float</span> quadraticAttenuation; <span class="comment">// K2</span>
};
uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
<span class="keyword">struct</span> gl_LightModelParameters {
vec4 ambient; <span class="comment">// Acs</span>
};
uniform gl_LightModelParameters gl_LightModel;
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
<span class="comment">// Derived state from products of light and material.</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_LightModelProducts {
vec4 sceneColor; <span class="comment">// Derived. Ecm + Acm * Acs</span>
};
uniform gl_LightModelProducts gl_FrontLightModelProduct;
uniform gl_LightModelProducts gl_BackLightModelProduct;
<span class="keyword">struct</span> gl_LightProducts {
vec4 ambient; <span class="comment">// Acm * Acli</span>
vec4 diffuse; <span class="comment">// Dcm * Dcli</span>
vec4 specular; <span class="comment">// Scm * Scli</span>
};
uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
uniform vec4 gl_TextureEnvColor[gl_MaxTextureUnits];
uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
<span class="comment">//</span>
<span class="comment">// compatibility profile only</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_FogParameters {
vec4 color;
<span class="predefined-type">float</span> density;
<span class="predefined-type">float</span> start;
<span class="predefined-type">float</span> end;
<span class="predefined-type">float</span> scale; <span class="comment">// Derived: 1.0 / (end - start)</span>
};
uniform gl_FogParameters gl_Fog;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="redeclaring-built-in-blocks">7.5. Redeclaring Built-In Blocks</h3>
<div class="paragraph">
<p>The <em>gl_PerVertex</em> block can be redeclared in a shader to explicitly
indicate what subset of the fixed pipeline interface will be used.
This is necessary to establish the interface between multiple programs.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex {
vec4 gl_Position; <span class="comment">// will use gl_Position</span>
<span class="predefined-type">float</span> gl_PointSize; <span class="comment">// will use gl_PointSize</span>
vec4 t; <span class="comment">// error, only gl_PerVertex members allowed</span>
}; <span class="comment">// no other members of gl_PerVertex will be used</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This establishes the output interface the shader will use with the
subsequent pipeline stage.
It must be a subset of the built-in members of <em>gl_PerVertex</em>.
Such a redeclaration can also add the <strong>invariant</strong> qualifier, interpolation
qualifiers, and the layout qualifiers <strong>xfb_offset</strong>, <strong>xfb_buffer</strong>, and
<strong>xfb_stride</strong>.
It can also add an array size for unsized arrays.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out layout(xfb_buffer = <span class="integer">1</span>, xfb_stride = <span class="integer">16</span>) gl_PerVertex {
vec4 gl_Position;
layout(xfb_offset = <span class="integer">0</span>) <span class="predefined-type">float</span> gl_ClipDistance[<span class="integer">4</span>];
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>Other layout qualifiers, like <strong>location</strong>, cannot be added to such a
redeclaration, unless specifically stated.</p>
</div>
<div class="paragraph">
<p>If a built-in interface block is redeclared, it must appear in the shader
before any use of any member included in the built-in declaration, or a
compile-time error will result.
It is also a compile-time error to redeclare the block more than once or to
redeclare a built-in block and then use a member from that built-in block
that was not included in the redeclaration.
Also, if a built-in interface block is redeclared, no member of the built-in
declaration can be redeclared outside the block redeclaration.
If multiple shaders using members of a built-in block belonging to the same
interface are linked together in the same program, they must all redeclare
the built-in block in the same way, as described in
&#8220;<a href="#interface-blocks">Interface Blocks</a>&#8221; for interface block matching, or a
link-time error will result.
It will also be a link-time error if some shaders in a program redeclare a
specific built-in interface block while another shader in that program does
not redeclare that interface block yet still uses a member of that interface
block.
If a built-in block interface is formed across shaders in different
programs, the shaders must all redeclare the built-in block in the same way
(as described for a single program), or the values passed along the
interface are undefined.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="built-in-functions">8. Built-In Functions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The OpenGL Shading Language defines an assortment of built-in convenience functions for
scalar and vector operations.
Many of these built-in functions can be used in more than one type of
shader, but some are intended to provide a direct mapping to hardware and so
are available only for a specific type of shader.</p>
</div>
<div class="paragraph">
<p>The built-in functions basically fall into three categories:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>They expose some necessary hardware functionality in a convenient way
such as accessing a texture map.
There is no way in the language for these functions to be emulated by a
shader.</p>
</li>
<li>
<p>They represent a trivial operation (clamp, mix, etc.) that is very
simple for the user to write, but they are very common and may have
direct hardware support.
It is a very hard problem for the compiler to map expressions to complex
assembler instructions.</p>
</li>
<li>
<p>They represent an operation graphics hardware is likely to accelerate at
some point.
The trigonometry functions fall into this category.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Many of the functions are similar to the same named ones in common C
libraries, but they support vector input as well as the more traditional
scalar input.</p>
</div>
<div class="paragraph">
<p>Applications should be encouraged to use the built-in functions rather than
do the equivalent computations in their own shader code since the built-in
functions are assumed to be optimal (e.g. perhaps supported directly in
hardware).</p>
</div>
<div class="paragraph">
<p>User code can replace built-in functions with their own if they choose, by
simply redeclaring and defining the same name and argument list.
Because built-in functions are in a more outer scope than user built-in
functions, doing this will hide all built-in functions with the same name as
the redeclared function.</p>
</div>
<div class="paragraph">
<p>When the built-in functions are specified below, where the input arguments
(and corresponding output) can be <strong>float</strong>, <strong>vec2</strong>, <strong>vec3</strong>, or <strong>vec4</strong>,
<em>genFType</em> is used as the argument.
Where the input arguments (and corresponding output) can be <strong>int</strong>, <strong>ivec2</strong>,
<strong>ivec3</strong>, or <strong>ivec4</strong>, <em>genIType</em> is used as the argument.
Where the input arguments (and corresponding output) can be <strong>uint</strong>, <strong>uvec2</strong>,
<strong>uvec3</strong>, or <strong>uvec4</strong>, <em>genUType</em> is used as the argument.
Where the input arguments (or corresponding output) can be <strong>bool</strong>, <strong>bvec2</strong>,
<strong>bvec3</strong>, or <strong>bvec4</strong>, <em>genBType</em> is used as the argument.
Where the input arguments (and corresponding output) can be <strong>double</strong>,
<strong>dvec2</strong>, <strong>dvec3</strong>, <strong>dvec4</strong>, <em>genDType</em> is used as the argument.
For any specific use of a function, the actual types substituted for
<em>genFType</em>, <em>genIType</em>, <em>genUType</em>, or <em>genBType</em> have to have the same
number of components for all arguments and for the return type.
Similarly, <em>mat</em> is used for any matrix basic
type with single-precision
components and <em>dmat</em> is used for any matrix basic type with
double-precision components.</p>
</div>
<div class="paragraph">
<p>Built-in functions have an effective precision qualification.
This qualification cannot be set explicitly and may be different from the
precision qualification of the result.</p>
</div>
<div class="paragraph">
<p>Note: In general, as has been noted, precision qualification is ignored
unless targeting Vulkan.</p>
</div>
<div class="paragraph">
<p>The precision qualification of the operation of a built-in function is based
on the precision qualification of its formal parameters and actual
parameters (input arguments): When a formal parameter specifies a precision
qualifier, that is used, otherwise, the precision qualification of the
actual (calling) argument is used.
The highest precision of these will be the precision of the operation of the
built-in function.
Generally, this is applied across all arguments to a built-in function, with
the exceptions being:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>bitfieldExtract</strong> and <strong>bitfieldInsert</strong> ignore the <em>offset</em> and <em>bits</em>
arguments.</p>
</li>
<li>
<p><strong>interpolateAt</strong> functions only look at the <em>interpolant</em> argument.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The precision qualification of the result of a built-in function is
determined in one of the following ways:</p>
</div>
<div class="paragraph">
<p>For the texture sampling, image load and image store functions, the
precision of the return type matches the precision of the
texture-combined sampler type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">uniform lowp sampler2D texSampler;
highp vec2 coord;
...
lowp vec4 col = texture (texSampler, coord); <span class="comment">// texture() returns lowp</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Otherwise:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>For prototypes that do not specify a resulting precision qualifier, the
precision will be the same as the precision of the operation (as defined
earlier).</p>
</li>
<li>
<p>For prototypes that do specify a resulting precision qualifier, the
specified precision qualifier is the precision qualification of the
result.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Where the built-in functions in the following sections specify an equation,
the entire equation will be evaluated at the operation&#8217;s precision.
This may lead to underflow or overflow in the result, even when the correct
result could be represented in the operation precision.</p>
</div>
<div class="sect2">
<h3 id="angle-and-trigonometry-functions">8.1. Angle and Trigonometry Functions</h3>
<div class="paragraph">
<p>Function parameters specified as <em>angle</em> are assumed to be in units of
radians.
In no case will any of these functions result in a divide by zero error.
If the divisor of a ratio is 0, then results will be undefined.</p>
</div>
<div class="paragraph">
<p>These all operate component-wise.
The description is per component.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>radians</strong>(genFType <em>degrees</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>degrees</em> to radians, i.e.,
<span class="eq">(π / 180) · degrees</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>degrees</strong>(genFType <em>radians</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Converts <em>radians</em> to degrees, i.e.,
<span class="eq">(180 / π) · radians</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>sin</strong>(genFType <em>angle</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard trigonometric sine function.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>cos</strong>(genFType <em>angle</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard trigonometric cosine function.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>tan</strong>(genFType <em>angle</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard trigonometric tangent.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>asin</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc sine.
Returns an angle whose sine is <em>x</em>.
The range of values returned by this function is
<span class="eq">[-π / 2, π / 2]</span>.
Results are undefined if <span class="eq">|x| &gt; 1</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>acos</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc cosine.
Returns an angle whose cosine is <em>x</em>.
The range of values returned by this function is <span class="eq">[0,Ï€]</span>.
Results are undefined if <span class="eq">|x| &gt; 1</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>atan</strong>(genFType <em>y</em>, genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent.
Returns an angle whose tangent is <span class="eq">y / x</span>.
The signs of <em>x</em> and <em>y</em> are used to determine what quadrant the angle
is in.
The range of values returned by this function is <span class="eq">[-π, π</span>.
Results are undefined if <em>x</em> and <em>y</em> are both 0.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>atan</strong>(genFType <em>y_over_x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc tangent.
Returns an angle whose tangent is <em>y_over_x</em>.
The range of values returned by this function is
<span class="eq">[-π / 2, π / 2]</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>sinh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the hyperbolic sine function <span class="eq">(e<sup>x</sup> - e<sup>-x</sup>) / 2</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>cosh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the hyperbolic cosine function <span class="eq">(e<sup>x</sup> + e<sup>-x</sup>) / 2</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>tanh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the hyperbolic tangent function <span class="eq">sinh(x) / cosh(x)</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>asinh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc hyperbolic sine; returns the inverse of <strong>sinh</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>acosh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc hyperbolic cosine; returns the non-negative inverse of <strong>cosh</strong>.
Results are undefined if <span class="eq">x &lt; 1</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>atanh</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Arc hyperbolic tangent; returns the inverse of <strong>tanh</strong>.
Results are undefined if <span class="eq">x ≥ 1</span>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="exponential-functions">8.2. Exponential Functions</h3>
<div class="paragraph">
<p>These all operate component-wise.
The description is per component.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>pow</strong>(genFType <em>x</em>, genFType <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> raised to the <em>y</em> power, i.e., <span class="eq">x<sup>y</sup></span>.
Results are undefined if <span class="eq">x &lt; 0</span>.
Results are undefined if <span class="eq">x = 0</span> and <span class="eq">y ≤ 0</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>exp</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the natural exponentiation of <em>x</em>, i.e., <span class="eq">e<sup>x</sup></span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>log</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the natural logarithm of <em>x</em>, i.e., returns the value <em>y</em>
which satisfies the equation <span class="eq">x = e<sup>y</sup></span>.
Results are undefined if <span class="eq">x ≤ 0</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>exp2</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 2 raised to the <em>x</em> power, i.e., <span class="eq">2<sup>x</sup></span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>log2</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the base 2 logarithm of <em>x</em>, i.e., returns the value <em>y</em> which
satisfies the equation <span class="eq">x = 2<sup>y</sup></span>.
Results are undefined if <span class="eq">x ≤ 0</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>sqrt</strong>(genFType <em>x</em>)<br>
genDType <strong>sqrt</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <span class="eq">sqrt(x)</span>.
Results are undefined if <span class="eq">x &lt; 0</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>inversesqrt</strong>(genFType <em>x</em>)<br>
genDType <strong>inversesqrt</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <span class="eq">1 / sqrt(x)</span>.
Results are undefined if <span class="eq">x ≤ 0</span>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="common-functions">8.3. Common Functions</h3>
<div class="paragraph">
<p>These all operate component-wise.
The description is per component.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>abs</strong>(genFType <em>x</em>)<br>
genIType <strong>abs</strong>(genIType <em>x</em>)<br>
genDType <strong>abs</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> if <span class="eq">x ≥ 0</span>; otherwise it returns -<em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>sign</strong>(genFType <em>x</em>)<br>
genIType <strong>sign</strong>(genIType <em>x</em>)<br>
genDType <strong>sign</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 1.0 if <em>x</em> &gt; 0, 0.0 if <em>x</em> = 0, or -1.0 if <em>x</em> &lt; 0.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>floor</strong>(genFType <em>x</em>)<br>
genDType <strong>floor</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a value equal to the nearest integer that is less than or
equal to <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>trunc</strong>(genFType <em>x</em>)<br>
genDType <strong>trunc</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a value equal to the nearest integer to <em>x</em> whose absolute
value is not larger than the absolute value of <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>round</strong>(genFType <em>x</em>)<br>
genDType <strong>round</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a value equal to the nearest integer to <em>x</em>.
The fraction 0.5 will round in a direction chosen by the
implementation, presumably the direction that is fastest.
This includes the possibility that <strong>round</strong>(<em>x</em>) returns the same value
as <strong>roundEven</strong>(<em>x</em>) for all values of <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>roundEven</strong>(genFType <em>x</em>)<br>
genDType <strong>roundEven</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a value equal to the nearest integer to <em>x</em>.
A fractional part of 0.5 will round toward the nearest even integer.
(Both 3.5 and 4.5 for x will return 4.0.)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>ceil</strong>(genFType <em>x</em>)<br>
genDType <strong>ceil</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a value equal to the nearest integer that is greater than or
equal to <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>fract</strong>(genFType <em>x</em>)<br>
genDType <strong>fract</strong>(genDType <em>x</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>x</em> - <strong>floor</strong>(<em>x</em>).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>mod</strong>(genFType <em>x</em>, float <em>y</em>)<br>
genFType <strong>mod</strong>(genFType <em>x</em>, genFType <em>y</em>)<br>
genDType <strong>mod</strong>(genDType <em>x</em>, double <em>y</em>)<br>
genDType <strong>mod</strong>(genDType <em>x</em>, genDType <em>y</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Modulus.
Returns <span class="eq">x - y · <strong>floor</strong>(x / y)</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>modf</strong>(genFType <em>x</em>, out genFType <em>i</em>)<br>
genDType <strong>modf</strong>(genDType <em>x</em>, out genDType <em>i</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the fractional part of <em>x</em> and sets <em>i</em> to the integer part (as
a whole number floating-point value).
Both the return value and the output parameter will have the same sign
as <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>min</strong>(genFType <em>x</em>, genFType <em>y</em>)<br>
genFType <strong>min</strong>(genFType <em>x</em>, float <em>y</em>)<br>
genDType <strong>min</strong>(genDType <em>x</em>, genDType <em>y</em>)<br>
genDType <strong>min</strong>(genDType <em>x</em>, double <em>y</em>)<br>
genIType <strong>min</strong>(genIType <em>x</em>, genIType <em>y</em>)<br>
genIType <strong>min</strong>(genIType <em>x</em>, int <em>y</em>)<br>
genUType <strong>min</strong>(genUType <em>x</em>, genUType <em>y</em>)<br>
genUType <strong>min</strong>(genUType <em>x</em>, uint <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>y</em> &lt; <em>x;</em> otherwise it returns <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>max</strong>(genFType <em>x</em>, genFType <em>y</em>)<br>
genFType <strong>max</strong>(genFType <em>x</em>, float <em>y</em>)<br>
genDType <strong>max</strong>(genDType <em>x</em>, genDType <em>y</em>)<br>
genDType <strong>max</strong>(genDType <em>x</em>, double <em>y</em>)<br>
genIType <strong>max</strong>(genIType <em>x</em>, genIType <em>y</em>)<br>
genIType <strong>max</strong>(genIType <em>x</em>, int <em>y</em>)<br>
genUType <strong>max</strong>(genUType <em>x</em>, genUType <em>y</em>)<br>
genUType <strong>max</strong>(genUType <em>x</em>, uint <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <em>y</em> if <em>x</em> &lt; <em>y;</em> otherwise it returns <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>clamp</strong>(genFType <em>x</em>, genFType <em>minVal</em>, genFType <em>maxVal</em>)<br>
genFType <strong>clamp</strong>(genFType <em>x</em>, float <em>minVal</em>, float <em>maxVal</em>)<br>
genDType <strong>clamp</strong>(genDType <em>x</em>, genDType <em>minVal</em>, genDType <em>maxVal</em>)<br>
genDType <strong>clamp</strong>(genDType <em>x</em>, double <em>minVal</em>, double <em>maxVal</em>)<br>
genIType <strong>clamp</strong>(genIType <em>x</em>, genIType <em>minVal</em>, genIType <em>maxVal</em>)<br>
genIType <strong>clamp</strong>(genIType <em>x</em>, int <em>minVal</em>, int <em>maxVal</em>)<br>
genUType <strong>clamp</strong>(genUType <em>x</em>, genUType <em>minVal</em>, genUType <em>maxVal</em>)<br>
genUType <strong>clamp</strong>(genUType <em>x</em>, uint <em>minVal</em>, uint <em>maxVal</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>min</strong>(<strong>max</strong>(<em>x</em>, <em>minVal</em>), <em>maxVal</em>).
Results are undefined if <em>minVal</em> &gt; <em>maxVal</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>mix</strong>(genFType <em>x</em>, genFType <em>y</em>, genFType <em>a</em>)<br>
genFType <strong>mix</strong>(genFType <em>x</em>, genFType <em>y</em>, float <em>a</em>)<br>
genDType <strong>mix</strong>(genDType <em>x</em>, genDType <em>y</em>, genDType <em>a</em>)<br>
genDType <strong>mix</strong>(genDType <em>x</em>, genDType <em>y</em>, double <em>a</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the linear blend of <em>x</em> and <em>y</em>, i.e.,
<span class="eq">x · (1 - a) + y · a</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>mix</strong>(genFType <em>x</em>, genFType <em>y</em>, genBType <em>a</em>)<br>
genDType <strong>mix</strong>(genDType <em>x</em>, genDType <em>y</em>, genBType <em>a</em>)<br>
genIType <strong>mix</strong>(genIType <em>x</em>, genIType <em>y</em>, genBType <em>a</em>)<br>
genUType <strong>mix</strong>(genUType <em>x</em>, genUType <em>y</em>, genBType <em>a</em>)<br>
genBType <strong>mix</strong>(genBType <em>x</em>, genBType <em>y</em>, genBType <em>a</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Selects which vector each returned component comes from.
For a component of <em>a</em> that is <strong>false</strong>, the corresponding component of
<em>x</em> is returned.
For a component of <em>a</em> that is <strong>true</strong>, the corresponding component of
<em>y</em> is returned.
Components of <em>x</em> and <em>y</em> that are not selected are allowed to be
invalid floating-point values and will have no effect on the results.
Thus, this provides different functionality than, for example,<br>
genFType <strong>mix</strong>(genFType <em>x</em>, genFType <em>y</em>, genFType(<em>a</em>))<br>
where <em>a</em> is a Boolean vector.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>step</strong>(genFType <em>edge</em>, genFType <em>x</em>)<br>
genFType <strong>step</strong>(float <em>edge</em>, genFType <em>x</em>)<br>
genDType <strong>step</strong>(genDType <em>edge</em>, genDType <em>x</em>)<br>
genDType <strong>step</strong>(double <em>edge</em>, genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns 0.0 if <em>x</em> &lt; <em>edge;</em> otherwise it returns 1.0.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>smoothstep</strong>(genFType <em>edge0</em>, genFType <em>edge1</em>, genFType <em>x</em>)<br>
genFType <strong>smoothstep</strong>(float <em>edge0</em>, float <em>edge1</em>, genFType <em>x</em>)<br>
genDType <strong>smoothstep</strong>(genDType <em>edge0</em>, genDType <em>edge1</em>, genDType <em>x</em>)<br>
genDType <strong>smoothstep</strong>(double <em>edge0</em>, double <em>edge1</em>, genDType <em>x</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Returns 0.0 if <span class="eq">x ≤ edge0</span> and 1.0 if <span class="eq">x ≥ edge1</span>, and
performs smooth Hermite interpolation between 0 and 1 when <span class="eq">edge0
&lt; x &lt; edge1</span>.
This is useful in cases where you would want a threshold function with
a smooth transition.
This is equivalent to:</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">genFType t;
t = clamp ((x - edge0) / (edge1 - edge0), <span class="integer">0</span>, <span class="integer">1</span>);
<span class="keyword">return</span> t * t * (<span class="integer">3</span> - <span class="integer">2</span> * t);</code></pre>
</div>
</div>
<div class="paragraph">
<p>(And similarly for doubles.) Results are undefined if <span class="eq">edge0 ≥
edge1</span>.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genBType <strong>isnan</strong>(genFType <em>x</em>)<br>
genBType <strong>isnan</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if <em>x</em> holds a NaN.
Returns <strong>false</strong> otherwise.
Always returns <strong>false</strong> if NaNs are not implemented.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genBType <strong>isinf</strong>(genFType <em>x</em>)<br>
genBType <strong>isinf</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if <em>x</em> holds a positive infinity or negative infinity.
Returns <strong>false</strong> otherwise.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genIType <strong>floatBitsToInt</strong>(highp genFType <em>value</em>)<br>
genUType <strong>floatBitsToUint</strong>(highp genFType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a signed or unsigned integer value representing the encoding
of a floating-point value.
The <strong>float</strong> value&#8217;s bit-level representation is preserved.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>intBitsToFloat</strong>(highp genIType <em>value</em>)<br>
genFType <strong>uintBitsToFloat</strong>(highp genUType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a floating-point value corresponding to a signed or unsigned
integer encoding of a floating-point value.
If a NaN is passed in, it will not signal, and the resulting value is
unspecified.
If an Inf is passed in, the resulting value is the corresponding Inf.
Otherwise, the bit-level representation is preserved.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>fma</strong>(genFType <em>a</em>, genFType <em>b</em>, genFType <em>c</em>)<br>
genDType <strong>fma</strong>(genDType <em>a</em>, genDType <em>b</em>, genDType <em>c</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Computes and returns <code>a * b + c</code>.
In uses where the return value is eventually consumed by a variable
declared as <strong>precise</strong>:</p>
</div>
<div class="openblock">
<div class="content">
<div class="ulist">
<ul>
<li>
<p><strong>fma</strong>() is considered a single operation, whereas the expression <code>a * b
+ c</code> consumed by a variable declared <strong>precise</strong> is considered two
operations.</p>
</li>
<li>
<p>The precision of <strong>fma</strong>() can differ from the precision of the expression
<code>a * b + c</code>.</p>
</li>
<li>
<p><strong>fma</strong>() will be computed with the same precision as any other <strong>fma</strong>()
consumed by a precise variable, giving invariant results for the same
input values of <em>a</em>, <em>b</em>, and <em>c</em>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Otherwise, in the absence of <strong>precise</strong> consumption, there are no special
constraints on the number of operations or difference in precision between
<strong>fma</strong>() and the expression <code>a * b + c</code>.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>frexp</strong>(highp genFType <em>x</em>, out highp genIType <em>exp</em>)
genDType <strong>frexp</strong>(genDType <em>x</em>, out genIType <em>exp</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Splits <em>x</em> into a floating-point significand in the range
<span class="eq">[0.5,1.0]</span>, and an integral exponent of two, such that</p>
<p class="tableblock"> <span class="eq">x = significant · 2<sup>exponent</sup></span></p>
<p class="tableblock"> The significand is returned by the function and the exponent is
returned in the parameter <em>exp</em>.
For a floating-point value of zero, the significand and exponent are
both zero.</p>
<p class="tableblock"> If an implementation supports signed zero, an input value of minus
zero should return a significand of minus zero.
For a floating-point value that is an infinity or is not a number, the
results are undefined.</p>
<p class="tableblock"> If the input <em>x</em> is a vector, this operation is performed in a
component-wise manner; the value returned by the function and the
value written to <em>exp</em> are vectors with the same number of components
as <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>ldexp</strong>(highp genFType <em>x</em>, highp genIType <em>exp</em>)<br>
genDType <strong>ldexp</strong>(genDType <em>x</em>, genIType <em>exp</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Builds a floating-point number from <em>x</em> and the corresponding integral
exponent of two in <em>exp</em>, returning:</p>
<p class="tableblock"> <span class="eq">significand · 2<sup>exponent</sup></span></p>
<p class="tableblock"> If this product is too large to be represented in the floating-point
type, the result is undefined.</p>
<p class="tableblock"> If <em>exp</em> is greater than +128 (single-precision) or +1024
(double-precision), the value returned is undefined.
If <em>exp</em> is less than -126 (single-precision) or -1022
(double-precision), the value returned may be flushed to zero.
Additionally, splitting the value into a significand and exponent
using <strong>frexp</strong>() and then reconstructing a floating-point value using
<strong>ldexp</strong>() should yield the original input for zero and all finite
non-denormalized values.<br>
If the input <em>x</em> is a vector, this operation is performed in a
component-wise manner; the value passed in <em>exp</em> and returned by the
function are vectors with the same number of components as <em>x</em>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="floating-point-pack-and-unpack-functions">8.4. Floating-Point Pack and Unpack Functions</h3>
<div class="paragraph">
<p>These functions do not operate component-wise, rather, as described in each
case.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">highp uint <strong>packUnorm2x16</strong>(vec2 <em>v</em>)<br>
highp uint <strong>packSnorm2x16</strong>(vec2 <em>v</em>)<br>
uint <strong>packUnorm4x8</strong>(vec4 <em>v</em>)<br>
uint <strong>packSnorm4x8</strong>(vec4 <em>v</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">First, converts each component of the normalized floating-point value
<em>v</em> into 16-bit (<strong>2x16</strong>) or 8-bit (<strong>4x8</strong>) integer values.
Then, the results are packed into the returned 32-bit unsigned
integer.</p>
<p class="tableblock"> The conversion for component <em>c</em> of <em>v</em> to fixed point is done as
follows:</p>
<p class="tableblock"> <strong>packUnorm2x16</strong>: <strong>round</strong>(<strong>clamp</strong>(<em>c</em>, 0, +1) * 65535.0)<br>
<strong>packSnorm2x16:</strong> <strong>round</strong>(<strong>clamp</strong>(<em>c</em>, -1, +1) * 32767.0)<br>
<strong>packUnorm4x8</strong>: <strong>round</strong>(<strong>clamp</strong>(<em>c</em>, 0, +1) * 255.0)<br>
<strong>packSnorm4x8</strong>: <strong>round</strong>(<strong>clamp</strong>(<em>c</em>, -1, +1) * 127.0)</p>
<p class="tableblock"> The first component of the vector will be written to the least
significant bits of the output; the last component will be written to
the most significant bits.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> vec2 <strong>unpackUnorm2x16</strong>(highp uint <em>p</em>)<br>
vec2 <strong>unpackSnorm2x16</strong>(highp uint <em>p</em>)<br>
vec4 <strong>unpackUnorm4x8</strong>(highp uint <em>p</em>)<br>
vec4 <strong>unpackSnorm4x8</strong>(highp uint <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">First, unpacks a single 32-bit unsigned integer <em>p</em> into a pair of
16-bit unsigned integers, a pair of 16-bit signed integers, four 8-bit
unsigned integers, or four 8-bit signed integers, respectively.
Then, each component is converted to a normalized floating-point value
to generate the returned two- or four-component vector.</p>
<p class="tableblock"> The conversion for unpacked fixed-point value <em>f</em> to floating-point is
done as follows:</p>
<p class="tableblock"> <strong>unpackUnorm2x16</strong>: <em>f</em> / 65535.0<br>
<strong>unpackSnorm2x16</strong>: <strong>clamp</strong>(<em>f</em> / 32767.0, -1, +1)<br>
<strong>unpackUnorm4x8</strong>: <em>f</em> / 255.0<br>
<strong>unpackSnorm4x8</strong>: <strong>clamp</strong>(<em>f</em> / 127.0, -1, +1)</p>
<p class="tableblock"> The first component of the returned vector will be extracted from the
least significant bits of the input; the last component will be
extracted from the most significant bits.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>packHalf2x16</strong>(vec2 <em>v</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns an unsigned integer obtained by converting the components of a
two-component floating-point vector to the 16-bit floating-point
representation of the <a href="#references">API</a>, and
then packing these two 16-bit integers into a 32-bit unsigned integer.</p>
<p class="tableblock"> The first vector component specifies the 16 least-significant bits of
the result; the second component specifies the 16 most-significant
bits.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> vec2 <strong>unpackHalf2x16</strong>( uint <em>v</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a two-component floating-point vector with components obtained
by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
interpreting those values as 16-bit floating-point numbers according
to the <a href="#references">API</a>, and converting them to
32-bit floating-point values.</p>
<p class="tableblock"> The first component of the vector is obtained from the 16
least-significant bits of <em>v</em>; the second component is obtained from
the 16 most-significant bits of <em>v</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">double <strong>packDouble2x32</strong>(uvec2 <em>v</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a double-precision value obtained by packing the components of
<em>v</em> into a 64-bit value.
If an IEEE 754 Inf or NaN is created, it will not signal, and the
resulting floating-point value is unspecified.
Otherwise, the bit-level representation of <em>v</em> is preserved.
The first vector component specifies the 32 least significant bits;
the second component specifies the 32 most significant bits.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uvec2 <strong>unpackDouble2x32</strong>(double <em>v</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a two-component unsigned integer vector representation of <em>v</em>.
The bit-level representation of <em>v</em> is preserved.
The first component of the vector contains the 32 least significant
bits of the double; the second component consists of the 32 most
significant bits.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="geometric-functions">8.5. Geometric Functions</h3>
<div class="paragraph">
<p>These operate on vectors as vectors, not component-wise.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>length</strong>(genFType <em>x</em>)<br>
double <strong>length</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Returns the length of vector <em>x</em>, i.e.,
<span class="eq">sqrt( x<sub>0</sub><sup>2</sup> + x<sub>1</sub><sup>2</sup> + &#8230;&#8203; )</span>.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>distance</strong>(genFType <em>p0</em>, genFType <em>p1</em>)<br>
double <strong>distance</strong>(genDType <em>p0</em>, genDType <em>p1</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the distance between <em>p0</em> and <em>p1</em>, i.e.,
<strong>length</strong>(<em>p0</em> - <em>p1</em>)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>dot</strong>(genFType <em>x</em>, genFType <em>y</em>)<br>
double <strong>dot</strong>(genDType <em>x</em>, genDType <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the dot product of <em>x</em> and <em>y</em>, i.e.,
<span class="eq">x<sub>0</sub> · y<sub>0</sub> + x<sub>1</sub> · y<sub>1</sub> + &#8230;&#8203;</span></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec3 <strong>cross</strong>(vec3 <em>x</em>, vec3 <em>y</em>)<br>
dvec3 <strong>cross</strong>(dvec3 <em>x</em>, dvec3 <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Returns the cross product of <em>x</em> and <em>y</em>, i.e.,
<span class="eq">(x<sub>1</sub> · y<sub>2</sub> - y<sub>1</sub> · x<sub>2</sub>,
x<sub>2</sub> · y<sub>0</sub> - y<sub>2</sub> · x<sub>0</sub>,
x<sub>0</sub> · y<sub>1</sub> - y<sub>0</sub> · x<sub>1</sub>)</span>.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>normalize</strong>(genFType <em>x</em>)<br>
genDType <strong>normalize</strong>(genDType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a vector in the same direction as <em>x</em> but with a length of 1,
i.e. <em>x</em> / <strong>length</strong>(x).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">compatibility profile only<br>
vec4 <strong>ftransform</strong>()</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Available only when using the compatibility profile.
For core OpenGL, use <strong>invariant</strong>.<br>
For vertex shaders only.
This function will ensure that the incoming vertex value will be
transformed in a way that produces exactly the same result as would be
produced by OpenGL&#8217;s fixed functionality transform.
It is intended to be used to compute <em>gl_Position</em>, e.g.</p>
</div>
<div class="openblock">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><em>gl_Position</em> = <strong>ftransform</strong>()</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>This function should be used, for example, when an application is rendering
the same geometry in separate passes, and one pass uses the fixed
functionality path to render and another pass uses programmable shaders.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>faceforward</strong>(genFType <em>N</em>, genFType <em>I</em>, genFType <em>Nref</em>)<br>
genDType <strong>faceforward</strong>(genDType <em>N</em>, genDType <em>I</em>, genDType <em>Nref</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If <strong>dot</strong>(<em>Nref</em>, <em>I</em>) &lt; 0 return <em>N</em>, otherwise return -<em>N</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>reflect</strong>(genFType <em>I</em>, genFType <em>N</em>)<br>
genDType <strong>reflect</strong>(genDType <em>I</em>, genDType <em>N</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">For the incident vector <em>I</em> and surface orientation <em>N</em>, returns the
reflection direction: <span class="eq">I - 2 · <strong>dot</strong>(N, I) · N</span>.
<em>N</em> must already be normalized in order to achieve the desired result.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>refract</strong>(genFType <em>I</em>, genFType <em>N</em>, float <em>eta</em>)<br>
genDType <strong>refract</strong>(genDType <em>I</em>, genDType <em>N</em>, double <em>eta</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>For the incident vector <em>I</em> and surface normal <em>N</em>, and the ratio of
indices of refraction <em>eta</em>, return the refraction vector.
The result is computed by the <a href="#refraction-equation">refraction
equation</a> shown below.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>The input parameters for the incident vector _I_ and the surface
normal _N_ must already be normalized to get the desired results.</pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
<div class="sect3">
<h4 id="refraction-equation">8.5.1. Refraction Equation</h4>
<div class="stemblock">
<div class="content">
\[k = 1.0 - eta * eta * (1.0 - \textbf{dot}(N,I) \cdot \textbf{dot}(N,I))\]
</div>
</div>
<div class="stemblock">
<div class="content">
\[\begin{aligned}
result &amp;=
\begin{cases}
genFType(0.0), &amp; k &lt; 0.0 \\
eta * I - (eta * \textbf{dot}(N,I) + \sqrt { k }) * N, &amp; \textbf{otherwise}
\end{cases}
\end{aligned}\]
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="matrix-functions">8.6. Matrix Functions</h3>
<div class="paragraph">
<p>For each of the following built-in matrix functions, there is both a
single-precision floating-point version, where all arguments and return
values are single precision, and a double-precision floating-point version,
where all arguments and return values are double precision.
Only the single-precision floating-point version is shown.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mat <strong>matrixCompMult</strong>(mat <em>x</em>, mat <em>y</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply matrix <em>x</em> by matrix <em>y</em> component-wise, i.e., result[i][j]
is the scalar product of <em>x</em>[i][j] and <em>y</em>[i][j].<br></p>
<p class="tableblock"> Note: to get linear algebraic matrix multiplication, use the multiply
operator (<strong>*</strong>).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mat2 <strong>outerProduct</strong>(vec2 <em>c</em>, vec2 <em>r</em>)<br>
mat3 <strong>outerProduct</strong>(vec3 <em>c</em>, vec3 <em>r</em>)<br>
mat4 <strong>outerProduct</strong>(vec4 <em>c</em>, vec4 <em>r</em>)<br>
mat2x3 <strong>outerProduct</strong>(vec3 <em>c</em>, vec2 <em>r</em>)<br>
mat3x2 <strong>outerProduct</strong>(vec2 <em>c</em>, vec3 <em>r</em>)<br>
mat2x4 <strong>outerProduct</strong>(vec4 <em>c</em>, vec2 <em>r</em>)<br>
mat4x2 <strong>outerProduct</strong>(vec2 <em>c</em>, vec4 <em>r</em>)<br>
mat3x4 <strong>outerProduct</strong>(vec4 <em>c</em>, vec3 <em>r</em>)<br>
mat4x3 <strong>outerProduct</strong>(vec3 <em>c</em>, vec4 <em>r</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Treats the first parameter <em>c</em> as a column vector (matrix with one
column) and the second parameter <em>r</em> as a row vector (matrix with one
row) and does a linear algebraic matrix multiply <em>c</em> * <em>r</em>, yielding a
matrix whose number of rows is the number of components in <em>c</em> and
whose number of columns is the number of components in <em>r</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mat2 <strong>transpose</strong>(mat2 <em>m</em>)<br>
mat3 <strong>transpose</strong>(mat3 <em>m</em>)<br>
mat4 <strong>transpose</strong>(mat4 <em>m</em>)<br>
mat2x3 <strong>transpose</strong>(mat3x2 <em>m</em>)<br>
mat3x2 <strong>transpose</strong>(mat2x3 <em>m</em>)<br>
mat2x4 <strong>transpose</strong>(mat4x2 <em>m</em>)<br>
mat4x2 <strong>transpose</strong>(mat2x4 <em>m</em>)<br>
mat3x4 <strong>transpose</strong>(mat4x3 <em>m</em>)<br>
mat4x3 <strong>transpose</strong>(mat3x4 <em>m</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a matrix that is the transpose of <em>m</em>.
The input matrix <em>m</em> is not modified.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>determinant</strong>(mat2 <em>m</em>)<br>
float <strong>determinant</strong>(mat3 <em>m</em>)<br>
float <strong>determinant</strong>(mat4 <em>m</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the determinant of <em>m</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mat2 <strong>inverse</strong>(mat2 <em>m</em>)<br>
mat3 <strong>inverse</strong>(mat3 <em>m</em>)<br>
mat4 <strong>inverse</strong>(mat4 <em>m</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a matrix that is the inverse of <em>m</em>.
The input matrix <em>m</em> is not modified.
The values in the returned matrix are undefined if <em>m</em> is singular or
poorly-conditioned (nearly singular).</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="vector-relational-functions">8.7. Vector Relational Functions</h3>
<div class="paragraph">
<p>Relational and equality operators (<strong>&lt;</strong>, <strong>&lt;=</strong>, <strong>&gt;</strong>, <strong>&gt;=</strong>, <strong>==</strong>, <strong>!=</strong>) are
defined to operate on scalars and produce scalar Boolean results.
For vector results, use the following built-in functions.
Below, the following placeholders are used for the listed specific types:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Placeholder</th>
<th class="tableblock halign-left valign-top">Specific Types Allowed</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec2, bvec3, bvec4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ivec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ivec2, ivec3, ivec4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uvec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">uvec2, uvec3, uvec4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec2, vec3, vec4, dvec2, dvec3, dvec4</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>In all cases, the sizes of all the input and return vectors for any
particular call must match.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>lessThan</strong>(vec x, vec y)<br>
bvec <strong>lessThan</strong>(ivec x, ivec y)<br>
bvec <strong>lessThan</strong>(uvec x, uvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x &lt; y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>lessThanEqual</strong>(vec x, vec y)<br>
bvec <strong>lessThanEqual</strong>(ivec x, ivec y)<br>
bvec <strong>lessThanEqual</strong>(uvec x, uvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x ≤ y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>greaterThan</strong>(vec x, vec y)<br>
bvec <strong>greaterThan</strong>(ivec x, ivec y)<br>
bvec <strong>greaterThan</strong>(uvec x, uvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x &gt; y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>greaterThanEqual</strong>(vec x, vec y)<br>
bvec <strong>greaterThanEqual</strong>(ivec x, ivec y)<br>
bvec <strong>greaterThanEqual</strong>(uvec x, uvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x ≥ y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>equal</strong>(vec x, vec y)<br>
bvec <strong>equal</strong>(ivec x, ivec y)<br>
bvec <strong>equal</strong>(uvec x, uvec y)<br>
bvec <strong>equal</strong>(bvec x, bvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x == y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>notEqual</strong>(vec x, vec y)<br>
bvec <strong>notEqual</strong>(ivec x, ivec y)<br>
bvec <strong>notEqual</strong>(uvec x, uvec y)<br>
bvec <strong>notEqual</strong>(bvec x, bvec y)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise compare of <span class="eq">x ≠ y</span>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>any</strong>(bvec x)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if any component of <em>x</em> is <strong>true</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>all</strong>(bvec x)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> only if all components of <em>x</em> are <strong>true</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bvec <strong>not</strong>(bvec x)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the component-wise logical complement of <em>x</em>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="integer-functions">8.8. Integer Functions</h3>
<div class="paragraph">
<p>These all operate component-wise.
The description is per component.
The notation [<em>a</em>, <em>b</em>] means the set of bits from bit-number <em>a</em> through
bit-number <em>b</em>, inclusive.
The lowest-order bit is bit 0.
&#8220;Bit number&#8221; will always refer to counting up from the lowest-order bit as
bit 0.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genUType <strong>uaddCarry</strong>(highp genUType <em>x</em>, highp genUType <em>y</em>, out lowp genUType <em>carry</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Adds 32-bit unsigned integers <em>x</em> and <em>y</em>, returning the sum modulo
2<sup>32</sup>.
The value <em>carry</em> is set to zero if the sum was less than 2<sup>32</sup>, or
one otherwise.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genUType <strong>usubBorrow</strong>(highp genUType <em>x</em>, highp genUType <em>y</em>, out lowp genUType <em>borrow</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Subtracts the 32-bit unsigned integer <em>y</em> from <em>x</em>, returning the
difference if non-negative, or 2<sup>32</sup> plus the difference otherwise.
The value <em>borrow</em> is set to zero if <span class="eq">x ≥ y</span>, or one
otherwise.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>umulExtended</strong>(highp genUType <em>x</em>, highp genUType <em>y</em>, out highp genUType <em>msb</em>, out highp genUType <em>lsb</em>)<br>
void <strong>imulExtended</strong>(highp genIType <em>x</em>, highp genIType <em>y</em>, out highp genIType <em>msb</em>, out highp genIType <em>lsb</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Multiplies 32-bit unsigned or signed integers <em>x</em> and <em>y</em>, producing a
64-bit result.
The 32 least-significant bits are returned in <em>lsb</em>.
The 32 most-significant bits are returned in <em>msb</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genIType <strong>bitfieldExtract</strong>(genIType <em>value</em>, int <em>offset</em>, int <em>bits</em>)<br>
genUType <strong>bitfieldExtract</strong>(genUType <em>value</em>, int <em>offset</em>, int <em>bits</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Extracts bits <span class="eq">[offset, offset + bits - 1]</span> from <em>value</em>,
returning them in the least significant bits of the result.<br></p>
<p class="tableblock"> For unsigned data types, the most significant bits of the result will
be set to zero.
For signed data types, the most significant bits will be set to the
value of bit <span class="eq">offset + bits - 1</span>.<br></p>
<p class="tableblock"> If <em>bits</em> is zero, the result will be zero.
The result will be undefined if <em>offset</em> or <em>bits</em> is negative, or if
the sum of <em>offset</em> and <em>bits</em> is greater than the number of bits used
to store the operand.
Note that for vector versions of <strong>bitfieldExtract</strong>(), a single pair of
<em>offset</em> and <em>bits</em> values is shared for all components.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genIType <strong>bitfieldInsert</strong>(genIType <em>base</em>, genIType <em>insert</em>, int <em>offset</em>, int <em>bits</em>)<br>
genUType <strong>bitfieldInsert</strong>(genUType <em>base</em>, genUType <em>insert</em>, int <em>offset</em>, int <em>bits</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Inserts the <em>bits</em> least significant bits of <em>insert</em> into <em>base</em>.</p>
<p class="tableblock"> The result will have bits <span class="eq">[offset, offset + bits - 1]</span> taken from
bits <span class="eq">[0, bits - 1]</span> of <em>insert</em>, and all other bits taken
directly from the corresponding bits of <em>base</em>.
If <em>bits</em> is zero, the result will simply be <em>base</em>.
The result will be undefined if <em>offset</em> or <em>bits</em> is negative, or if
the sum of <em>offset</em> and <em>bits</em> is greater than the number of bits used
to store the operand.<br>
Note that for vector versions of <strong>bitfieldInsert</strong>(), a single pair of
<em>offset</em> and <em>bits</em> values is shared for all components.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genIType <strong>bitfieldReverse</strong>(highp genIType <em>value</em>)<br>
genUType <strong>bitfieldReverse</strong>(highp genUType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reverses the bits of <em>value</em>.
The bit numbered <em>n</em> of the result will be taken from bit <span class="eq">(bits -
1) - n</span> of <em>value</em>, where <em>bits</em> is the total number of bits used to
represent <em>value</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> genIType <strong>bitCount</strong>(genIType <em>value</em>)<br>
genIType <strong>bitCount</strong>(genUType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of one bits in the binary representation of
<em>value</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> genIType <strong>findLSB</strong>(genIType <em>value</em>)<br>
genIType <strong>findLSB</strong>(genUType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the bit number of the least significant one bit in the binary
representation of <em>value</em>.
If <em>value</em> is zero, -1 will be returned.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> genIType <strong>findMSB</strong>(highp genIType <em>value</em>)<br>
genIType <strong>findMSB</strong>(highp genUType <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the bit number of the most significant bit in the binary
representation of <em>value</em>.</p>
<p class="tableblock"> For positive integers, the result will be the bit number of the most
significant one bit.
For negative integers, the result will be the bit number of the most
significant zero bit.
For a <em>value</em> of zero or negative one, -1 will be returned.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="texture-functions">8.9. Texture Functions</h3>
<div class="paragraph">
<p>Texture lookup functions are available in all shading stages.
However, level-of-detail is implicitly computed only for fragment shaders.
Other shaders operate as though the base level-of-detail were computed as
zero.
The functions in the table below provide access to textures through
texture-combined samplers, as set up through the API.
Texture properties such as size, pixel format, number of dimensions,
filtering method, number of mipmap levels, depth comparison, and so on are
also defined by API calls.
Such properties are taken into account as the texture is accessed via the
built-in functions defined below.</p>
</div>
<div class="paragraph">
<p>Texture data can be stored by the GL as single-precision floating-point,
unsigned normalized integer, unsigned integer or signed integer data.
This is determined by the type of the internal format of the texture.</p>
</div>
<div class="paragraph">
<p>Texture lookup functions are provided that can return their result as
floating-point, unsigned integer or signed integer, depending on the sampler
type passed to the lookup function.
Care must be taken to use the right sampler type for texture access.
The following table lists the supported combinations of sampler types and
texture internal formats.
Blank entries are unsupported.
Doing a texture lookup will return undefined values for unsupported
combinations.</p>
</div>
<div class="paragraph">
<p>For depth/stencil textures, the internal texture format is determined by the
component being accessed as set through the API.
When the depth/stencil texture mode is set to DEPTH_COMPONENT, the internal
format of the depth component should be used.
When the depth/stencil texture mode is set to STENCIL_INDEX, the internal format
of the stencil component should be used.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Internal Texture Format</th>
<th class="tableblock halign-left valign-top">Floating-Point Sampler Types</th>
<th class="tableblock halign-left valign-top">Signed Integer Sampler Types</th>
<th class="tableblock halign-left valign-top">Unsigned Integer Sampler Types</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Floating-point</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Supported</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Normalized Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Supported</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Signed Integer</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Supported</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Unsigned Integer</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Supported</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>If an integer sampler type is used, the result of a texture lookup is an
<strong>ivec4</strong>.
If an unsigned integer sampler type is used, the result of a texture lookup
is a <strong>uvec4</strong>.
If a floating-point sampler type is used, the result of a texture lookup is
a <strong>vec4</strong>.</p>
</div>
<div class="paragraph">
<p>In the prototypes below, the <code>g</code> in the return type <code>gvec4</code> is used
as a placeholder for either nothing, <code>i</code>, or <code>u</code> making a return type of
<strong>vec4</strong>, <strong>ivec4</strong>, or <strong>uvec4</strong>.
In these cases, the sampler argument type also starts with <code>g</code>,
indicating the same substitution done on the return type; it is either a
single-precision
floating-point, signed integer, or unsigned integer sampler, matching the
basic type of the return type, as described above.</p>
</div>
<div class="paragraph">
<p>For shadow forms (the sampler parameter is a shadow-type), a depth
comparison lookup on the depth texture bound to <em>sampler</em> is done as
described in section
8.23
&#8220;Texture Comparison Modes&#8221; of the
<a href="#references">OpenGL Specification</a>.
See the table below for which component specifies <em>D<sub>ref</sub></em>.
The texture bound to <em>sampler</em> must be a depth texture, or results are
undefined.
If a non-shadow texture call is made to a sampler that represents a depth
texture with depth comparisons turned on, then results are undefined.
If a shadow texture call is made to a sampler that represents a depth
texture with depth comparisons turned off, then results are undefined.
If a shadow texture call is made to a sampler that does not represent a
depth texture, then results are undefined.</p>
</div>
<div class="paragraph">
<p>In all functions below, the <em>bias</em> parameter is optional for fragment
shaders.
The <em>bias</em> parameter is not accepted in any other shader stage.
For a fragment shader, if <em>bias</em> is present, it is added to the implicit
level-of-detail prior to performing the texture access operation.
No <em>bias</em> or <em>lod</em> parameters for
rectangle textures,
multisample textures, or texture buffers
are supported because mipmaps are not allowed for these types of textures.</p>
</div>
<div class="paragraph">
<p>The implicit level-of-detail is selected as follows: For a texture that is
not mipmapped, the texture is used directly.
If it is mipmapped and running in a fragment shader, the level-of-detail
computed by the implementation is used to do the texture lookup.
If it is mipmapped and running in a non-fragment shader, then the base
texture is used.</p>
</div>
<div class="paragraph">
<p>Some texture functions (non-&#8220;<strong>Lod</strong>&#8221; and non-&#8220;<strong>Grad</strong>&#8221; versions) may
require implicit derivatives.
Implicit derivatives are undefined within non-uniform control flow and for
non-fragment shader texture fetches.</p>
</div>
<div class="paragraph">
<p>For <strong>Cube</strong> forms, the direction of <em>P</em> is used to select which face to do a
2-dimensional texture lookup in, as described in section 8.13 &#8220;Cube Map
Texture Selection&#8221; of the <a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>For <strong>Array</strong> forms, the array layer used will be</p>
</div>
<div class="paragraph">
<p>\(\max(0,\min(d-1,\left\lfloor layer + 0.5\right\rfloor))\)</p>
</div>
<div class="paragraph">
<p>where <em>d</em> is the depth of the texture array and <em>layer</em> comes from the
component indicated in the tables below.</p>
</div>
<div class="sect3">
<h4 id="texture-query-functions">8.9.1. Texture Query Functions</h4>
<div class="paragraph">
<p>The <strong>textureSize</strong> functions query the dimensions of a specific texture level
for a texture-combined sampler.</p>
</div>
<div class="paragraph">
<p>The <strong>textureQueryLod</strong> functions are available only in a fragment shader.
They take the components of <em>P</em> and compute the level-of-detail information
that the texture pipe would use to access that texture through a normal
texture lookup.
The level-of-detail \(\lambda^{'}\) (equation 3.18 of the
<a href="#references">OpenGL Specification</a>) is obtained after any level-of-detail bias, but
prior to clamping to [TEXTURE_MIN_LOD, TEXTURE_MAX_LOD].
The mipmap array(s) that would be accessed are also computed.
If a single level-of-detail would be accessed, the level-of-detail number
relative to the base level is returned.
If multiple levels-of-detail would be accessed, a floating-point number
between the two levels is returned, with the fractional part equal to the
fractional part of the computed and clamped level-of-detail.</p>
</div>
<div class="paragraph">
<p>The algorithm used is given by the following pseudo-code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> ComputeAccessedLod(<span class="predefined-type">float</span> computedLod)
{
<span class="comment">// Clamp the computed LOD according to the texture LOD clamps.</span>
<span class="keyword">if</span> (computedLod &lt; TEXTURE_MIN_LOD) computedLod = TEXTURE_MIN_LOD;
<span class="keyword">if</span> (computedLod &gt; TEXTURE_MAX_LOD) computedLod = TEXTURE_MAX_LOD;
<span class="comment">// Clamp the computed LOD to the range of accessible levels.</span>
<span class="keyword">if</span> (computedLod &lt; <span class="float">0</span><span class="float">.0</span>)
computedLod = <span class="float">0</span><span class="float">.0</span>;
<span class="keyword">if</span> (computedLod &gt; (<span class="predefined-type">float</span>) maxAccessibleLevel)
computedLod = (<span class="predefined-type">float</span>) maxAccessibleLevel;
<span class="comment">// Return a value according to the min filter.</span>
<span class="keyword">if</span> (TEXTURE_MIN_FILTER is LINEAR <span class="keyword">or</span> NEAREST) {
<span class="keyword">return</span> <span class="float">0</span><span class="float">.0</span>;
} <span class="keyword">else</span> <span class="keyword">if</span> (TEXTURE_MIN_FILTER is NEAREST_MIPMAP_NEAREST
<span class="keyword">or</span> LINEAR_MIPMAP_NEAREST) {
<span class="keyword">return</span> ceil(computedLod + <span class="float">0</span><span class="float">.5</span>) - <span class="float">1</span><span class="float">.0</span>;
} <span class="keyword">else</span> {
<span class="keyword">return</span> computedLod;
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The value <em>maxAccessibleLevel</em> is the level number of the smallest
accessible level of the mipmap array (the value <em>q</em> in section 8.14.3
&#8220;Mipmapping&#8221; of the <a href="#references">OpenGL Specification</a>) minus the base level.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> int <strong>textureSize</strong>(gsampler1D <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(gsampler2D <em>sampler</em>, int <em>lod</em>)<br>
ivec3 <strong>textureSize</strong>(gsampler3D <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(gsamplerCube <em>sampler</em>, int <em>lod</em>)<br>
int <strong>textureSize</strong>(sampler1DShadow <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(sampler2DShadow <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(samplerCubeShadow <em>sampler</em>, int <em>lod</em>)
ivec3 <strong>textureSize</strong>(gsamplerCubeArray <em>sampler</em>, int <em>lod</em>)<br>
ivec3 <strong>textureSize</strong>(samplerCubeArrayShadow <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(gsampler2DRect <em>sampler</em>)<br>
ivec2 <strong>textureSize</strong>(sampler2DRectShadow <em>sampler</em>)<br>
ivec2 <strong>textureSize</strong>(gsampler1DArray <em>sampler</em>, int <em>lod</em>)<br>
ivec2 <strong>textureSize</strong>(sampler1DArrayShadow <em>sampler</em>, int <em>lod</em>)<br>
ivec3 <strong>textureSize</strong>(gsampler2DArray <em>sampler</em>, int <em>lod</em>)<br>
ivec3 <strong>textureSize</strong>(sampler2DArrayShadow <em>sampler</em>, int <em>lod</em>)<br>
int <strong>textureSize</strong>(gsamplerBuffer <em>sampler</em>)<br>
ivec2 <strong>textureSize</strong>(gsampler2DMS <em>sampler</em>)<br>
ivec3 <strong>textureSize</strong>(gsampler2DMSArray <em>sampler</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the dimensions of level <em>lod</em> (if present) for the texture
bound to <em>sampler</em>, as described in section
8.11 &#8220;Texture Queries&#8221; of the <a href="#references">OpenGL Specification</a>.<br>
The components in the return value are filled in, in order, with the
width, height, and depth of the texture.</p>
<p class="tableblock"> For the array forms, the last component of the return value is the
number of layers in the texture array, or the number of cubes in the
texture cube map array.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec2 <strong>textureQueryLod</strong>(gsampler1D <em>sampler</em>, float <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsamplerCube <em>sampler</em>, vec3 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsampler1DArray <em>sampler</em>, float <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsampler2DArray <em>sampler</em>, vec2 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(gsamplerCubeArray <em>sampler</em>, vec3 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(sampler1DShadow <em>sampler</em>, float <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(sampler2DShadow <em>sampler</em>, vec2 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(samplerCubeShadow <em>sampler</em>, vec3 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(sampler1DArrayShadow <em>sampler</em>, float <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(sampler2DArrayShadow <em>sampler</em>, vec2 <em>P</em>)<br>
vec2 <strong>textureQueryLod</strong>(samplerCubeArrayShadow <em>sampler</em>, vec3 <em>P</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the mipmap array(s) that would be accessed in the <em>x</em>
component of the return value.</p>
<p class="tableblock"> Returns the computed level-of-detail relative to the base level in the
<em>y</em> component of the return value.</p>
<p class="tableblock"> If called on an incomplete texture, the results are undefined.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>textureQueryLevels</strong>(gsampler1D <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsampler2D <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsampler3D <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsamplerCube <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsampler1DArray <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsampler2DArray <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(gsamplerCubeArray <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(sampler1DShadow <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(sampler2DShadow <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(samplerCubeShadow <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(sampler1DArrayShadow <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(sampler2DArrayShadow <em>sampler</em>)<br>
int <strong>textureQueryLevels</strong>(samplerCubeArrayShadow <em>sampler</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of mipmap levels accessible in the texture
associated with <em>sampler</em>, as defined in the <a href="#references">OpenGL Specification.</a></p>
<p class="tableblock"> The value zero will be returned if no texture or an incomplete texture
is associated with <em>sampler</em>.</p>
<p class="tableblock"> Available in all shader stages.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>textureSamples</strong>(gsampler2DMS <em>sampler</em>)<br>
int <strong>textureSamples</strong>(gsampler2DMSArray <em>sampler</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of samples of the texture or textures bound to
<em>sampler</em>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="texel-lookup-functions">8.9.2. Texel Lookup Functions</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>texture</strong>(gsampler1D <em>sampler</em>, float <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsamplerCube <em>sampler</em>, vec3 <em>P</em>[, float <em>bias</em>] )<br>
float <strong>texture</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>])<br>
float <strong>texture</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>])<br>
float <strong>texture</strong>(samplerCubeShadow <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsamplerCubeArray <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>texture</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em> [, float <em>bias</em>] )<br>
float <strong>texture</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>] )<br>
float <strong>texture</strong>(sampler2DArrayShadow <em>sampler</em>, vec4 <em>P</em>)<br>
gvec4 <strong>texture</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>)<br>
float <strong>texture</strong>(sampler2DRectShadow <em>sampler</em>, vec3 <em>P</em>)<br>
float <strong>texture</strong>(samplerCubeArrayShadow <em>sampler</em>, vec4 <em>P</em>, float <em>compare</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Use the texture coordinate <em>P</em> to do a texture lookup in the texture
currently bound to <em>sampler</em>.</p>
<p class="tableblock"> For shadow forms: When <em>compare</em> is present, it is used as <em>D<sub>ref</sub></em>
and the array layer comes from the last component of <em>P</em>.
When <em>compare</em> is not present, the last component of <em>P</em> is used as
<em>D<sub>ref</sub></em> and the array layer comes from the second to last component
of <em>P</em>.
(The second component of <em>P</em> is unused for <strong>1D</strong> shadow lookups.)</p>
<p class="tableblock"> For non-shadow forms: the array layer comes from the last component of
<em>P</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProj</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProj</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProj</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProj</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProj</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
float <strong>textureProj</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
float <strong>textureProj</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProj</strong>(gsampler2DRect <em>sampler</em>, vec3 <em>P</em>)<br>
gvec4 <strong>textureProj</strong>(gsampler2DRect <em>sampler</em>, vec4 <em>P</em>)<br>
float <strong>textureProj</strong>(sampler2DRectShadow <em>sampler</em>, vec4 <em>P</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a texture lookup with projection.
The texture coordinates consumed from <em>P</em>, not including the last
component of <em>P</em>, are divided by the last component of <em>P</em> to
form projected coordinates <em>P'</em>.
The resulting third component of <em>P</em> in the shadow forms is used as
<em>D<sub>ref</sub></em>.
The third component of <em>P</em> is ignored when <em>sampler</em> has type
<strong>gsampler2D</strong> and <em>P</em> has type <strong>vec4</strong>.
After these values are computed, texture lookup proceeds as in
<strong>texture</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureLod</strong>(gsampler1D <em>sampler</em>, float <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsamplerCube <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
float <strong>textureLod</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
float <strong>textureLod</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>)<br>
float <strong>textureLod</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureLod</strong>(gsamplerCubeArray <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Do a texture lookup as in <strong>texture</strong> but with explicit level-of-detail;
<em>lod</em> specifies <span class="eq">λ<sub>base</sub>]</span> and sets the partial derivatives
as follows:<br>
(See section 8.14 &#8220;Texture Minification&#8221; and equations 8.4-8.6 of
the <a href="#references">OpenGL Specification</a>.)<br>
<br>
<span class="eq">∂u / ∂x =
∂v / ∂x =
∂w / ∂x = 0</span>
<br>
<span class="eq">∂u / ∂y =
∂v / ∂y =
∂w / ∂y = 0</span></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureOffset</strong>(gsampler1D <em>sampler</em>, float <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureOffset</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureOffset</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em>, ivec3 <em>offset</em> [, float <em>bias</em>] )<br>
float <strong>textureOffset</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureOffset</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offset</em>)<br>
float <strong>textureOffset</strong>(sampler2DRectShadow <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em>)<br>
float <strong>textureOffset</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureOffset</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureOffset</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br>
float <strong>textureOffset</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
float <strong>textureOffset</strong>(sampler2DArrayShadow <em>sampler</em>, vec4 <em>P</em>, ivec2 <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a texture lookup as in <strong>texture</strong> but with <em>offset</em> added to the
<span class="eq">(u,v,w)</span> texel coordinates before looking up each texel.
The offset value must be a constant expression.
A limited range of offset values are supported; the minimum and
maximum offset values are implementation-dependent and given by
<em>gl_MinProgramTexelOffset</em> and <em>gl_MaxProgramTexelOffset</em>,
respectively.</p>
<p class="tableblock"> Note that <em>offset</em> does not apply to the layer coordinate for texture
arrays.
This is explained in detail in section 8.14.2 &#8220;Coordinate Wrapping
and Texel Selection&#8221; of the <a href="#references">OpenGL Specification</a>, where <em>offset</em>
is <span class="eq">(δ<sub>u</sub>, δ<sub>v</sub>, δ<sub>w</sub>)</span>.<br>
Note that texel offsets are also not supported for cube maps.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>texelFetch</strong>(gsampler1D <em>sampler</em>, int <em>P</em>, int <em>lod</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler2D <em>sampler</em>, ivec2 <em>P</em>, int <em>lod</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler3D <em>sampler</em>, ivec3 <em>P</em>, int <em>lod</em>)
gvec4 <strong>texelFetch</strong>(gsampler2DRect <em>sampler</em>, ivec2 <em>P</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler1DArray <em>sampler</em>, ivec2 <em>P</em>, int <em>lod</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler2DArray <em>sampler</em>, ivec3 <em>P</em>, int <em>lod</em>)<br>
gvec4 <strong>texelFetch</strong>(gsamplerBuffer <em>sampler</em>, int <em>P</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler2DMS <em>sampler</em>, ivec2 <em>P</em>, int <em>sample</em>)<br>
gvec4 <strong>texelFetch</strong>(gsampler2DMSArray <em>sampler</em>, ivec3 <em>P</em>, int <em>sample</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Use integer texture coordinate <em>P</em> to lookup a single texel from
<em>sampler</em>.
The array layer comes from the last component of <em>P</em> for the array
forms.
The level-of-detail <em>lod</em> (if present) is as described in sections
11.1.3.2 &#8220;Texel Fetches&#8221; and 8.14.1 &#8220;Scale Factor and Level of
Detail&#8221; of the <a href="#references">OpenGL Specification</a>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>texelFetchOffset</strong>(gsampler1D <em>sampler</em>, int <em>P</em>, int <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>texelFetchOffset</strong>(gsampler2D <em>sampler</em>, ivec2 <em>P</em>, int <em>lod</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>texelFetchOffset</strong>(gsampler3D <em>sampler</em>, ivec3 <em>P</em>, int <em>lod</em>, ivec3 <em>offset</em>)<br>
gvec4 <strong>texelFetchOffset</strong>(gsampler2DRect <em>sampler</em>, ivec2 <em>P</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>texelFetchOffset</strong>(gsampler1DArray <em>sampler</em>, ivec2 <em>P</em>, int <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>texelFetchOffset</strong>(gsampler2DArray <em>sampler</em>, ivec3 <em>P</em>, int <em>lod</em>, ivec2 <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Fetch a single texel as in <strong>texelFetch</strong>, offset by <em>offset</em> as
described in <strong>textureOffset</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProjOffset</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProjOffset</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProjOffset</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProjOffset</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProjOffset</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em>, ivec3 <em>offset</em> [, float <em>bias</em>] )<br>
gvec4 <strong>textureProjOffset</strong>(gsampler2DRect <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjOffset</strong>(gsampler2DRect <em>sampler</em>, vec4 <em>P</em>, ivec2 <em>offset</em>)<br>
float <strong>textureProjOffset</strong>(sampler2DRectShadow <em>sampler</em>, vec4 <em>P</em>, ivec2 <em>offset</em>)<br>
float <strong>textureProjOffset</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em>, int <em>offset</em> [, float <em>bias</em>] )<br>
float <strong>textureProjOffset</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a projective texture lookup as described in <strong>textureProj</strong>, offset
by <em>offset</em> as described in <strong>textureOffset</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureLodOffset</strong>(gsampler1D <em>sampler</em>, float <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>textureLodOffset</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureLodOffset</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, ivec3 <em>offset</em>)<br>
float <strong>textureLodOffset</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
float <strong>textureLodOffset</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureLodOffset</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>textureLodOffset</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)<br>
float <strong>textureLodOffset</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, int <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do an offset texture lookup with explicit level-of-detail.
See <strong>textureLod</strong> and <strong>textureOffset</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProjLod</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureProjLod</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureProjLod</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureProjLod</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)<br>
gvec4 <strong>textureProjLod</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)<br>
float <strong>textureProjLod</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)<br>
float <strong>textureProjLod</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a projective texture lookup with explicit level-of-detail.
See <strong>textureProj</strong> and <strong>textureLod</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProjLodOffset</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>textureProjLodOffset</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
gvec4 <strong>textureProjLodOffset</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjLodOffset</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjLodOffset</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>, ivec3 <em>offset</em>)<br>
float <strong>textureProjLodOffset</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>, int <em>offset</em>)<br>
float <strong>textureProjLodOffset</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>lod</em>, ivec2 <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do an offset projective texture lookup with explicit level-of-detail.
See <strong>textureProj</strong>, <strong>textureLod</strong>, and <strong>textureOffset</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureGrad</strong>(gsampler1D <em>sampler</em>, <em>float _P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsampler3D <em>sampler</em>, <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsamplerCube <em>sampler</em>, vec3 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(sampler2DRectShadow <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(samplerCubeShadow <em>sampler</em>, vec4 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>)<br>
float <strong>textureGrad</strong>(sampler2DArrayShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
gvec4 <strong>textureGrad</strong>(gsamplerCubeArray <em>sampler</em>, vec4 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Do a texture lookup as in <strong>texture</strong> but with <a href="#explicit-gradients">explicit gradients</a> as shown below.
The partial derivatives of <em>P</em> are with respect to window <em>x</em> and
window <em>y</em>.
For the cube version, the partial derivatives of <em>P</em> are assumed to be
in the coordinate system used before texture coordinates are projected
onto the appropriate cube face.</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureGradOffset</strong>(gsampler1D <em>sampler</em>, float <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
gvec4 <strong>textureGradOffset</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureGradOffset</strong>(gsampler3D <em>sampler</em>, vec3 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>, ivec3 <em>offset</em>)<br>
gvec4 <strong>textureGradOffset</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
float <strong>textureGradOffset</strong>(sampler2DRectShadow <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
float <strong>textureGradOffset</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
float <strong>textureGradOffset</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureGradOffset</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureGradOffset</strong>(gsampler1DArray <em>sampler</em>, vec2 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
float <strong>textureGradOffset</strong>(sampler1DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
float <strong>textureGradOffset</strong>(sampler2DArrayShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a texture lookup with both explicit gradient and offset, as
described in <strong>textureGrad</strong> and <strong>textureOffset</strong>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProjGrad</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler2DRect <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
gvec4 <strong>textureProjGrad</strong>(gsampler2DRect <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureProjGrad</strong>(sampler2DRectShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)<br>
float <strong>textureProjGrad</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>)<br>
float <strong>textureProjGrad</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a texture lookup both projectively, as described in <strong>textureProj</strong>,
and with explicit gradient as described in <strong>textureGrad</strong>.
The partial derivatives <em>dPdx</em> and <em>dPdy</em> are assumed to be already
projected.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureProjGradOffset</strong>(gsampler1D <em>sampler</em>, vec2 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler1D <em>sampler</em>, vec4 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler2D <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler2D <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler3D <em>sampler</em>, vec4 <em>P</em>, vec3 <em>dPdx</em>, vec3 <em>dPdy</em>, ivec3 <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler2DRect <em>sampler</em>, vec3 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureProjGradOffset</strong>(gsampler2DRect <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
float <strong>textureProjGradOffset</strong>(sampler2DRectShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)<br>
float <strong>textureProjGradOffset</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>P</em>, float <em>dPdx</em>, float <em>dPdy</em>, int <em>offset</em>)<br>
float <strong>textureProjGradOffset</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em>, vec2 <em>dPdx</em>, vec2 <em>dPdy</em>, ivec2 <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do a texture lookup projectively and with explicit gradient as
described in <strong>textureProjGrad</strong>, as well as with offset, as described in
<strong>textureOffset</strong>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="explicit-gradients">8.9.3. Explicit Gradients</h4>
<div class="paragraph">
<p>In the <strong>textureGrad</strong> functions described above, explicit gradients control
texture lookups as follows:</p>
</div>
<div class="stemblock">
<div class="content">
\[\begin{aligned}
\frac{\partial{s}}{\partial{x}} &amp; =
\begin{cases}
\frac{\partial{P}}{\partial{x}}, &amp; \text{for a 1D texture} \\[0.8em]
\frac{\partial{P.s}}{\partial{x}}, &amp; \text{otherwise}
\end{cases} \\[2.5em]
\frac{\partial{s}}{\partial{y}} &amp; =
\begin{cases}
\frac{\partial{P}}{\partial{y}}, &amp; \text{for a 1D texture} \\[0.8em]
\frac{\partial{P.s}}{\partial{y}}, &amp; \text{otherwise}
\end{cases} \\[2.5em]
\frac{\partial{t}}{\partial{x}} &amp; =
\begin{cases}
0.0, &amp; \text{for a 1D texture} \\[0.8em]
\frac{\partial{P.t}}{\partial{x}}, &amp; \text{otherwise}
\end{cases} \\[2.5em]
\frac{\partial{t}}{\partial{y}} &amp; =
\begin{cases}
0.0, &amp; \text{for a 1D texture} \\[0.8em]
\frac{\partial{P.t}}{\partial{y}}, &amp; \text{otherwise}
\end{cases} \\[2.5em]
\frac{\partial{r}}{\partial{x}} &amp; =
\begin{cases}
0.0, &amp; \text{for 1D or 2D} \\[0.8em]
\frac{\partial{P.p}}{\partial{x}}, &amp; \text{cube, other}
\end{cases} \\[2.5em]
\frac{\partial{r}}{\partial{y}} &amp; =
\begin{cases}
0.0, &amp; \text{for 1D or 2D} \\[0.8em]
\frac{\partial{P.p}}{\partial{y}}, &amp; \text{cube, other}
\end{cases}
\end{aligned}\]
</div>
</div>
</div>
<div class="sect3">
<h4 id="texture-gather-functions">8.9.4. Texture Gather Functions</h4>
<div class="paragraph">
<p>The texture gather functions take components of a single floating-point
vector operand as a texture coordinate, determine a set of four texels to
sample from the base level-of-detail of the specified texture image, and
return one component from each texel in a four-component result vector.</p>
</div>
<div class="paragraph">
<p>When performing a texture gather operation, the minification and
magnification filters are ignored, and the rules for LINEAR filtering in the
<a href="#references">OpenGL Specification</a> are applied to the base level of the texture image
to identify the four texels <em>i<sub>0</sub> j<sub>1</sub></em>, <em>i<sub>1</sub> j<sub>1</sub></em>, <em>i<sub>1</sub> j<sub>0</sub></em>, and <em>i<sub>0</sub>
j<sub>0</sub></em>.
The texels are then converted to texture base colors (<em>R<sub>s</sub></em>, <em>G<sub>s</sub></em>,
<em>B<sub>s</sub></em>, <em>A<sub>s</sub></em>) according to table 15.1, followed by application of the
texture swizzle as described in section 15.2.1 &#8220;Texture Access&#8221; of the
<a href="#references">OpenGL Specification</a>.
A four-component vector is assembled by taking the selected component from
each of the post-swizzled texture source colors in the order (<em>i<sub>0</sub> j<sub>1</sub></em>,
<em>i<sub>1</sub> j<sub>1</sub></em>, <em>i<sub>1</sub> j<sub>0</sub></em>, <em>i<sub>0</sub> j<sub>0</sub></em>).</p>
</div>
<div class="paragraph">
<p>For texture gather functions using a texture-combined shadow sampler type,
each of the four
texel lookups perform a depth comparison against the depth reference value
passed in (<em>refZ</em>), and returns the result of that comparison in the
appropriate component of the result vector.</p>
</div>
<div class="paragraph">
<p>As with other texture lookup functions, the results of a texture gather are
undefined for shadow samplers if the texture referenced is not a depth
texture or has depth comparisons disabled; or for non-shadow samplers if the
texture referenced is a depth texture with depth comparisons enabled.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureGather</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em> [, int <em>comp</em>])<br>
gvec4 <strong>textureGather</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em> [, int <em>comp</em>])<br>
gvec4 <strong>textureGather</strong>(gsamplerCube <em>sampler</em>, vec3 <em>P</em> [, int <em>comp</em>])<br>
gvec4 <strong>textureGather</strong>(gsamplerCubeArray <em>sampler</em>, vec4 <em>P</em>[, int <em>comp</em>])<br>
gvec4 <strong>textureGather</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>[, int <em>comp</em>])<br>
vec4 <strong>textureGather</strong>(sampler2DShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>)<br>
vec4 <strong>textureGather</strong>(sampler2DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>refZ</em>)<br>
vec4 <strong>textureGather</strong>(samplerCubeShadow <em>sampler</em>, vec3 <em>P</em>, float <em>refZ</em>)<br>
vec4 <strong>textureGather</strong>(samplerCubeArrayShadow <em>sampler</em>, vec4 <em>P</em>, float <em>refZ</em>)<br>
vec4 <strong>textureGather</strong>(sampler2DRectShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Returns the value<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec4(Sample_i0_j1(P, base).comp,
Sample_i1_j1(P, base).comp,
Sample_i1_j0(P, base).comp,
Sample_i0_j0(P, base).comp)</code></pre>
</div>
</div>
<div class="paragraph">
<p>If specified, the value of <em>comp</em> must be a constant integer expression with
a value of 0, 1, 2, or 3, identifying the <em>x</em>, <em>y</em>, <em>z</em>, or <em>w</em>
post-swizzled component of the four-component vector lookup result for each
texel, respectively.
If <em>comp</em> is not specified, it is treated as 0, selecting the <em>x</em> component
of each texel to generate the result.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureGatherOffset</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offset</em>, [ int <em>comp</em>])<br>
gvec4 <strong>textureGatherOffset</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em> [ int <em>comp</em>])<br>
vec4 <strong>textureGatherOffset</strong>(sampler2DShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>, ivec2 <em>offset</em>)<br>
vec4 <strong>textureGatherOffset</strong>(sampler2DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>refZ</em>, ivec2 <em>offset</em>)<br>
gvec4 <strong>textureGatherOffset</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offset</em> [ int <em>comp</em>])<br>
vec4 <strong>textureGatherOffset</strong>(sampler2DRectShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>, ivec2 <em>offset</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Perform a texture gather operation as in <strong>textureGather</strong> by <em>offset</em>
as described in <strong>textureOffset</strong> except that the <em>offset</em> can be
variable (non constant) and the implementation-dependent minimum and
maximum offset values are given by MIN_PROGRAM_TEXTURE_GATHER_OFFSET
and MAX_PROGRAM_TEXTURE_GATHER_OFFSET, respectively.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>textureGatherOffsets</strong>(gsampler2D <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offsets</em>[4] [, int <em>comp</em>])<br>
gvec4 <strong>textureGatherOffsets</strong>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offsets</em>[4] [, int <em>comp</em>])<br>
vec4 <strong>textureGatherOffsets</strong>(sampler2DShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>, ivec2 <em>offsets</em>[4])<br>
vec4 <strong>textureGatherOffsets</strong>(sampler2DArrayShadow <em>sampler</em>, vec3 <em>P</em>, float <em>refZ</em>, ivec2 <em>offsets</em>[4])<br>
gvec4 <strong>textureGatherOffsets</strong>(gsampler2DRect <em>sampler</em>, vec2 <em>P</em>, ivec2 <em>offsets</em>[4] [, int <em>comp</em>])<br>
vec4 <strong>textureGatherOffsets</strong>(sampler2DRectShadow <em>sampler</em>, vec2 <em>P</em>, float <em>refZ</em>, ivec2 <em>offsets</em>[4])</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Operate identically to <strong>textureGatherOffset</strong> except that <em>offsets</em> is
used to determine the location of the four texels to sample.
Each of the four texels is obtained by applying the corresponding
offset in <em>offsets</em> as a (<em>u</em>, <em>v</em>) coordinate offset to <em>P</em>,
identifying the four-texel LINEAR footprint, and then selecting the
texel <em>i<sub>0</sub> j<sub>0</sub></em> of that footprint.
The specified values in <em>offsets</em> must be constant integral
expressions.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="compatibility-profile-texture-functions">8.9.5. Compatibility Profile Texture Functions</h4>
<div class="paragraph">
<p>The following texture functions are only in the compatibility profile.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>texture1D</strong>(sampler1D <em>sampler</em>, float <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture1DProj</strong>(sampler1D <em>sampler</em>, vec2 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture1DProj</strong>(sampler1D <em>sampler</em>, vec4 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture1DLod</strong>(sampler1D <em>sampler</em>, float <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>texture1DProjLod</strong>(sampler1D <em>sampler</em>, vec2 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>texture1DProjLod</strong>(sampler1D <em>sampler</em>, vec4 <em>coord</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">See corresponding signature above without &#8220;1D&#8221; in the name.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>texture2D</strong>(sampler2D <em>sampler</em>, vec2 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture2DProj</strong>(sampler2D <em>sampler</em>, vec3 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture2DProj</strong>(sampler2D <em>sampler</em>, vec4 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture2DLod</strong>(sampler2D <em>sampler</em>, vec2 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>texture2DProjLod</strong>(sampler2D <em>sampler</em>, vec3 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>texture2DProjLod</strong>(sampler2D <em>sampler</em>, vec4 <em>coord</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">See corresponding signature above without &#8220;2D&#8221; in the name.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>texture3D</strong>(sampler3D <em>sampler</em>, vec3 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture3DProj</strong>(sampler3D <em>sampler</em>, vec4 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>texture3DLod</strong>(sampler3D <em>sampler</em>, vec3 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>texture3DProjLod</strong>(sampler3D <em>sampler</em>, vec4 <em>coord</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">See corresponding signature above without &#8220;3D&#8221; in the name.<br>
Use the texture coordinate <em>coord</em> to do a texture lookup in the 3D
texture currently bound to <em>sampler</em>.
For the projective (&#8220;<strong>Proj</strong>&#8221;) versions, the texture coordinate is
divided by <em>coord.q</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>textureCube</strong>(samplerCube <em>sampler</em>, vec3 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>textureCubeLod</strong>(samplerCube <em>sampler</em>, vec3 <em>coord</em>, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">See corresponding signature above without &#8220;Cube&#8221; in the name.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>shadow1D</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>shadow2D</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>shadow1DProj</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>shadow2DProj</strong>(sampler2DShadow <em>sampler</em>, vec4 <em>coord</em> [, float <em>bias</em>] )<br>
vec4 <strong>shadow1DLod</strong>(sampler1DShadow <em>sampler</em>, vec3 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>shadow2DLod</strong>(sampler2DShadow <em>sampler</em>, vec3 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>shadow1DProjLod</strong>(sampler1DShadow <em>sampler</em>, vec4 <em>coord</em>, float <em>lod</em>)<br>
vec4 <strong>shadow2DProjLod</strong>(sampler2DShadow <em>sampler</em>, vec4 coord, float <em>lod</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Same functionality as the &#8220;<strong>texture</strong>&#8221; based names above with the
same signature.</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect2">
<h3 id="atomic-counter-functions">8.10. Atomic Counter Functions</h3>
<div class="paragraph">
<p>The atomic-counter operations in this section operate atomically with
respect to each other.
They are atomic for any single counter, meaning any of these operations on a
specific counter in one shader instantiation will be indivisible by any of
these operations on the same counter from another shader instantiation.
There is no guarantee that these operations are atomic with respect to other
forms of access to the counter or that they are serialized when applied to
separate counters.
Such cases would require additional use of fences, barriers, or other forms
of synchronization, if atomicity or serialization is desired.</p>
</div>
<div class="paragraph">
<p>The underlying counter is a 32-bit unsigned integer.
The result of operations will wrap to [0, 2<sup>32</sup>-1].</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterIncrement</strong>(atomic_uint <em>c</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>increments the counter for <em>c</em>, and</p>
</li>
<li>
<p>returns its value prior to the increment operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterDecrement</strong>(atomic_uint <em>c</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>decrements the counter for <em>c</em>, and</p>
</li>
<li>
<p>returns the value resulting from the decrement operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounter</strong>(atomic_uint <em>c</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the counter value for <em>c</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterAdd</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>adds the value of <em>data</em> to the counter for <em>c</em>, and</p>
</li>
<li>
<p>returns its value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterSubtract</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>subtracts the value of <em>data</em> from the counter for <em>c</em>, and</p>
</li>
<li>
<p>returns its value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterMin</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter for <em>c</em> to the minimum of the value of the counter and
the value of <em>data</em>, and</p>
</li>
<li>
<p>returns the value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterMax</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter for <em>c</em> to the maximum of the value of the counter and
the value of <em>data</em>, and</p>
</li>
<li>
<p>returns the value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterAnd</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter for <em>c</em> to the bitwise AND of the value of the counter
and the value of <em>data</em>, and</p>
</li>
<li>
<p>returns the value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterOr</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter for <em>c</em> to the bitwise OR of the value of the counter
and the value of <em>data</em>, and</p>
</li>
<li>
<p>returns the value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterXor</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter for <em>c</em> to the bitwise XOR of the value of the counter
and the value of <em>data</em>, and</p>
</li>
<li>
<p>returns the value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterExchange</strong>(atomic_uint <em>c</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>sets the counter value for <em>c</em> to the value of <em>data</em>, and</p>
</li>
<li>
<p>returns its value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These two steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCounterCompSwap</strong>(atomic_uint <em>c</em>, uint <em>compare</em>, uint <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Atomically<br></p>
</div>
<div class="openblock">
<div class="content">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>compares the value of <em>compare</em> and the counter value for <em>c</em></p>
</li>
<li>
<p>if the values are equal, sets the counter value for <em>c</em> to the value of
<em>data</em>, and</p>
</li>
<li>
<p>returns its value prior to the operation.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These three steps are done atomically with respect to the atomic counter
functions in this table.</p>
</div>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="atomic-memory-functions">8.11. Atomic Memory Functions</h3>
<div class="paragraph">
<p>Atomic memory functions perform atomic operations on an individual signed or
unsigned integer stored in buffer object or shared variable storage.
All of the atomic memory operations read a value from memory, compute a new
value using one of the operations described below, write the new value to
memory, and return the original value read.
The contents of the memory being updated by the atomic operation are
guaranteed not to be modified by any other assignment or atomic memory
function in any shader invocation between the time the original value is
read and the time the new value is written.</p>
</div>
<div class="paragraph">
<p>Atomic memory functions are supported only for a limited set of variables.
A shader will fail to compile if the value passed to the <em>mem</em> argument of
an atomic memory function does not correspond to a buffer or shared
variable.
It is acceptable to pass an element of an array or a single component of a
vector to the <em>mem</em> argument of an atomic memory function, as long as the
underlying array or vector is a buffer or shared variable.</p>
</div>
<div class="paragraph">
<p>All the built-in functions in this section accept arguments with
combinations of <strong>restrict</strong>, <strong>coherent</strong>, and <strong>volatile</strong> memory qualification,
despite not having them listed in the prototypes.
The atomic operation will operate as required by the calling argument&#8217;s
memory qualification, not by the built-in function&#8217;s formal parameter memory
qualification.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicAdd</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicAdd</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by adding the value of <em>data</em> to the contents
<em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicMin</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicMin</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by taking the minimum of the value of <em>data</em> and
the contents of <em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicMax</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicMax</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by taking the maximum of the value of <em>data</em> and
the contents of <em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicAnd</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicAnd</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise AND of the value of
<em>data</em> and the contents of <em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicOr</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicOr</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise OR of the value of
<em>data</em> and the contents of <em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicXor</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicXor</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise EXCLUSIVE OR of the
value of <em>data</em> and the contents of <em>mem</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicExchange</strong>(inout uint <em>mem</em>, uint <em>data</em>)<br>
int <strong>atomicExchange</strong>(inout int <em>mem</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by simply copying the value of <em>data</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">uint <strong>atomicCompSwap</strong>(inout uint <em>mem</em>, uint <em>compare</em>, uint <em>data</em>)<br>
int <strong>atomicCompSwap</strong>(inout int <em>mem</em>, int <em>compare</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Compares the value of <em>compare</em> and the contents of <em>mem</em>.
If the values are equal, the new value is given by <em>data</em>; otherwise,
it is taken from the original contents of <em>mem</em>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="image-functions">8.12. Image Functions</h3>
<div class="paragraph">
<p>Variables using one of the image basic types may be used by the built-in
shader image memory functions defined in this section to read and write
individual texels of a texture.
Each image variable references an image unit, which has a texture image
attached.</p>
</div>
<div class="paragraph">
<p>When image memory functions below access memory, an individual texel in the
image is identified using an (<em>i</em>), (<em>i, j</em>), or (<em>i, j, k</em>) coordinate
corresponding to the values of <em>P</em>.
For <strong>image2DMS</strong> and <strong>image2DMSArray</strong> variables (and the corresponding
int/unsigned int types) corresponding to multisample textures, each texel
may have multiple samples and an individual sample is identified using the
integer <em>sample</em> parameter.
The coordinates
and sample number
are used to select an individual texel in the manner described in section
8.26
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>Loads and stores support float, integer, and unsigned integer types.
The data types below starting <code>gimage</code> serve as placeholders meaning
types starting either &#8220;<strong>image</strong>&#8221;, &#8220;<strong>iimage</strong>&#8221;, or &#8220;<strong>uimage</strong>&#8221; in the same
way as "<strong>gvec</strong>" or "<strong>gsampler</strong>" in earlier sections.</p>
</div>
<div class="paragraph">
<p>The <em>IMAGE_PARAMS</em> in the prototypes below is a placeholder representing
33
separate functions, each for a different type of image variable.
The <em>IMAGE_PARAMS</em> placeholder is replaced by one of the following parameter
lists:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>gimage2D <em>image</em>, ivec2 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage3D <em>image</em>, ivec3 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimageCube <em>image</em>, ivec3 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimageBuffer <em>image</em>, int <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage2DArray <em>image</em>, ivec3 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimageCubeArray <em>image</em>, ivec3 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage1D <em>image</em>, int <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage1DArray <em>image</em>, ivec2 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage2DRect <em>image</em>, ivec2 <em>P</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage2DMS <em>image</em>, ivec2 <em>P</em>, int <em>sample</em></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>gimage2DMSArray <em>image</em>, ivec3 <em>P</em>, int <em>sample</em></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>where each of the lines represents one of three different image variable
types, and <em>image</em>,
<em>P</em>, and <em>sample</em>
specify the individual texel to operate on.
The method for identifying the individual texel operated on from <em>image</em>,
<em>P</em>,
and <em>sample</em>,
and the method for reading and writing the texel are specified in section
8.26
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL Specification</a>.</p>
</div>
<div class="paragraph">
<p>The atomic functions perform operations on individual texels or samples of
an image variable.
Atomic memory operations read a value from the selected texel, compute a new
value using one of the operations described below, write the new value to
the selected texel, and return the original value read.
The contents of the texel being updated by the atomic operation are
guaranteed not to be modified by any other image store or atomic function
between the time the original value is read and the time the new value is
written.</p>
</div>
<div class="paragraph">
<p>Atomic memory operations are supported on only a subset of all image
variable types; <em>image</em> must be either:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a signed integer image variable (type starts &#8220;<strong>iimage</strong>&#8221;) and a format
qualifier of <strong>r32i</strong>, used with a <em>data</em> argument of type <strong>int</strong>, or</p>
</li>
<li>
<p>an unsigned integer image variable (type starts &#8220;<strong>uimage</strong>&#8221;) and a
format qualifier of <strong>r32ui</strong>, used with a <em>data</em> argument of type <strong>uint</strong>,
or</p>
</li>
<li>
<p>a float image variable (type starts &#8220;<strong>image</strong>&#8221;) and a format qualifier
of <strong>r32f</strong>, used with a <em>data</em> argument of type <strong>float</strong>
(<strong>imageAtomicExchange</strong> only).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>All the built-in functions in this section accept arguments with
combinations of <strong>restrict</strong>, <strong>coherent</strong>, and <strong>volatile</strong> memory qualification,
despite not having them listed in the prototypes.
The image operation will operate as required by the calling argument&#8217;s
memory qualification, not by the built-in function&#8217;s formal parameter memory
qualification.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> int <strong>imageSize</strong>(readonly writeonly gimage1D <em>image</em>)<br>
ivec2 <strong>imageSize</strong>(readonly writeonly gimage2D <em>image</em>)<br>
ivec3 <strong>imageSize</strong>(readonly writeonly gimage3D <em>image</em>)<br>
ivec2 <strong>imageSize</strong>(readonly writeonly gimageCube <em>image</em>)<br>
ivec3 <strong>imageSize</strong>(readonly writeonly gimageCubeArray <em>image</em>)<br>
ivec3 <strong>imageSize</strong>(readonly writeonly gimage2DArray <em>image</em>)<br>
ivec2 <strong>imageSize</strong>(readonly writeonly gimageRect <em>image</em>)<br>
ivec2 <strong>imageSize</strong>(readonly writeonly gimage1DArray <em>image</em>)<br>
ivec2 <strong>imageSize</strong>(readonly writeonly gimage2DMS <em>image</em>)<br>
ivec3 <strong>imageSize</strong>(readonly writeonly gimage2DMSArray <em>image</em>)<br>
int <strong>imageSize</strong>(readonly writeonly gimageBuffer <em>image</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the dimensions of the image or images bound to <em>image</em>.
For arrayed images, the last component of the return value will hold
the size of the array.
Cube images only return the dimensions of one face, and the number of
cubes in the cube map array, if arrayed.<br>
Note: The qualification <strong>readonly writeonly</strong> accepts a variable
qualified with <strong>readonly</strong>, <strong>writeonly</strong>, both, or neither.
It means the formal argument will be used for neither reading nor
writing to the underlying memory.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">int <strong>imageSamples</strong>(readonly writeonly gimage2DMS <em>image</em>)<br>
int <strong>imageSamples</strong>(readonly writeonly gimage2DMSArray <em>image</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the number of samples of the image or images bound to <em>image</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> gvec4 <strong>imageLoad</strong>(readonly <em>IMAGE_PARAMS</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Loads the texel at the coordinate <em>P</em> from the image unit <em>image</em> (in
<em>IMAGE_PARAMS</em>).
For multisample loads, the sample number is given by <em>sample</em>.
When <em>image</em>, <em>P</em>, and <em>sample</em>
identify a valid texel, the bits used to represent the selected texel in
memory are converted to a <strong>vec4</strong>, <strong>ivec4</strong>, or <strong>uvec4</strong> in the manner
described in section
8.26
&#8220;Texture Image Loads and Stores&#8221; of the
<a href="#references">OpenGL Specification</a> and returned.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>imageStore</strong>(writeonly <em>IMAGE_PARAMS</em>, gvec4 <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Stores <em>data</em> into the texel at the coordinate <em>P</em> from the image
specified by <em>image</em>.
For multisample stores, the sample number is given by <em>sample</em>.
When <em>image</em>, <em>P</em>, and <em>sample</em>
identify a valid texel, the bits used to represent <em>data</em> are converted
to the format of the image unit in the manner described in section
8.26
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL Specification</a>
and stored to the specified texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicAdd</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicAdd</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by adding the value of <em>data</em> to the contents of
the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicMin</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicMin</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by taking the minimum of the value of <em>data</em> and
the contents of the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicMax</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicMax</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by taking the maximum of the value <em>data</em> and the
contents of the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicAnd</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicAnd</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise AND of the value of
<em>data</em> and the contents of the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicOr</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicOr</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise OR of the value of
<em>data</em> and the contents of the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicXor</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicXor</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by performing a bit-wise EXCLUSIVE OR of the
value of <em>data</em> and the contents of the selected texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicExchange</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
int <strong>imageAtomicExchange</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)<br>
float <strong>imageAtomicExchange</strong>(<em>IMAGE_PARAMS</em>, float <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Computes a new value by simply copying the value of <em>data</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"> uint <strong>imageAtomicCompSwap</strong>(<em>IMAGE_PARAMS</em>, uint <em>compare</em>, uint <em>data</em>)<br>
int <strong>imageAtomicCompSwap</strong>(<em>IMAGE_PARAMS</em>, int <em>compare</em>, int <em>data</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Compares the value of <em>compare</em> and the contents of the selected
texel.
If the values are equal, the new value is given by <em>data</em>; otherwise,
it is taken from the original value loaded from the texel.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="geometry-shader-functions">8.13. Geometry Shader Functions</h3>
<div class="paragraph">
<p>These functions are only available in geometry shaders.
They are described in more depth following the table.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>EmitStreamVertex</strong>(int <em>stream</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Emits the current values of output variables to the current output
primitive on stream <em>stream</em>.
The argument to <em>stream</em> must be a constant integral expression.
On return from this call, the values of all output variables are
undefined.<br>
Can only be used if multiple output streams are supported.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>EndStreamPrimitive</strong>(int <em>stream</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Completes the current output primitive on stream <em>stream</em> and starts a
new one.
The argument to <em>stream</em> must be a constant integral expression.
No vertex is emitted.<br>
Can only be used if multiple output streams are supported.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>EmitVertex</strong>()<br></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Emits the current values of output variables to the current output
primitive.
When multiple output streams are supported, this is equivalent to
calling <strong>EmitStreamVertex</strong>(0).<br>
On return from this call, the values of output variables are
undefined.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>EndPrimitive</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Completes the current output primitive and starts a new one.
When multiple output streams are supported, this is equivalent to
calling <strong>EndStreamPrimitive</strong>(0).<br>
No vertex is emitted.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The function <strong>EmitStreamVertex</strong>() specifies that a vertex is completed.
A vertex is added to the current output primitive in vertex stream <em>stream</em>
using the current values of all built-in and user-defined output variables
associated with <em>stream</em>.
The values of all output variables for all output streams are undefined
after a call to <strong>EmitStreamVertex</strong>().
If a geometry shader invocation has emitted more vertices than permitted by
the output layout qualifier <strong>max_vertices</strong>, the results of calling
<strong>EmitStreamVertex</strong>() are undefined.</p>
</div>
<div class="paragraph">
<p>The function <strong>EndStreamPrimitive</strong>() specifies that the current output
primitive for vertex stream <em>stream</em> is completed and a new output primitive
(of the same type) will be started by any subsequent <strong>EmitStreamVertex</strong>().
This function does not emit a vertex.
If the output layout is declared to be <strong>points</strong>, calling
<strong>EndStreamPrimitive</strong>() is optional.</p>
</div>
<div class="paragraph">
<p>A geometry shader starts with an output primitive containing no vertices for
each stream.
When a geometry shader terminates, the current output primitive for each
stream is automatically completed.
It is not necessary to call <strong>EndStreamPrimitive</strong>() if the geometry shader
writes only a single primitive.</p>
</div>
<div class="paragraph">
<p>Multiple output streams are supported only if the output primitive type is
declared to be <strong>points</strong>.
It is a compile-time or link-time error if a program contains a geometry
shader calling <strong>EmitStreamVertex</strong>() or <strong>EndStreamPrimitive</strong>() if its output
primitive type is not <strong>points</strong>.</p>
</div>
</div>
<div class="sect2">
<h3 id="fragment-processing-functions">8.14. Fragment Processing Functions</h3>
<div class="paragraph">
<p>Fragment processing functions are only available in fragment shaders.</p>
</div>
<div class="sect3">
<h4 id="derivative-functions">8.14.1. Derivative Functions</h4>
<div class="paragraph">
<p>Derivatives may be computationally expensive and/or numerically unstable.
Therefore, an implementation may approximate the true derivatives
by using a fast but not entirely accurate derivative computation.
Derivatives are undefined within non-uniform control flow.</p>
</div>
<div class="paragraph">
<p>The expected behavior of a derivative is specified using forward/backward
differencing.</p>
</div>
<div class="paragraph">
<p>Forward differencing:</p>
</div>
<div class="paragraph">
<p>\(F(x+dx) - F(x) \sim dFdx(x) \cdot dx (1a)\)</p>
</div>
<div class="paragraph">
<p>\(dFdx(x) \sim \frac{F(x+dx) - F(x)}{dx} (1b)\)</p>
</div>
<div class="paragraph">
<p>Backward differencing:</p>
</div>
<div class="paragraph">
<p>\(F(x-dx) - F(x) \sim -dFdx(x) \cdot dx (2a)\)</p>
</div>
<div class="paragraph">
<p>\(dFdx(x) \sim \frac{F(x) - F(x-dx)}{dx} (2b)\)</p>
</div>
<div class="paragraph">
<p>With single-sample rasterization, \(dx \leq 1.0\) in equations 1b
and 2b.
For multisample rasterization, \(dx &lt; 2.0\) in equations 1b and 2b.</p>
</div>
<div class="paragraph">
<p>\(dFdy\) is approximated similarly, with <em>y</em> replacing <em>x</em>.</p>
</div>
<div class="paragraph">
<p>With multisample rasterization, for any given fragment or sample, either
neighboring fragments or samples may be considered.</p>
</div>
<div class="paragraph">
<p>It is typical to consider a 2x2 square of fragments or samples, and compute
independent <strong>dFdxFine</strong> per row and independent <strong>dFdyFine</strong> per column, while
computing only a single <strong>dFdxCoarse</strong> and a single <strong>dFdyCoarse</strong> for the
entire 2x2 square.
Thus, all second-order coarse derivatives, e.g.
<strong>dFdxCoarse</strong>(<strong>dFdxCoarse</strong>(<em>x</em>)), may be 0, even for non-linear arguments.
However, second-order fine derivatives, e.g. <strong>dFdxFine</strong>(<strong>dFdyFine</strong>(<em>x</em>))
will properly reflect the difference between the independent fine
derivatives computed within the 2x2 square.</p>
</div>
<div class="paragraph">
<p>The method may differ per fragment, subject to the constraint that the
method may vary by window coordinates, not screen coordinates.
The invariance requirement described in section 14.2 &#8220;Invariance&#8221; of the
<a href="#references">OpenGL Specification</a>, is relaxed for derivative calculations, because
the method may be a function of fragment location.</p>
</div>
<div class="paragraph">
<p>In some implementations, varying degrees of derivative accuracy for <strong>dFdx</strong>
and <strong>dFdy</strong> may be obtained by providing GL hints (see section 21.4 &#8220;Hints&#8221;
of the <a href="#references">OpenGL Specification</a>), allowing a user to make an image quality
versus speed trade off.
These hints have no effect on <strong>dFdxCoarse</strong>, <strong>dFdyCoarse</strong>, <strong>dFdxFine</strong> and
<strong>dFdyFine</strong>.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdx</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns either <strong>dFdxFine</strong>(<em>p</em>) or <strong>dFdxCoarse</strong>(<em>p</em>), based on
implementation choice, presumably whichever is the faster, or by whichever
is selected in the API through quality-versus-speed hints.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdy</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns either <strong>dFdyFine</strong>(<em>p</em>) or <strong>dFdyCoarse</strong>(<em>p</em>), based on
implementation choice, presumably whichever is the faster, or by
whichever is selected in the API through quality-versus-speed hints.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdxFine</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the partial derivative of <em>p</em> with respect to the window x
coordinate.
Will use local differencing based on the value of <em>p</em> for the current
fragment and its immediate neighbor(s).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdyFine</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the partial derivative of <em>p</em> with respect to the window y
coordinate.
Will use local differencing based on the value of <em>p</em> for the current
fragment and its immediate neighbor(s).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdxCoarse</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the partial derivative of <em>p</em> with respect to the window x
coordinate.
Will use local differencing based on the value of <em>p</em> for the current
fragment&#8217;s neighbors, and will possibly, but not necessarily, include
the value of <em>p</em> for the current fragment.
That is, over a given area, the implementation can x compute
derivatives in fewer unique locations than would be allowed for
<strong>dFdxFine</strong>(<em>p</em>).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>dFdyCoarse</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the partial derivative of <em>p</em> with respect to the window y
coordinate.
Will use local differencing based on the value of <em>p</em> for the current
fragment&#8217;s neighbors, and will possibly, but not necessarily, include
the value of <em>p</em> for the current fragment.
That is, over a given area, the implementation can compute y
derivatives in fewer unique locations than would be allowed for
<strong>dFdyFine</strong>(<em>p</em>).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>fwidth</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>abs</strong>(<strong>dFdx</strong>(<em>p</em>)) + <strong>abs</strong>(<strong>dFdy</strong>(<em>p</em>)).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>fwidthFine</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>abs</strong>(<strong>dFdxFine</strong>(<em>p</em>)) + <strong>abs</strong>(<strong>dFdyFine</strong>(<em>p</em>)).</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>fwidthCoarse</strong>(genFType <em>p</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>abs</strong>(<strong>dFdxCoarse</strong>(<em>p</em>)) + <strong>abs</strong>(<strong>dFdyCoarse</strong>(<em>p</em>)).</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="interpolation-functions">8.14.2. Interpolation Functions</h4>
<div class="paragraph">
<p>Built-in interpolation functions are available to compute an interpolated
value of a fragment shader input variable at a shader-specified (<em>x</em>, <em>y</em>)
location.
A separate (<em>x</em>, <em>y</em>) location may be used for each invocation of the
built-in function, and those locations may differ from the default (<em>x</em>,
<em>y</em>) location used to produce the default value of the input.</p>
</div>
<div class="paragraph">
<p>For all of the interpolation functions, <em>interpolant</em> must be an l-value
from an <strong>in</strong> declaration;
this can include a variable, a block or structure member, an array element, or
some combination of these.
Additionally, component selection operators (e.g. <strong>.xy</strong>, <strong>.xxz</strong>) may be applied
to <em>interpolant</em>, in which case the interpolation function will return the
result of applying the component selection operator to the interpolated value
of <em>interpolant</em> (for example, interpolateAt(v.xxz) is defined to return
interpolateAt(v).xxz).
Arrayed inputs can be indexed with general (nonuniform) integer expressions.</p>
</div>
<div class="paragraph">
<p>If <em>interpolant</em> is declared with the <strong>flat</strong> qualifier, the interpolated
value will have the same value everywhere for a single primitive, so the
location used for interpolation has no effect and the functions just return
that same value.
If <em>interpolant</em> is declared with the <strong>centroid</strong> qualifier, the value
returned by <strong>interpolateAtSample</strong>() and <strong>interpolateAtOffset</strong>() will be
evaluated at the specified location, ignoring the location normally used
with the <strong>centroid</strong> qualifier.
If <em>interpolant</em> is declared with the <strong>noperspective</strong> qualifier, the
interpolated value will be computed without perspective correction.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>interpolateAtCentroid</strong>(float <em>interpolant</em>)<br>
vec2 <strong>interpolateAtCentroid</strong>(vec2 <em>interpolant</em>)<br>
vec3 <strong>interpolateAtCentroid</strong>(vec3 <em>interpolant</em>)<br>
vec4 <strong>interpolateAtCentroid</strong>(vec4 <em>interpolant</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value of the input <em>interpolant</em> sampled at a location
inside both the pixel and the primitive being processed.
The value obtained would be the same value assigned to the input
variable if declared with the <strong>centroid</strong> qualifier.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>interpolateAtSample</strong>(float <em>interpolant</em>, int <em>sample</em>)<br>
vec2 <strong>interpolateAtSample</strong>(vec2 <em>interpolant</em>, int <em>sample</em>)<br>
vec3 <strong>interpolateAtSample</strong>(vec3 <em>interpolant</em>, int <em>sample</em>)<br>
vec4 <strong>interpolateAtSample</strong>(vec4 <em>interpolant</em>, int <em>sample</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value of the input <em>interpolant</em> variable at the location
of sample number <em>sample</em>.
If multisample buffers are not available, the input variable will be
evaluated at the center of the pixel.
If sample <em>sample</em> does not exist, the position used to interpolate
the input variable is undefined.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>interpolateAtOffset</strong>(float <em>interpolant</em>, vec2 offset)<br>
vec2 <strong>interpolateAtOffset</strong>(vec2 <em>interpolant</em>, vec2 offset)<br>
vec3 <strong>interpolateAtOffset</strong>(vec3 <em>interpolant</em>, vec2 offset)<br>
vec4 <strong>interpolateAtOffset</strong>(vec4 <em>interpolant</em>, vec2 offset)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns the value of the input <em>interpolant</em> variable sampled at an
offset from the center of the pixel specified by <em>offset</em>.
The two floating-point components of <em>offset</em>, give the offset in
pixels in the <em>x</em> and <em>y</em> directions, respectively.<br>
An offset of (0, 0) identifies the center of the pixel.
The range and granularity of offsets supported by this function is
implementation-dependent.</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect2">
<h3 id="noise-functions">8.15. Noise Functions</h3>
<div class="paragraph">
<p>The noise functions <strong>noise1</strong>, <strong>noise2</strong>, <strong>noise3</strong>, and <strong>noise4</strong> have been
deprecated starting with version 4.4 of GLSL.
When not generating SPIR-V they are defined to return the value 0.0 or a vector
whose components are all 0.0. When generating SPIR-V the noise functions are
not declared and may not be used.</p>
</div>
<div class="paragraph">
<p>As in previous releases, the noise functions are not semantically considered to
be compile-time constant expressions.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax (deprecated)</th>
<th class="tableblock halign-left valign-top">Description (deprecated)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">float <strong>noise1</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a 1D noise value based on the input value <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec2 <strong>noise2</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a 2D noise value based on the input value <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec3 <strong>noise3</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a 3D noise value based on the input value <em>x</em>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">vec4 <strong>noise4</strong>(genFType <em>x</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns a 4D noise value based on the input value <em>x</em>.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="shader-invocation-control-functions">8.16. Shader Invocation Control Functions</h3>
<div class="paragraph">
<p>The shader invocation control function is only available in tessellation
control and compute shaders.
It is used to control the relative execution order of multiple shader
invocations used to process a patch (in the case of tessellation control
shaders) or a workgroup (in the case of compute shaders), which are
otherwise executed with an undefined relative order.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>barrier</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">For any given static instance of <strong>barrier</strong>(), all tessellation control
shader invocations for a single input patch must enter it before any
will be allowed to continue beyond it, or all compute shader
invocations for a single workgroup must enter it before any will
continue beyond it.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The function <strong>barrier</strong>() provides a partially defined order of execution
between shader invocations.
The ensures that, for some types of memory accesses, values written by one
invocation prior to a given static instance of <strong>barrier</strong>() can be safely read
by other invocations after their call to the same static instance <strong>barrier</strong>().
Because invocations may execute in an undefined order between these barrier
calls, the values of a per-vertex or per-patch output variable for tessellation
control shaders, or the values of <strong>shared</strong> variables for compute shaders will be
undefined in a number of cases enumerated in
&#8220;<a href="#output-variables">Output Variables</a>&#8221; (for tessellation control shaders)
and &#8220;<a href="#shared-variables">Shared Variables</a>&#8221; (for compute shaders).</p>
</div>
<div class="paragraph">
<p>For tessellation control shaders, the <strong>barrier</strong>() function may only be
placed inside the function <strong>main</strong>() of the shader and may not be called
within any control flow.
Barriers are also disallowed after a return statement in the function
<strong>main</strong>().
Any such misplaced barriers result in a compile-time error.</p>
</div>
<div class="paragraph">
<p>A <strong>barrier</strong>() affects control flow but only synchronizes memory accesses
to <strong>shared</strong> variables and tessellation control output variables.
For other memory accesses, it does not ensure that values written by one invocation
prior to a given static instance of <strong>barrier</strong>() can be safely read by other
invocations after their call to the same static instance of <strong>barrier</strong>().
To achieve this requires the use of both <strong>barrier</strong>() and a memory barrier.</p>
</div>
<div class="paragraph">
<p>For compute shaders, the <strong>barrier</strong>() function may be placed within control
flow, but that control flow must be uniform control flow.
That is, all the controlling expressions that lead to execution of the
barrier must be dynamically uniform expressions.
This ensures that if any shader invocation enters a conditional statement,
then all invocations will enter it.
While compilers are encouraged to give warnings if they can detect this
might not happen, compilers cannot completely determine this.
Hence, it is the author&#8217;s responsibility to ensure <strong>barrier</strong>() only exists
inside uniform control flow.
Otherwise, some shader invocations will stall indefinitely, waiting for a
barrier that is never reached by other invocations.</p>
</div>
</div>
<div class="sect2">
<h3 id="shader-memory-control-functions">8.17. Shader Memory Control Functions</h3>
<div class="paragraph">
<p>Within a single shader invocation, the visibility and order of writes made
by that invocation are well-defined.
However, the relative order of reads and writes to a single shared memory
address from multiple separate shader invocations is largely undefined.
Additionally, the order of accesses to multiple memory addresses performed
by a single shader invocation, as observed by other shader invocations, is
also undefined.</p>
</div>
<div class="paragraph">
<p>The following built-in functions can be used to control the ordering of
reads and writes:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>memoryBarrier</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of memory transactions issued by a single shader
invocation.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>memoryBarrierAtomicCounter</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of accesses to atomic-counter variables issued by
a single shader invocation.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>memoryBarrierBuffer</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of memory transactions to buffer variables issued
within a single shader invocation.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>memoryBarrierShared</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of memory transactions to shared variables issued
within a single shader invocation, as viewed by other invocations in
the same workgroup.<br>
Only available in compute shaders.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>memoryBarrierImage</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of memory transactions to images issued within a
single shader invocation.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">void <strong>groupMemoryBarrier</strong>()</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Control the ordering of all memory transactions issued within a single
shader invocation, as viewed by other invocations in the same workgroup.<br>
Only available in compute shaders.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The memory barrier built-in functions can be used to order reads and writes
to variables stored in memory accessible to other shader invocations.
When called, these functions will wait for the completion of all reads and
writes previously performed by the caller that access selected variable
types, and then return with no other effect.
The built-in functions <strong>memoryBarrierAtomicCounter</strong>(),
<strong>memoryBarrierBuffer</strong>(), <strong>memoryBarrierImage</strong>(), and <strong>memoryBarrierShared</strong>()
wait for the completion of accesses to atomic counter, buffer, image, and
shared variables, respectively.
The built-in functions <strong>memoryBarrier</strong>() and <strong>groupMemoryBarrier</strong>() wait for
the completion of accesses to all of the above variable types.
The functions <strong>memoryBarrierShared</strong>() and <strong>groupMemoryBarrier</strong>() are
available only in compute shaders; the other functions are available in all
shader types.</p>
</div>
<div class="paragraph">
<p>When these functions return, the effects of any memory stores performed
using coherent variables prior to the call will be visible to any
future<sup>1</sup> coherent access to the same memory performed by any other shader
invocation.
In particular, the values written this way in one shader stage are
guaranteed to be visible to coherent memory accesses performed by shader
invocations in subsequent stages when those invocations were triggered by
the execution of the original shader invocation (e.g. fragment shader
invocations for a primitive resulting from a particular geometry
shader invocation).</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">1</dt>
<dd>
<p>An access is only a <em>future</em> access if a <em>happens-before</em> relation can
be established between the store and the load.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Additionally, memory barrier functions order stores performed by the calling
invocation, as observed by other shader invocations.
Without memory barriers, if one shader invocation performs two stores to
coherent variables, a second shader invocation might see the values written
by the second store prior to seeing those written by the first.
However, if the first shader invocation calls a memory barrier function
between the two stores, selected other shader invocations will never see the
results of the second store before seeing those of the first.
When using the functions <strong>groupMemoryBarrier</strong>() or <strong>memoryBarrierShared</strong>(),
this ordering guarantee applies only to other shader invocations in the same
compute shader workgroup; all other memory barrier functions provide the
guarantee to all other shader invocations.
No memory barrier is required to guarantee the order of memory stores as
observed by the invocation performing the stores; an invocation reading from
a variable that it previously wrote will always see the most recently
written value unless another shader invocation also wrote to the same
memory.</p>
</div>
</div>
<div class="sect2">
<h3 id="_subpass_input_functions">8.18. Subpass-Input Functions</h3>
<div class="paragraph">
<p>Subpass-input functions are only available when targeting a Vulkan fragment stage.</p>
</div>
<div class="paragraph">
<p>Subpass inputs are read through the built-in functions below. The <code>g</code> is again
a placeholder for either nothing, <code>i</code>, or <code>u</code>, indicating either a floating-point,
signed integer, or unsigned integer, and these must match between argument type
and return type.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">gvec4 <strong>subpassLoad</strong>(gsubpassInput subpass)<br>
gvec4 <strong>subpassLoad</strong>(gsubpassInputMS subpass, int sample)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Read from a subpass input, from the implicit location <em>(x, y, layer)</em>
of the current fragment coordinate.</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="shader-invocation-group-functions">8.19. Shader Invocation Group Functions</h3>
<div class="paragraph">
<p>Implementations of the OpenGL Shading Language may optionally group multiple shader
invocations for a single shader stage into a single SIMD invocation group,
where invocations are assigned to groups in an undefined,
implementation-dependent manner.
Shader algorithms on such implementations may benefit from being able to
evaluate a composite of Boolean values over all active invocations in a
group.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Syntax</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>anyInvocation</strong>(bool <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if and only if <em>value</em> is <strong>true</strong> for at least one
active invocation in the group.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>allInvocations</strong>(bool <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if and only if <em>value</em> is <strong>true</strong> for all active
invocations in the group.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">bool <strong>allInvocationsEqual</strong>(bool <em>value</em>)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <strong>true</strong> if <em>value</em> is the same for all active invocations in
the group.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For all of these functions, the same result is returned to all active
invocations in the group.</p>
</div>
<div class="paragraph">
<p>These functions may be called within conditionally executed code.
In groups where some invocations do not execute the function call, the value
returned by the function is not affected by any invocation not calling the
function, even when value is well-defined for that invocation.</p>
</div>
<div class="paragraph">
<p>Because these functions depend on the values of <em>value</em> in an undefined
group of invocations, the value returned by these functions is largely
undefined.
However, <strong>anyInvocation</strong>() is guaranteed to return <strong>true</strong> if <em>value</em> is
<strong>true</strong>, and <strong>allInvocations</strong>() is guaranteed to return <strong>false</strong> if <em>value</em> is
<strong>false</strong>.</p>
</div>
<div class="paragraph">
<p>Because implementations are not required to combine invocations into groups,
simply returning <em>value</em> for <strong>anyInvocation</strong>() and <strong>allInvocations</strong>() and
returning true for <strong>allInvocationsEqual</strong>() is a legal implementation of
these functions.</p>
</div>
<div class="paragraph">
<p>For fragment shaders, invocations in a SIMD invocation group may include
invocations corresponding to pixels that are covered by a primitive being
rasterized, as well as invocations corresponding to neighboring pixels not
covered by the primitive.
<em>Helper invocations</em> (see &#8220;<a href="#built-in-language-variables">Built-In Language
Variables</a>&#8221;) may be created and the value of <em>value</em> for such
helper-invocation pixels may affect the value returned by <strong>anyInvocation</strong>(),
<strong>allInvocations</strong>(), and <strong>allInvocationsEqual</strong>().</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="shading-language-grammar">9. Shading Language Grammar</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The grammar is fed from the output of lexical analysis.
The tokens returned from lexical analysis are</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="paragraph">
<p>CONST BOOL FLOAT INT UINT
DOUBLE</p>
</div>
<div class="paragraph">
<p>BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4</p>
</div>
<div class="paragraph">
<p>MAT2 MAT3 MAT4
MAT2X2 MAT2X3 MAT2X4
MAT3X2 MAT3X3 MAT3X4
MAT4X2 MAT4X3 MAT4X4</p>
</div>
<div class="paragraph">
<p>DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
DMAT2X2 DMAT2X3 DMAT2X4
DMAT3X2 DMAT3X3 DMAT3X4
DMAT4X2 DMAT4X3 DMAT4X4</p>
</div>
<div class="paragraph">
<p>CENTROID IN OUT INOUT UNIFORM PATCH SAMPLE BUFFER SHARED
COHERENT VOLATILE RESTRICT READONLY WRITEONLY
NOPERSPECTIVE
FLAT SMOOTH LAYOUT</p>
</div>
<div class="paragraph">
<p>ATOMIC_UINT</p>
</div>
<div class="paragraph">
<p>SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER2DSHADOW
SAMPLERCUBESHADOW SAMPLER2DARRAY SAMPLER2DARRAYSHADOW
ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY</p>
</div>
<div class="paragraph">
<p>SAMPLER1D SAMPLER1DSHADOW
SAMPLER1DARRAY SAMPLER1DARRAYSHADOW
ISAMPLER1D ISAMPLER1DARRAY
USAMPLER1D USAMPLER1DARRAY
SAMPLER2DRECT SAMPLER2DRECTSHADOW ISAMPLER2DRECT USAMPLER2DRECT</p>
</div>
<div class="paragraph">
<p>SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER
SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW
ISAMPLERCUBEARRAY USAMPLERCUBEARRAY
SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
IMAGE2D IIMAGE2D UIMAGE2D
IMAGE3D IIMAGE3D UIMAGE3D
IMAGECUBE IIMAGECUBE UIMAGECUBE
IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY</p>
</div>
<div class="paragraph">
<p>IMAGE1D IIMAGE1D UIMAGE1D
IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY
IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT
IMAGE2DMS IIMAGE2DMS UIMAGE2DMS
IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY</p>
</div>
<div class="paragraph">
<p>STRUCT VOID</p>
</div>
<div class="paragraph">
<p>WHILE BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
SUBROUTINE</p>
</div>
<div class="paragraph">
<p>IDENTIFIER TYPE_NAME
FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
DOUBLECONSTANT
FIELD_SELECTION</p>
</div>
<div class="paragraph">
<p>LEFT_OP RIGHT_OP
INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
SUB_ASSIGN
LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION</p>
</div>
<div class="paragraph">
<p>INVARIANT PRECISE
HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION</p>
</div>
</div>
</div>
<div class="paragraph">
<p>The following describes the grammar for the OpenGL Shading Language in terms of the above
tokens.
The starting rule is <em>translation_unit</em>.
An empty shader (one having no tokens to parse, after pre-processing) is
valid, resulting in no compile-time errors, even though the grammar below
does not have a rule to accept an empty token stream.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>variable_identifier</em> : </dt>
<dd>
<p><em>IDENTIFIER</em></p>
</dd>
<dt class="hdlist1"><em>primary_expression</em> : </dt>
<dd>
<p><em>variable_identifier</em><br>
<em>INTCONSTANT</em><br>
<em>UINTCONSTANT</em><br>
<em>FLOATCONSTANT</em><br>
<em>BOOLCONSTANT</em><br>
<em>DOUBLECONSTANT</em><br>
<em>LEFT_PAREN</em> <em>expression</em> <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>postfix_expression</em> : </dt>
<dd>
<p><em>primary_expression</em><br>
<em>postfix_expression</em> <em>LEFT_BRACKET</em> <em>integer_expression</em> <em>RIGHT_BRACKET</em><br>
<em>function_call</em><br>
<em>postfix_expression</em> <em>DOT</em> <em>FIELD_SELECTION</em><br>
<em>postfix_expression</em> <em>INC_OP</em><br>
<em>postfix_expression</em> <em>DEC_OP</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>FIELD_SELECTION includes members in structures, component selection for
vectors and the 'length' identifier for the length() method</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>integer_expression</em> : </dt>
<dd>
<p><em>expression</em></p>
</dd>
<dt class="hdlist1"><em>function_call</em> : </dt>
<dd>
<p><em>function_call_or_method</em></p>
</dd>
<dt class="hdlist1"><em>function_call_or_method</em> : </dt>
<dd>
<p><em>function_call_generic</em></p>
</dd>
<dt class="hdlist1"><em>function_call_generic</em> : </dt>
<dd>
<p><em>function_call_header_with_parameters</em> <em>RIGHT_PAREN</em><br>
<em>function_call_header_no_parameters</em> <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>function_call_header_no_parameters</em> : </dt>
<dd>
<p><em>function_call_header</em> <em>VOID</em><br>
<em>function_call_header</em></p>
</dd>
<dt class="hdlist1"><em>function_call_header_with_parameters</em> : </dt>
<dd>
<p><em>function_call_header</em> <em>assignment_expression</em><br>
<em>function_call_header_with_parameters</em> <em>COMMA</em> <em>assignment_expression</em></p>
</dd>
<dt class="hdlist1"><em>function_call_header</em> : </dt>
<dd>
<p><em>function_identifier</em> <em>LEFT_PAREN</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: Constructors look like functions, but lexical analysis
recognized most of them as keywords.
They are now recognized through <em>type_specifier</em>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Methods (<strong>.length</strong>), subroutine array calls, and identifiers are recognized
through <em>postfix_expression</em>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>function_identifier</em> : </dt>
<dd>
<p><em>type_specifier</em><br>
<em>postfix_expression</em></p>
</dd>
<dt class="hdlist1"><em>unary_expression</em> : </dt>
<dd>
<p><em>postfix_expression</em><br>
<em>INC_OP</em> <em>unary_expression</em><br>
<em>DEC_OP</em> <em>unary_expression</em><br>
<em>unary_operator</em> <em>unary_expression</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: No traditional style type casts.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>unary_operator</em> : </dt>
<dd>
<p><em>PLUS</em><br>
<em>DASH</em><br>
<em>BANG</em><br>
<em>TILDE</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: No '*' or '&amp;' unary ops.
Pointers are not supported.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>multiplicative_expression</em> : </dt>
<dd>
<p><em>unary_expression</em><br>
<em>multiplicative_expression</em> <em>STAR</em> <em>unary_expression</em><br>
<em>multiplicative_expression</em> <em>SLASH</em> <em>unary_expression</em><br>
<em>multiplicative_expression</em> <em>PERCENT</em> <em>unary_expression</em></p>
</dd>
<dt class="hdlist1"><em>additive_expression</em> : </dt>
<dd>
<p><em>multiplicative_expression</em><br>
<em>additive_expression</em> <em>PLUS</em> <em>multiplicative_expression</em><br>
<em>additive_expression</em> <em>DASH</em> <em>multiplicative_expression</em></p>
</dd>
<dt class="hdlist1"><em>shift_expression</em> : </dt>
<dd>
<p><em>additive_expression</em><br>
<em>shift_expression</em> <em>LEFT_OP</em> <em>additive_expression</em><br>
<em>shift_expression</em> <em>RIGHT_OP</em> <em>additive_expression</em></p>
</dd>
<dt class="hdlist1"><em>relational_expression</em> : </dt>
<dd>
<p><em>shift_expression</em><br>
<em>relational_expression</em> <em>LEFT_ANGLE</em> <em>shift_expression</em><br>
<em>relational_expression</em> <em>RIGHT_ANGLE</em> <em>shift_expression</em><br>
<em>relational_expression</em> <em>LE_OP</em> <em>shift_expression</em><br>
<em>relational_expression</em> <em>GE_OP</em> <em>shift_expression</em></p>
</dd>
<dt class="hdlist1"><em>equality_expression</em> : </dt>
<dd>
<p><em>relational_expression</em><br>
<em>equality_expression</em> <em>EQ_OP</em> <em>relational_expression</em><br>
<em>equality_expression</em> <em>NE_OP</em> <em>relational_expression</em></p>
</dd>
<dt class="hdlist1"><em>and_expression</em> : </dt>
<dd>
<p><em>equality_expression</em><br>
<em>and_expression</em> <em>AMPERSAND</em> <em>equality_expression</em></p>
</dd>
<dt class="hdlist1"><em>exclusive_or_expression</em> : </dt>
<dd>
<p><em>and_expression</em><br>
<em>exclusive_or_expression</em> <em>CARET</em> <em>and_expression</em></p>
</dd>
<dt class="hdlist1"><em>inclusive_or_expression</em> : </dt>
<dd>
<p><em>exclusive_or_expression</em><br>
<em>inclusive_or_expression</em> <em>VERTICAL_BAR</em> <em>exclusive_or_expression</em></p>
</dd>
<dt class="hdlist1"><em>logical_and_expression</em> : </dt>
<dd>
<p><em>inclusive_or_expression</em><br>
<em>logical_and_expression</em> <em>AND_OP</em> <em>inclusive_or_expression</em></p>
</dd>
<dt class="hdlist1"><em>logical_xor_expression</em> : </dt>
<dd>
<p><em>logical_and_expression</em><br>
<em>logical_xor_expression</em> <em>XOR_OP</em> <em>logical_and_expression</em></p>
</dd>
<dt class="hdlist1"><em>logical_or_expression</em> : </dt>
<dd>
<p><em>logical_xor_expression</em><br>
<em>logical_or_expression</em> <em>OR_OP</em> <em>logical_xor_expression</em></p>
</dd>
<dt class="hdlist1"><em>conditional_expression</em> : </dt>
<dd>
<p><em>logical_or_expression</em><br>
<em>logical_or_expression</em> <em>QUESTION</em> <em>expression</em> <em>COLON</em>
<em>assignment_expression</em></p>
</dd>
<dt class="hdlist1"><em>assignment_expression</em> : </dt>
<dd>
<p><em>conditional_expression</em><br>
<em>unary_expression</em> <em>assignment_operator</em> <em>assignment_expression</em></p>
</dd>
<dt class="hdlist1"><em>assignment_operator</em> : </dt>
<dd>
<p><em>EQUAL</em><br>
<em>MUL_ASSIGN</em><br>
<em>DIV_ASSIGN</em><br>
<em>MOD_ASSIGN</em><br>
<em>ADD_ASSIGN</em><br>
<em>SUB_ASSIGN</em><br>
<em>LEFT_ASSIGN</em><br>
<em>RIGHT_ASSIGN</em><br>
<em>AND_ASSIGN</em><br>
<em>XOR_ASSIGN</em><br>
<em>OR_ASSIGN</em></p>
</dd>
<dt class="hdlist1"><em>expression</em> : </dt>
<dd>
<p><em>assignment_expression</em><br>
<em>expression</em> <em>COMMA</em> <em>assignment_expression</em></p>
</dd>
<dt class="hdlist1"><em>constant_expression</em> : </dt>
<dd>
<p><em>conditional_expression</em></p>
</dd>
<dt class="hdlist1"><em>declaration</em> : </dt>
<dd>
<p><em>function_prototype</em> <em>SEMICOLON</em><br>
<em>init_declarator_list</em> <em>SEMICOLON</em><br>
<em>PRECISION</em> <em>precision_qualifier</em> <em>type_specifier</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>IDENTIFIER</em> <em>LEFT_BRACE</em> <em>struct_declaration_list</em>
<em>RIGHT_BRACE</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>IDENTIFIER</em> <em>LEFT_BRACE</em> <em>struct_declaration_list</em>
<em>RIGHT_BRACE</em> <em>IDENTIFIER</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>IDENTIFIER</em> <em>LEFT_BRACE</em> <em>struct_declaration_list</em>
<em>RIGHT_BRACE</em> <em>IDENTIFIER</em> <em>array_specifier</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>IDENTIFIER</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>IDENTIFIER</em> <em>identifier_list</em> <em>SEMICOLON</em></p>
</dd>
<dt class="hdlist1"><em>identifier_list</em> : </dt>
<dd>
<p><em>COMMA</em> <em>IDENTIFIER</em><br>
<em>identifier_list</em> <em>COMMA</em> <em>IDENTIFIER</em></p>
</dd>
<dt class="hdlist1"><em>function_prototype</em> : </dt>
<dd>
<p><em>function_declarator</em> <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>function_declarator</em> : </dt>
<dd>
<p><em>function_header</em><br>
<em>function_header_with_parameters</em></p>
</dd>
<dt class="hdlist1"><em>function_header_with_parameters</em> : </dt>
<dd>
<p><em>function_header</em> <em>parameter_declaration</em><br>
<em>function_header_with_parameters</em> <em>COMMA</em> <em>parameter_declaration</em></p>
</dd>
<dt class="hdlist1"><em>function_header</em> : </dt>
<dd>
<p><em>fully_specified_type</em> <em>IDENTIFIER</em> <em>LEFT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>parameter_declarator</em> : </dt>
<dd>
<p><em>type_specifier</em> <em>IDENTIFIER</em><br>
<em>type_specifier</em> <em>IDENTIFIER</em> <em>array_specifier</em></p>
</dd>
<dt class="hdlist1"><em>parameter_declaration</em> : </dt>
<dd>
<p><em>type_qualifier</em> <em>parameter_declarator</em><br>
<em>parameter_declarator</em><br>
<em>type_qualifier</em> <em>parameter_type_specifier</em><br>
<em>parameter_type_specifier</em></p>
</dd>
<dt class="hdlist1"><em>parameter_type_specifier</em> : </dt>
<dd>
<p><em>type_specifier</em></p>
</dd>
<dt class="hdlist1"><em>init_declarator_list</em> : </dt>
<dd>
<p><em>single_declaration</em><br>
<em>init_declarator_list</em> <em>COMMA</em> <em>IDENTIFIER</em><br>
<em>init_declarator_list</em> <em>COMMA</em> <em>IDENTIFIER</em> <em>array_specifier</em><br>
<em>init_declarator_list</em> <em>COMMA</em> <em>IDENTIFIER</em> <em>array_specifier</em> <em>EQUAL</em>
<em>initializer</em><br>
<em>init_declarator_list</em> <em>COMMA</em> <em>IDENTIFIER</em> <em>EQUAL</em> <em>initializer</em></p>
</dd>
<dt class="hdlist1"><em>single_declaration</em> : </dt>
<dd>
<p><em>fully_specified_type</em><br>
<em>fully_specified_type</em> <em>IDENTIFIER</em><br>
<em>fully_specified_type</em> <em>IDENTIFIER</em> <em>array_specifier</em><br>
<em>fully_specified_type</em> <em>IDENTIFIER</em> <em>array_specifier</em> <em>EQUAL</em>
<em>initializer</em><br>
<em>fully_specified_type</em> <em>IDENTIFIER</em> <em>EQUAL</em> <em>initializer</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: No 'enum', or 'typedef'.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>fully_specified_type</em> : </dt>
<dd>
<p><em>type_specifier</em><br>
<em>type_qualifier</em> <em>type_specifier</em></p>
</dd>
<dt class="hdlist1"><em>invariant_qualifier</em> : </dt>
<dd>
<p><em>INVARIANT</em></p>
</dd>
<dt class="hdlist1"><em>interpolation_qualifier</em> : </dt>
<dd>
<p><em>SMOOTH</em><br>
<em>FLAT</em><br>
<em>NOPERSPECTIVE</em></p>
</dd>
<dt class="hdlist1"><em>layout_qualifier</em> : </dt>
<dd>
<p><em>LAYOUT</em> <em>LEFT_PAREN</em> <em>layout_qualifier_id_list</em> <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>layout_qualifier_id_list</em> : </dt>
<dd>
<p><em>layout_qualifier_id</em><br>
<em>layout_qualifier_id_list</em> <em>COMMA</em> <em>layout_qualifier_id</em></p>
</dd>
<dt class="hdlist1"><em>layout_qualifier_id</em> : </dt>
<dd>
<p><em>IDENTIFIER</em><br>
<em>IDENTIFIER</em> <em>EQUAL</em> <em>constant_expression</em><br>
<em>SHARED</em></p>
</dd>
<dt class="hdlist1"><em>precise_qualifier</em> : </dt>
<dd>
<p><em>PRECISE</em></p>
</dd>
<dt class="hdlist1"><em>type_qualifier</em> : </dt>
<dd>
<p><em>single_type_qualifier</em><br>
<em>type_qualifier</em> <em>single_type_qualifier</em></p>
</dd>
<dt class="hdlist1"><em>single_type_qualifier</em> : </dt>
<dd>
<p><em>storage_qualifier</em><br>
<em>layout_qualifier</em><br>
<em>precision_qualifier</em><br>
<em>interpolation_qualifier</em><br>
<em>invariant_qualifier</em><br>
<em>precise_qualifier</em></p>
</dd>
<dt class="hdlist1"><em>storage_qualifier</em> : </dt>
<dd>
<p><em>CONST</em><br>
<em>IN</em><br>
<em>OUT</em><br>
<em>INOUT</em><br>
<em>CENTROID</em><br>
<em>PATCH</em><br>
<em>SAMPLE</em><br>
<em>UNIFORM</em><br>
<em>BUFFER</em><br>
<em>SHARED</em><br>
<em>COHERENT</em><br>
<em>VOLATILE</em><br>
<em>RESTRICT</em><br>
<em>READONLY</em><br>
<em>WRITEONLY</em><br>
<em>SUBROUTINE</em><br>
<em>SUBROUTINE</em> <em>LEFT_PAREN</em> <em>type_name_list</em> <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>type_name_list</em> : </dt>
<dd>
<p><em>TYPE_NAME</em><br>
<em>type_name_list</em> <em>COMMA</em> <em>TYPE_NAME</em></p>
</dd>
<dt class="hdlist1"><em>type_specifier</em> : </dt>
<dd>
<p><em>type_specifier_nonarray</em><br>
<em>type_specifier_nonarray</em> <em>array_specifier</em></p>
</dd>
<dt class="hdlist1"><em>array_specifier</em> : </dt>
<dd>
<p><em>LEFT_BRACKET</em> <em>RIGHT_BRACKET</em><br>
<em>LEFT_BRACKET</em> <em>conditional_expression</em> <em>RIGHT_BRACKET</em><br>
<em>array_specifier</em> <em>LEFT_BRACKET</em> <em>RIGHT_BRACKET</em><br>
<em>array_specifier</em> <em>LEFT_BRACKET</em> <em>conditional_expression</em> <em>RIGHT_BRACKET</em></p>
</dd>
<dt class="hdlist1"><em>type_specifier_nonarray</em> : </dt>
<dd>
<p><em>VOID</em><br>
<em>FLOAT</em><br>
<em>DOUBLE</em><br>
<em>INT</em><br>
<em>UINT</em><br>
<em>BOOL</em><br>
<em>VEC2</em><br>
<em>VEC3</em><br>
<em>VEC4</em><br>
<em>DVEC2</em><br>
<em>DVEC3</em><br>
<em>DVEC4</em><br>
<em>BVEC2</em><br>
<em>BVEC3</em><br>
<em>BVEC4</em><br>
<em>IVEC2</em><br>
<em>IVEC3</em><br>
<em>IVEC4</em><br>
<em>UVEC2</em><br>
<em>UVEC3</em><br>
<em>UVEC4</em><br>
<em>MAT2</em><br>
<em>MAT3</em><br>
<em>MAT4</em><br>
<em>MAT2X2</em><br>
<em>MAT2X3</em><br>
<em>MAT2X4</em><br>
<em>MAT3X2</em><br>
<em>MAT3X3</em><br>
<em>MAT3X4</em><br>
<em>MAT4X2</em><br>
<em>MAT4X3</em><br>
<em>MAT4X4</em><br>
<em>DMAT2</em><br>
<em>DMAT3</em><br>
<em>DMAT4</em><br>
<em>DMAT2X2</em><br>
<em>DMAT2X3</em><br>
<em>DMAT2X4</em><br>
<em>DMAT3X2</em><br>
<em>DMAT3X3</em><br>
<em>DMAT3X4</em><br>
<em>DMAT4X2</em><br>
<em>DMAT4X3</em><br>
<em>DMAT4X4</em><br>
<em>ATOMIC_UINT</em><br>
<em>SAMPLER2D</em><br>
<em>SAMPLER3D</em><br>
<em>SAMPLERCUBE</em><br>
<em>SAMPLER2DSHADOW</em><br>
<em>SAMPLERCUBESHADOW</em><br>
<em>SAMPLER2DARRAY</em><br>
<em>SAMPLER2DARRAYSHADOW</em><br>
<em>SAMPLERCUBEARRAY</em><br>
<em>SAMPLERCUBEARRAYSHADOW</em><br>
<em>ISAMPLER2D</em><br>
<em>ISAMPLER3D</em><br>
<em>ISAMPLERCUBE</em><br>
<em>ISAMPLER2DARRAY</em><br>
<em>ISAMPLERCUBEARRAY</em><br>
<em>USAMPLER2D</em><br>
<em>USAMPLER3D</em><br>
<em>USAMPLERCUBE</em><br>
<em>USAMPLER2DARRAY</em><br>
<em>USAMPLERCUBEARRAY</em><br>
<em>SAMPLER1D</em><br>
<em>SAMPLER1DSHADOW</em><br>
<em>SAMPLER1DARRAY</em><br>
<em>SAMPLER1DARRAYSHADOW</em><br>
<em>ISAMPLER1D</em><br>
<em>ISAMPLER1DARRAY</em><br>
<em>USAMPLER1D</em><br>
<em>USAMPLER1DARRAY</em><br>
<em>SAMPLER2DRECT</em><br>
<em>SAMPLER2DRECTSHADOW</em><br>
<em>ISAMPLER2DRECT</em><br>
<em>USAMPLER2DRECT</em><br>
<em>SAMPLERBUFFER</em><br>
<em>ISAMPLERBUFFER</em><br>
<em>USAMPLERBUFFER</em><br>
<em>SAMPLER2DMS</em><br>
<em>ISAMPLER2DMS</em><br>
<em>USAMPLER2DMS</em><br>
<em>SAMPLER2DMSARRAY</em><br>
<em>ISAMPLER2DMSARRAY</em><br>
<em>USAMPLER2DMSARRAY</em><br>
<em>IMAGE2D</em><br>
<em>IIMAGE2D</em><br>
<em>UIMAGE2D</em><br>
<em>IMAGE3D</em><br>
<em>IIMAGE3D</em><br>
<em>UIMAGE3D</em><br>
<em>IMAGECUBE</em><br>
<em>IIMAGECUBE</em><br>
<em>UIMAGECUBE</em><br>
<em>IMAGEBUFFER</em><br>
<em>IIMAGEBUFFER</em><br>
<em>UIMAGEBUFFER</em><br>
<em>IMAGE1D</em><br>
<em>IIMAGE1D</em><br>
<em>UIMAGE1D</em><br>
<em>IMAGE1DARRAY</em><br>
<em>IIMAGE1DARRAY</em><br>
<em>UIMAGE1DARRAY</em><br>
<em>IMAGE2DRECT</em><br>
<em>IIMAGE2DRECT</em><br>
<em>UIMAGE2DRECT</em><br>
<em>IMAGE2DARRAY</em><br>
<em>IIMAGE2DARRAY</em><br>
<em>UIMAGE2DARRAY</em><br>
<em>IMAGECUBEARRAY</em><br>
<em>IIMAGECUBEARRAY</em><br>
<em>UIMAGECUBEARRAY</em><br>
<em>IMAGE2DMS</em><br>
<em>IIMAGE2DMS</em><br>
<em>UIMAGE2DMS</em><br>
<em>IMAGE2DMSARRAY</em><br>
<em>IIMAGE2DMSARRAY</em><br>
<em>UIMAGE2DMSARRAY</em><br>
<em>struct_specifier</em><br>
<em>TYPE_NAME</em></p>
</dd>
<dt class="hdlist1"><em>precision_qualifier</em> : </dt>
<dd>
<p><em>HIGH_PRECISION</em><br>
<em>MEDIUM_PRECISION</em><br>
<em>LOW_PRECISION</em></p>
</dd>
<dt class="hdlist1"><em>struct_specifier</em> : </dt>
<dd>
<p><em>STRUCT</em> <em>IDENTIFIER</em> <em>LEFT_BRACE</em> <em>struct_declaration_list</em>
<em>RIGHT_BRACE</em><br>
<em>STRUCT</em> <em>LEFT_BRACE</em> <em>struct_declaration_list</em> <em>RIGHT_BRACE</em></p>
</dd>
<dt class="hdlist1"><em>struct_declaration_list</em> : </dt>
<dd>
<p><em>struct_declaration</em><br>
<em>struct_declaration_list</em> <em>struct_declaration</em></p>
</dd>
<dt class="hdlist1"><em>struct_declaration</em> : </dt>
<dd>
<p><em>type_specifier</em> <em>struct_declarator_list</em> <em>SEMICOLON</em><br>
<em>type_qualifier</em> <em>type_specifier</em> <em>struct_declarator_list</em> <em>SEMICOLON</em></p>
</dd>
<dt class="hdlist1"><em>struct_declarator_list</em> : </dt>
<dd>
<p><em>struct_declarator</em><br>
<em>struct_declarator_list</em> <em>COMMA</em> <em>struct_declarator</em></p>
</dd>
<dt class="hdlist1"><em>struct_declarator</em> : </dt>
<dd>
<p><em>IDENTIFIER</em><br>
<em>IDENTIFIER</em> <em>array_specifier</em></p>
</dd>
<dt class="hdlist1"><em>initializer</em> : </dt>
<dd>
<p><em>assignment_expression</em><br>
<em>LEFT_BRACE</em> <em>initializer_list</em> <em>RIGHT_BRACE</em><br>
<em>LEFT_BRACE</em> <em>initializer_list</em> <em>COMMA</em> <em>RIGHT_BRACE</em></p>
</dd>
<dt class="hdlist1"><em>initializer_list</em> : </dt>
<dd>
<p><em>initializer</em><br>
<em>initializer_list</em> <em>COMMA</em> <em>initializer</em></p>
</dd>
<dt class="hdlist1"><em>declaration_statement</em> : </dt>
<dd>
<p><em>declaration</em></p>
</dd>
<dt class="hdlist1"><em>statement</em> : </dt>
<dd>
<p><em>compound_statement</em><br>
<em>simple_statement</em></p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: labeled statements for SWITCH only; 'goto' is not supported.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>simple_statement</em> : </dt>
<dd>
<p><em>declaration_statement</em><br>
<em>expression_statement</em><br>
<em>selection_statement</em><br>
<em>switch_statement</em><br>
<em>case_label</em><br>
<em>iteration_statement</em><br>
<em>jump_statement</em></p>
</dd>
<dt class="hdlist1"><em>compound_statement</em> : </dt>
<dd>
<p><em>LEFT_BRACE</em> <em>RIGHT_BRACE</em><br>
<em>LEFT_BRACE</em> <em>statement_list</em> <em>RIGHT_BRACE</em></p>
</dd>
<dt class="hdlist1"><em>statement_no_new_scope</em> : </dt>
<dd>
<p><em>compound_statement_no_new_scope</em><br>
<em>simple_statement</em></p>
</dd>
<dt class="hdlist1"><em>compound_statement_no_new_scope</em> : </dt>
<dd>
<p><em>LEFT_BRACE</em> <em>RIGHT_BRACE</em><br>
<em>LEFT_BRACE</em> <em>statement_list</em> <em>RIGHT_BRACE</em></p>
</dd>
<dt class="hdlist1"><em>statement_list</em> : </dt>
<dd>
<p><em>statement</em><br>
<em>statement_list</em> <em>statement</em></p>
</dd>
<dt class="hdlist1"><em>expression_statement</em> : </dt>
<dd>
<p><em>SEMICOLON</em><br>
<em>expression</em> <em>SEMICOLON</em></p>
</dd>
<dt class="hdlist1"><em>selection_statement</em> : </dt>
<dd>
<p><em>IF</em> <em>LEFT_PAREN</em> <em>expression</em> <em>RIGHT_PAREN</em> <em>selection_rest_statement</em></p>
</dd>
<dt class="hdlist1"><em>selection_rest_statement</em> : </dt>
<dd>
<p><em>statement</em> <em>ELSE</em> <em>statement</em><br>
<em>statement</em></p>
</dd>
<dt class="hdlist1"><em>condition</em> : </dt>
<dd>
<p><em>expression</em><br>
<em>fully_specified_type</em> <em>IDENTIFIER</em> <em>EQUAL</em> <em>initializer</em></p>
</dd>
<dt class="hdlist1"><em>switch_statement</em> : </dt>
<dd>
<p><em>SWITCH</em> <em>LEFT_PAREN</em> <em>expression</em> <em>RIGHT_PAREN</em> <em>LEFT_BRACE</em>
<em>switch_statement_list</em><br>
<em>RIGHT_BRACE</em></p>
</dd>
<dt class="hdlist1"><em>switch_statement_list</em> : </dt>
<dd>
<p>/* <em>nothing</em> */<br>
<em>statement_list</em></p>
</dd>
<dt class="hdlist1"><em>case_label</em> : </dt>
<dd>
<p><em>CASE</em> <em>expression</em> <em>COLON</em><br>
<em>DEFAULT</em> <em>COLON</em></p>
</dd>
<dt class="hdlist1"><em>iteration_statement</em> : </dt>
<dd>
<p><em>WHILE</em> <em>LEFT_PAREN</em> <em>condition</em> <em>RIGHT_PAREN</em> <em>statement_no_new_scope</em><br>
<em>DO</em> <em>statement</em> <em>WHILE</em> <em>LEFT_PAREN</em> <em>expression</em> <em>RIGHT_PAREN</em>
<em>SEMICOLON</em><br>
<em>FOR</em> <em>LEFT_PAREN</em> <em>for_init_statement</em> <em>for_rest_statement</em>
<em>RIGHT_PAREN</em> <em>statement_no_new_scope</em></p>
</dd>
<dt class="hdlist1"><em>for_init_statement</em> : </dt>
<dd>
<p><em>expression_statement</em><br>
<em>declaration_statement</em></p>
</dd>
<dt class="hdlist1"><em>conditionopt</em> : </dt>
<dd>
<p><em>condition</em><br>
/* <em>empty</em> */</p>
</dd>
<dt class="hdlist1"><em>for_rest_statement</em> : </dt>
<dd>
<p><em>conditionopt</em> <em>SEMICOLON</em><br>
<em>conditionopt</em> <em>SEMICOLON</em> <em>expression</em></p>
</dd>
<dt class="hdlist1"><em>jump_statement</em> : </dt>
<dd>
<p><em>CONTINUE</em> <em>SEMICOLON</em><br>
<em>BREAK</em> <em>SEMICOLON</em><br>
<em>RETURN</em> <em>SEMICOLON</em><br>
<em>RETURN</em> <em>expression</em> <em>SEMICOLON</em><br>
<em>DISCARD</em> <em>SEMICOLON</em> // Fragment shader only.</p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Grammar Note: No 'goto'.
Gotos are not supported.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><em>translation_unit</em> : </dt>
<dd>
<p><em>external_declaration</em><br>
<em>translation_unit</em> <em>external_declaration</em></p>
</dd>
<dt class="hdlist1"><em>external_declaration</em> : </dt>
<dd>
<p><em>function_definition</em><br>
<em>declaration</em><br>
<em>SEMICOLON</em></p>
</dd>
<dt class="hdlist1"><em>function_definition</em> : </dt>
<dd>
<p><em>function_prototype</em> <em>compound_statement_no_new_scope</em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>In general the above grammar describes a super set of the OpenGL Shading Language.
Certain constructs that are valid purely in terms of the grammar are
disallowed by statements elsewhere in this specification.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="acknowledgments">10. Acknowledgments</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This specification is based on the work of those who contributed to past
versions of the Open GL and Open GL ES Language Specifications and the
following contributors to this version:</p>
</div>
<div class="paragraph">
<p>Pat Brown, NVIDIA<br>
Jeff Bolz, NVIDIA<br>
Frank Chen<br>
Pierre Boudier, AMD<br>
Piers Daniell, NVIDIA<br>
Chris Dodd, NVIDIA<br>
Nick Haemel, NVIDIA<br>
Jason Green, Transgaming<br>
Brent Insko, Intel<br>
Jon Leech<br>
Bill Licea-Kane, Qualcomm<br>
Daniel Koch, NVIDIA<br>
Graeme Leese, Broadcom<br>
Barthold Lichtenbelt, NVIDIA<br>
Bruce Merry, ARM<br>
Robert Ohannessian<br>
Tom Olson, ARM<br>
Brian Paul, VMware<br>
Acorn Pooley, NVIDIA<br>
Daniel Rakos, AMD<br>
Christophe Riccio, AMD<br>
Kevin Rogovin<br>
Ian Romanick, Intel<br>
Greg Roth, NVIDIA<br>
Graham Sellers, AMD<br>
Dave Shreiner, ARM<br>
Jeremy Sandmel, Apple<br>
Robert Simpson, Qualcomm<br>
Eric Werness, NVIDIA<br>
Mark Young, AMD</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="references">11. Normative References</h2>
<div class="sectionbody">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>International Standard ISO/IEC 14882:1998(E).
Programming Languages - C++. Referenced for preprocessor only</p>
</li>
<li>
<p>&#8220;OpenGL<sup>R</sup> ES, Version 3.2&#8221;,
<a href="https://www.khronos.org/registry/OpenGL/index_es.php" class="bare">https://www.khronos.org/registry/OpenGL/index_es.php</a>, November 3, 2016.</p>
</li>
<li>
<p>&#8220;The OpenGL<sup>R</sup> Graphics System: A Specification, Version 4.6 (Core
Profile)&#8221;, <a href="https://www.khronos.org/registry/OpenGL/index_gl.php" class="bare">https://www.khronos.org/registry/OpenGL/index_gl.php</a>, June
1, 2016.</p>
</li>
<li>
<p>IEEE 754-2008.
<em>IEEE Standard for Floating-Point Arithmetic</em></p>
</li>
<li>
<p>&#8220;SPIR-V Specification, Version 1.3, Revision 7&#8221; ,
<a href="https://www.khronos.org/registry/spir-v/" class="bare">https://www.khronos.org/registry/spir-v/</a>.</p>
</li>
<li>
<p>&#8220;Vulkan<sup>R</sup> 1.1.105 - A Specification&#8221;,
<a href="https://www.khronos.org/registry/vulkan/" class="bare">https://www.khronos.org/registry/vulkan/</a>,
March 19, 2019.</p>
</li>
</ol>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_non_normative_spir_v_mappings">12. Non-Normative SPIR-V Mappings</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This appendix includes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>a comparision of feature differences with SPIR-V versus without, for both Vulkan and OpenGL</p>
</li>
<li>
<p>a discussion of how GLSL features logically map to SPIR-V features.</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_feature_comparisons">12.1. Feature Comparisons</h3>
<div class="paragraph">
<p>The following features are removed for both OpenGL and Vulkan:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>subroutines</p>
</li>
<li>
<p>shared and packed block layouts</p>
</li>
<li>
<p>the already deprecated texturing functions (e.g., <code>texture2D()</code>)</p>
</li>
<li>
<p>the already deprecated noise functions (e.g., <code>noise1()</code>)</p>
</li>
<li>
<p>compatibility-profile features</p>
</li>
<li>
<p><em>gl_DepthRangeParameters</em> and <em>gl_NumSamples</em></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Vulkan removed the following features, which are still present for OpenGL:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Default uniforms, for non-opaque types:
The <strong>UniformConstant</strong> storage class can be used on individual
variables at global scope. (That is, uniforms don&#8217;t have to be in a
block, unless they are built-in members that are in block in GLSL
version 4.5 or above.)</p>
</li>
<li>
<p>GLSL atomic-counter bindings have the <em>offset</em> layout qualifier &#8594;
SPIR-V <strong>AtomicCounter</strong> storage class using the <strong>Offset</strong> decoration</p>
</li>
<li>
<p>GLSL <em>origin_lower_left</em> &#8594; SPIR-V <strong>OriginLowerLeft</strong></p>
</li>
<li>
<p>special rules for locations for input doubles in the vertex shader</p>
</li>
<li>
<p><em>gl_VertexID</em> and <em>gl_InstanceID</em> (more detail follows)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The following features are added for both OpenGL and Vulkan:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>specialization constants</p>
</li>
<li>
<p><em>offset</em> can organize members in a different order than declaration order</p>
</li>
<li>
<p><em>offset</em> and <em>align</em> layout qualifiers for uniform/buffer blocks for
versions that did not support them</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Vulkan Only: The following features are added:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>push-constant buffers</p>
</li>
<li>
<p>shader combining of separate textures and samplers (SPIR-V <strong>OpTypeSampler</strong>)</p>
</li>
<li>
<p>descriptor sets (<strong>DescriptorSet</strong> must be 0, if present)</p>
</li>
<li>
<p><em>gl_VertexIndex</em> and <em>gl_InstanceIndex</em></p>
</li>
<li>
<p>subpass-input targets and input attachments (<em>input_attachment_index</em>)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The following features are changed in both OpenGL and Vulkan:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><em>gl_FragColor</em> will no longer indicate an implicit broadcast</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Vulkan Only: The following features are changed:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>precision qualifiers (<strong>mediump</strong> and <strong>lowp</strong>) will be respected for all
versions, not dropped for desktop versions (default precision for
desktop versions is <strong>highp</strong> for all types)</p>
</li>
<li>
<p>arrays of uniforms and buffer blocks take only one binding number for
the entire object, not one per array element</p>
</li>
<li>
<p>the default origin is <em>origin_upper_left</em> instead of <em>origin_lower_left</em></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Vulkan does not allow multi-dimensional arrays of resources like
UBOs and SSBOs in its SPIR-V environment spec. SPIR-V supports
it and OpenGL already allows this for GLSL shaders. SPIR-V
for OpenGL also allows it.</p>
</div>
</div>
<div class="sect2">
<h3 id="_mapping_from_glsl_to_spir_v">12.2. Mapping from GLSL to SPIR-V</h3>
<div class="sect3">
<h4 id="_specialization_constants">12.2.1. Specialization Constants</h4>
<div class="paragraph">
<p>SPIR-V specialization constants, which can be set later by the client API,
can be declared using <code>layout(constant_id=&#8230;&#8203;)</code>. For example, to make a
specialization constant with a default value of 12:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(constant_id = 17) const int arraySize = 12;</pre>
</div>
</div>
<div class="paragraph">
<p>Above, <code>17</code> is the ID by which the API or other tools can later refer to
this specific specialization constant. The API or an intermediate tool can
then change its value to another constant integer before it is fully
lowered to executable code. If it is never changed before final lowering,
it will retain the value of 12.</p>
</div>
<div class="paragraph">
<p>Specialization constants have const semantics, except they don&#8217;t fold.
Hence, an array can be declared with <code>arraySize</code> from above:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>vec4 data[arraySize]; // legal, even though arraySize might change</pre>
</div>
</div>
<div class="paragraph">
<p>Specialization constants can be in expressions:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>vec4 data2[arraySize + 2];</pre>
</div>
</div>
<div class="paragraph">
<p>This will make <code>data2</code> be sized by 2 more than whatever constant value
<code>arraySize</code> has when it is time to lower the shader to executable code.</p>
</div>
<div class="paragraph">
<p>An expression formed with specialization constants also behaves in the
shader like a specialization constant, not a like a constant.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>arraySize + 2 // a specialization constant (with no constant_id)</pre>
</div>
</div>
<div class="paragraph">
<p>Such expressions can be used in the same places as a constant.</p>
</div>
<div class="paragraph">
<p>The <em>constant_id</em> can only be applied to a scalar integer, a scalar floating-point
or a scalar Boolean.</p>
</div>
<div class="paragraph">
<p>Only basic operators and constructors can be applied to a specialization
constant and still result in a specialization constant:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(constant_id = 17) const int arraySize = 12;
sin(float(arraySize)); // result is not a specialization constant</pre>
</div>
</div>
<div class="paragraph">
<p>While SPIR-V specialization constants are only for scalars, a vector
can be made by operations on scalars:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(constant_id = 18) const int scX = 1;
layout(constant_id = 19) const int scZ = 1;
const vec3 scVec = vec3(scX, 1, scZ); // partially specialized vector</pre>
</div>
</div>
<div class="paragraph">
<p>A built-in variable can have a <em>constant_id</em> attached to it:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(constant_id = 18) gl_MaxImageUnits;</pre>
</div>
</div>
<div class="paragraph">
<p>This makes it behave as a specialization constant. It is not a full
redeclaration; all other characteristics are left intact from the
original built-in declaration.</p>
</div>
<div class="paragraph">
<p>The built-in vector <em>gl_WorkGroupSize</em> can be specialized using special
layout <code>local_size_{xyz}_id</code> applied to the <strong>in</strong> qualifier. For example:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(local_size_x_id = 18, local_size_z_id = 19) in;</pre>
</div>
</div>
<div class="paragraph">
<p>This leaves <em>gl_WorkGroupSize.y</em> as a non-specialization constant, with
<em>gl_WorkGroupSize</em> being a partially specialized vector. Its <em>x</em> and <em>z</em>
components can be later specialized using the ID&#8217;s 18 and 19.</p>
</div>
</div>
<div class="sect3">
<h4 id="_vulkan_only_push_constants">12.2.2. Vulkan Only: Push Constants</h4>
<div class="paragraph">
<p>Push constants reside in a uniform block declared using the new
layout-qualifier-id <em>push_constant</em> applied to a uniform-block declaration.
The API writes a set of constants to a push-constant buffer, and the shader
reads them from a <em>push_constant</em> block:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(push_constant) uniform BlockName {
int member1;
float member2;
...
} InstanceName; // optional instance name
... = InstanceName.member2; // read a push constant</pre>
</div>
</div>
<div class="paragraph">
<p>The memory accounting used for the <em>push_constant</em> uniform block is different
than for other uniform blocks: There is a separate small pool of memory
it must fit within. By default, a <em>push_constant</em> buffer follows the std430
packing rules.</p>
</div>
</div>
<div class="sect3">
<h4 id="_vulkan_only_descriptor_sets">12.2.3. Vulkan Only: Descriptor Sets</h4>
<div class="paragraph">
<p>Each shader resource in a descriptor set is assigned a tuple of (set
number, binding number, array element) that defines its location within
a descriptor set layout.
In GLSL, the set number and binding number are assigned via the <em>set</em>
and <em>binding</em> layout qualifiers respectively, and the array element is
implicitly assigned consecutively starting with index equal to zero for
the first element of an array (and array element is zero for non-array
variables):</p>
</div>
<div class="literalblock">
<div class="content">
<pre>// Assign set number = M, binding number = N, array element = 0
layout (set=M, binding=N) uniform sampler2D variableName;</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>// Assign set number = M, binding number = N for all array elements,
// and array element = i for the ith member of an array of size I.
layout (set=M, binding=N) uniform sampler2D variableNameArray[I];</pre>
</div>
</div>
<div class="paragraph">
<p>For example, two combined texture/sampler objects can be declared in two
different descriptor sets as follows</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout(set = 0, binding = 0) uniform sampler2D ts3;
layout(set = 1, binding = 0) uniform sampler2D ts4;</pre>
</div>
</div>
<div class="paragraph">
<p>See the API documentation for more detail on the operation model of
descriptor sets.</p>
</div>
</div>
<div class="sect3">
<h4 id="_vulkan_only_samplers_images_textures_and_buffers">12.2.4. Vulkan Only: Samplers, Images, Textures, and Buffers</h4>
<div class="sect4">
<h5 id="_storage_images">Storage Images</h5>
<div class="paragraph">
<p>Storage images are declared in GLSL shader source using uniform image
variables of the appropriate dimensionality as well as a format layout
qualifier (if necessary):</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n, r32f) uniform image2D myStorageImage;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "myStorageImage"
OpDecorate %9 DescriptorSet m
OpDecorate %9 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 2D 0 0 0 2 R32f
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_samplers">Samplers</h5>
<div class="paragraph">
<p>SPIR-V samplers are declared in GLSL shader source using uniform <strong>sampler</strong> and
<strong>samplerShadow</strong> types:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) uniform sampler mySampler;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %8 "mySampler"
OpDecorate %8 DescriptorSet m
OpDecorate %8 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeSampler
%7 = OpTypePointer UniformConstant %6
%8 = OpVariable %7 UniformConstant
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_textures_sampled_images">Textures (Sampled Images)</h5>
<div class="paragraph">
<p>Textures are declared in GLSL shader source using uniform texture
variables of the appropriate dimensionality:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) uniform texture2D mySampledImage;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "mySampledImage"
OpDecorate %9 DescriptorSet m
OpDecorate %9 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_combined_texture_and_samplers">Combined Texture and Samplers</h5>
<div class="paragraph">
<p>Combined textures and samplers are declared in GLSL shader source using
uniform texture-combined sampler variables of the appropriate dimensionality:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) uniform sampler2D myCombinedImageSampler;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %10 "myCombinedImageSampler"
OpDecorate %10 DescriptorSet m
OpDecorate %10 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
%8 = OpTypeSampledImage %7
%9 = OpTypePointer UniformConstant %8
%10 = OpVariable %9 UniformConstant
...</pre>
</div>
</div>
<div class="paragraph">
<p>Note that a combined image sampler descriptor can be referred to as just
an image or sampler in the shader as per the above sections.</p>
</div>
</div>
<div class="sect4">
<h5 id="_combining_separate_samplers_and_textures">Combining Separate Samplers and Textures</h5>
<div class="paragraph">
<p>A sampler, declared with the keyword <strong>sampler</strong>, contains just filtering
information, containing neither a texture nor an image:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>uniform sampler s; // a handle to filtering information</pre>
</div>
</div>
<div class="paragraph">
<p>A texture, declared with keywords like <strong>texture2D</strong>, contains just image
information, not filtering information:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>uniform texture2D t; // a handle to a texture (an image in SPIR-V)</pre>
</div>
</div>
<div class="paragraph">
<p>Constructors can then be used to combine a sampler and a texture at the
point of making a texture lookup call:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>texture(sampler2D(t, s), ...);</pre>
</div>
</div>
<div class="paragraph">
<p>Note, <code>layout()</code> information is omitted above for clarity of this feature.</p>
</div>
</div>
<div class="sect4">
<h5 id="_texture_buffers_uniform_texel_buffers">Texture Buffers (Uniform Texel Buffers)</h5>
<div class="paragraph">
<p>Texture buffers are declared in GLSL shader source using uniform
textureBuffer variables:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) uniform textureBuffer myUniformTexelBuffer;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "myUniformTexelBuffer"
OpDecorate %9 DescriptorSet m
OpDecorate %9 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 Buffer 0 0 0 1 Unknown
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_image_buffers_storage_texel_buffers">Image Buffers (Storage Texel Buffers)</h5>
<div class="paragraph">
<p>Image buffers are declared in GLSL shader source using uniform
imageBuffer variables:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n, r32f) uniform imageBuffer myStorageTexelBuffer;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "myStorageTexelBuffer"
OpDecorate %9 DescriptorSet m
OpDecorate %9 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_storage_buffers">Storage Buffers</h5>
<div class="paragraph">
<p>Storage buffers are declared in GLSL shader source using buffer storage
qualifier and block syntax:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) buffer myStorageBuffer
{
vec4 myElement[];
};</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "myStorageBuffer"
OpMemberName %9 0 "myElement"
OpName %11 ""
OpDecorate %8 ArrayStride 16
OpMemberDecorate %9 0 Offset 0
OpDecorate %9 BufferBlock
OpDecorate %11 DescriptorSet m
OpDecorate %11 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeVector %6 4
%8 = OpTypeRuntimeArray %7
%9 = OpTypeStruct %8
%10 = OpTypePointer Uniform %9
%11 = OpVariable %10 Uniform
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_uniform_buffers">Uniform Buffers</h5>
<div class="paragraph">
<p>Uniform buffers are declared in GLSL shader source using the uniform storage
qualifier and block syntax:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (set=m, binding=n) uniform myUniformBuffer
{
vec4 myElement[32];
};</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %11 "myUniformBuffer"
OpMemberName %11 0 "myElement"
OpName %13 ""
OpDecorate %10 ArrayStride 16
OpMemberDecorate %11 0 Offset 0
OpDecorate %11 Block
OpDecorate %13 DescriptorSet m
OpDecorate %13 Binding n
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeVector %6 4
%8 = OpTypeInt 32 0
%9 = OpConstant %8 32
%10 = OpTypeArray %7 %9
%11 = OpTypeStruct %10
%12 = OpTypePointer Uniform %11
%13 = OpVariable %12 Uniform
...</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_subpass_inputs_2">Subpass Inputs</h5>
<div class="paragraph">
<p>Within a rendering pass, a subpass can write results to an output target
that can then be read by the next subpass as an input subpass. The
"Subpass Input" feature regards the ability to read an output target.</p>
</div>
<div class="paragraph">
<p>Subpass inputs are read through a new set of types, available only
to fragment shaders:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>subpassInput
subpassInputMS
isubpassInput
isubpassInputMS
usubpassInput
usubpassInputMS</pre>
</div>
</div>
<div class="paragraph">
<p>Unlike sampler and image objects, subpass inputs are implicitly addressed
by the fragment&#8217;s (<em>x</em>, <em>y</em>, <em>layer</em>) coordinate.</p>
</div>
<div class="paragraph">
<p>Input attachments are decorated with their input attachment index in
addition to descriptor set and binding numbers.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>layout (input_attachment_index=i, set=m, binding=n) uniform subpassInput myInputAttachment;</pre>
</div>
</div>
<div class="paragraph">
<p>Which maps to the following SPIR-V:</p>
</div>
<div class="literalblock">
<div class="content">
<pre> ...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "myInputAttachment"
OpDecorate %9 DescriptorSet m
OpDecorate %9 Binding n
OpDecorate %9 InputAttachmentIndex i
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
...</pre>
</div>
</div>
<div class="paragraph">
<p>An <em>input_attachment_index</em> of i selects the ith entry in the input pass
list. (See API specification for more information.)</p>
</div>
<div class="paragraph">
<p>These objects support reading the subpass input through the following
functions:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>gvec4 subpassLoad(gsubpassInput subpass);
gvec4 subpassLoad(gsubpassInputMS subpass, int sample);</pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_variables">12.2.5. Mapping Variables</h4>
<div class="sect4">
<h5 id="_gl_fragcolor"><em>gl_FragColor</em></h5>
<div class="paragraph">
<p>The fragment-stage built-in <em>gl_FragColor</em>, which implies a broadcast to all
outputs, is not present in SPIR-V. Shaders where writing to <em>gl_FragColor</em>
is allowed can still write to it, but it only means to write to an output:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>of the same type as <em>gl_FragColor</em></p>
</li>
<li>
<p>decorated with location 0</p>
</li>
<li>
<p>not decorated as a built-in variable.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>There is no implicit broadcast.</p>
</div>
</div>
<div class="sect4">
<h5 id="_vulkan_gl_vertexindex_and_gl_instanceindex">Vulkan <em>gl_VertexIndex</em> and <em>gl_InstanceIndex</em></h5>
<div class="paragraph">
<p>Adds two new built-in variables, <em>gl_VertexIndex</em> and <em>gl_InstanceIndex</em> to
replace the existing built-in variables <em>gl_VertexID</em> and <em>gl_InstanceID</em>.</p>
</div>
<div class="paragraph">
<p>In the situations where the indexing is relative to some base offset,
these built-in variables are defined, for Vulkan, to take on values as
follows:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>gl_VertexIndex base, base+1, base+2, ...
gl_InstanceIndex base, base+1, base+2, ...</pre>
</div>
</div>
<div class="paragraph">
<p>Where it depends on the situation what the base actually is.</p>
</div>
</div>
<div class="sect4">
<h5 id="_storage_classes">Storage Classes:</h5>
<div class="literalblock">
<div class="content">
<pre>uniform sampler2D...; -&gt; UniformConstant
uniform blockN { ... } ...; -&gt; Uniform, with Block decoration
in / out variable -&gt; Input/Output, possibly with block (below)
in / out block... -&gt; Input/Output, with Block decoration
buffer blockN { ... } ...; -&gt; Uniform, with BufferBlock decoration
shared -&gt; Workgroup
&lt;normal global&gt; -&gt; Private</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>Vulkan Only: buffer blockN { ... } ...; -&gt; StorageBuffer, when requested
OpenGL Only: uniform variable (non-block) -&gt; UniformConstant
OpenGL Only: ... uniform atomic_uint ... -&gt; AtomicCounter</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_inputoutput">Input/Output</h5>
<div class="paragraph">
<p>Mapping of input/output blocks or variables is the same for all versions
of GLSL or ESSL. To the extent variables or members are available in a
version, its location is as follows:</p>
</div>
<div class="paragraph">
<p>These are mapped to SPIR-V individual variables, with similarly spelled
built-in decorations (except as noted):</p>
</div>
<div class="paragraph">
<p>Any stage:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>in gl_VertexIndex (Vulkan only)
in gl_VertexID (OpenGL only)
in gl_InstanceIndex (Vulkan only)
in gl_InstanceID (OpenGL only)
in gl_InvocationID
in gl_PatchVerticesIn (PatchVertices)
in gl_PrimitiveIDIn (PrimitiveID)
in/out gl_PrimitiveID (in/out based only on storage qualifier)
in gl_TessCoord</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>in/out gl_Layer
in/out gl_ViewportIndex</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>patch in/out gl_TessLevelOuter (uses Patch decoration)
patch in/out gl_TessLevelInner (uses Patch decoration)</pre>
</div>
</div>
<div class="paragraph">
<p>Compute stage only:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>in gl_NumWorkGroups
in gl_WorkGroupSize
in gl_WorkGroupID
in gl_LocalInvocationID
in gl_GlobalInvocationID
in gl_LocalInvocationIndex</pre>
</div>
</div>
<div class="paragraph">
<p>Fragment stage only:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>in gl_FragCoord
in gl_FrontFacing
in gl_ClipDistance
in gl_CullDistance
in gl_PointCoord
in gl_SampleID
in gl_SamplePosition
in gl_HelperInvocation
out gl_FragDepth
in gl_SampleMaskIn (SampleMask)
out gl_SampleMask (in/out based only on storage qualifier)</pre>
</div>
</div>
<div class="paragraph">
<p>These are mapped to SPIR-V blocks, as implied by the pseudo code, with
the members decorated with similarly spelled built-in decorations:</p>
</div>
<div class="paragraph">
<p>Non-fragment stage:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>in/out gl_PerVertex { // some subset of these members will be used
gl_Position
gl_PointSize
gl_ClipDistance
gl_CullDistance
} // name of block is for debug only</pre>
</div>
</div>
<div class="paragraph">
<p>There is at most one input and one output block per stage in SPIR-V.
The subset and order of members will match between stages sharing an
interface.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_vulkan_only_mapping_of_precision_qualifiers">12.2.6. Vulkan Only: Mapping of Precision Qualifiers</h4>
<div class="literalblock">
<div class="content">
<pre>lowp -&gt; RelaxedPrecision, on storage variable and operation
mediump -&gt; RelaxedPrecision, on storage variable and operation
highp -&gt; 32-bit, same as int or float</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>portability tool/mode -&gt; OpQuantizeToF16</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_precise">12.2.7. Mapping of <strong>precise</strong>:</h4>
<div class="literalblock">
<div class="content">
<pre>precise -&gt; NoContraction</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_opengl_mapping_of_atomic_uint_offset_layout_qualifier">12.2.8. OpenGL Mapping of <strong>atomic_uint</strong> <em>offset</em> layout qualifier</h4>
<div class="literalblock">
<div class="content">
<pre>offset -&gt; Offset (decoration)</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_images">12.2.9. Mapping of Images</h4>
<div class="literalblock">
<div class="content">
<pre>imageLoad() -&gt; OpImageRead
imageStore() -&gt; OpImageWrite
texelFetch() -&gt; OpImageFetch
subpassInput -&gt; OpTypeImage with Dim of SubpassData (Vulkan only)
subpassLoad() -&gt; OpImageRead (Vulkan only)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>imageAtomicXXX(params, data) -&gt; %ptr = OpImageTexelPointer params
OpAtomicXXX %ptr, data</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>XXXQueryXXX(combined) -&gt; %image = OpImage combined
OpXXXQueryXXX %image</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_layouts">12.2.10. Mapping of Layouts</h4>
<div class="literalblock">
<div class="content">
<pre>std140/std430 -&gt; explicit Offset, ArrayStride, and MatrixStride
Decoration on struct members
shared/packed -&gt; not allowed
&lt;default&gt; -&gt; not shared, but std140 or std430
xfb_offset -&gt; Offset Decoration on the object or struct member
xfb_buffer -&gt; XfbBuffer Decoration on the object
xfb_stride -&gt; XfbStride Decoration on the object
any xfb_* -&gt; the Xfb Execution Mode is set
captured XFB -&gt; has both XfbBuffer and Offset
non-captured -&gt; lacking XfbBuffer or Offset</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>max_vertices -&gt; OutputVertices</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_barriers">12.2.11. Mapping of barriers</h4>
<div class="literalblock">
<div class="content">
<pre>barrier() (compute) -&gt; OpControlBarrier(/*Execution*/Workgroup,
/*Memory*/Workgroup,
/*Semantics*/AcquireRelease |
WorkgroupMemory)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>barrier() (tess control) -&gt; OpControlBarrier(/*Execution*/Workgroup,
/*Memory*/Invocation,
/*Semantics*/None)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>memoryBarrier() -&gt; OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
UniformMemory |
WorkgroupMemory |
ImageMemory)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>memoryBarrierBuffer() -&gt; OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
UniformMemory)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>memoryBarrierShared() -&gt; OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
WorkgroupMemory)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>memoryBarrierImage() -&gt; OpMemoryBarrier(/*Memory*/Device,
/*Semantics*/AcquireRelease |
ImageMemory)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>groupMemoryBarrier() -&gt; OpMemoryBarrier(/*Memory*/Workgroup,
/*Semantics*/AcquireRelease |
UniformMemory |
WorkgroupMemory |
ImageMemory)</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_atomics">12.2.12. Mapping of atomics</h4>
<div class="literalblock">
<div class="content">
<pre>all atomic builtin functions -&gt; Semantics = None(Relaxed)</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>atomicExchange() -&gt; OpAtomicExchange
imageAtomicExchange() -&gt; OpAtomicExchange
atomicCompSwap() -&gt; OpAtomicCompareExchange
imageAtomicCompSwap() -&gt; OpAtomicCompareExchange
N/A -&gt; OpAtomicCompareExchangeWeak</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_opengl_only_mapping_of_atomics">12.2.13. OpenGL Only: Mapping of Atomics</h4>
<div class="literalblock">
<div class="content">
<pre>atomicCounterIncrement -&gt; OpAtomicIIncrement
atomicCounterDecrement -&gt; OpAtomicIDecrement
atomicCounter -&gt; OpAtomicLoad</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_mapping_of_other_instructions">12.2.14. Mapping of other instructions</h4>
<div class="literalblock">
<div class="content">
<pre>% -&gt; OpUMod/OpSMod
mod() -&gt; OpFMod
N/A -&gt; OpSRem/OpFRem</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre>pack/unpack (conversion) -&gt; pack/unpack in GLSL extended instructions
pack/unpack (no conversion) -&gt; OpBitcast</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 4.60.7<br>
Last updated 2019-07-10 14:42:53 MDT
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
</body>
</html>