blob: 98653c01f16de0b4a8bdda3df46aa7450bf29291 [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="Robert J. Simpson, Qualcomm (Editor), John Kessenich, Google (Editor), Dave Baldwin and Randi Rost (Version 1.1 Authors)">
<title>The OpenGL ES&#174; Shading Language, Version 3.20.6</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 ES<sup>&#174;</sup> Shading Language, Version 3.20.6</h1>
<div class="details">
<span id="author" class="author">Robert J. Simpson, Qualcomm (Editor), John Kessenich, Google (Editor), Dave Baldwin and Randi Rost (Version 1.1 Authors)</span><br>
<span id="revnumber">version 3.20.6,</span>
<span id="revdate">Wed, 10 Jul 2019 20:42:56 +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="#compatibility">1.5. Compatibility</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</a></li>
<li><a href="#source-strings">3.2. Source Strings</a></li>
<li><a href="#version-declaration">3.3. Version Declaration</a></li>
<li><a href="#preprocessor">3.4. Preprocessor</a></li>
<li><a href="#comments">3.5. Comments</a></li>
<li><a href="#tokens">3.6. Tokens</a></li>
<li><a href="#keywords">3.7. Keywords</a></li>
<li><a href="#identifiers">3.8. Identifiers</a></li>
<li><a href="#definitions">3.9. Definitions</a></li>
<li><a href="#logical-phases-of-compilation">3.10. Logical Phases of Compilation</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 Components</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="#specialization-constant-operations">5.11. Specialization-Constant Operations</a></li>
<li><a href="#evaluation-of-expressions">5.12. Evaluation of Expressions</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="#built-in-constants">7.2. Built-In Constants</a></li>
<li><a href="#built-in-uniform-state">7.3. Built-In Uniform State</a></li>
<li><a href="#redeclaring-built-in-blocks">7.4. 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="#shader-invocation-control-functions">8.15. Shader Invocation Control Functions</a></li>
<li><a href="#shader-memory-control-functions">8.16. Shader Memory Control Functions</a></li>
<li><a href="#_subpass_input_functions">8.17. Subpass-Input Functions</a></li>
</ul>
</li>
<li><a href="#shader-interface-matching">9. Shader Interface Matching</a>
<ul class="sectlevel2">
<li><a href="#input-output-matching-by-name-in-linked-programs">9.1. Input Output Matching by Name in Linked Programs</a></li>
<li><a href="#matching-of-qualifiers">9.2. Matching of Qualifiers</a></li>
</ul>
</li>
<li><a href="#shading-language-grammar">10. Shading Language Grammar</a></li>
<li><a href="#counting-of-inputs-and-outputs">11. Counting of Inputs and Outputs</a></li>
<li><a href="#acknowledgments">12. Acknowledgments</a></li>
<li><a href="#references">13. Normative References</a></li>
<li><a href="#_non_normative_spir_v_mappings">14. Non-Normative SPIR-V Mappings</a>
<ul class="sectlevel2">
<li><a href="#_feature_comparisons">14.1. Feature Comparisons</a></li>
<li><a href="#_mapping_from_glsl_to_spir_v">14.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 3.20 of the OpenGL ES Shading Language (GLSL ES).
It requires __VERSION__ to substitute 320, and requires
<strong>#version</strong> to accept only
<code>320 es</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>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 ES Specification are normative for OpenGL ES 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 ES 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 ES 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 ES &#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 ES 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 ES
source: the front-end can be informed of such limits, and report errors when
they are exceeded.</p>
</div>
<div class="paragraph">
<p>All references in this specification to the <a href="#references">OpenGL ES Specification</a> are to
version 3.2.</p>
</div>
<div class="sect2">
<h3 id="changes">1.1. Changes</h3>
<div class="sect3">
<h4 id="_changes_from_glsl_es_3_2_revision_5">1.1.1. Changes from GLSL ES 3.2 revision 5</h4>
<div class="ulist">
<ul>
<li>
<p>Incorporated the GL_KHR_vulkan_glsl specification.</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-glsl-es-3.2-revision-4">1.1.2. Changes from GLSL ES 3.2 revision 4</h4>
<div class="ulist">
<ul>
<li>
<p>Clarified that this specification completely defines the OpenGL ES Shading Language.
Normatively reference C++ only for the preprocessor.</p>
</li>
<li>
<p>Private GLSL issues 7, 38: Corrected the values of some builtin constants.
The values were given correctly in the OpenGL ES Specification.</p>
</li>
<li>
<p>Private GLSL issue 30: Clarify that output packing rules apply to the last
vertex pipeline stage, not necessarily the vertex stage.</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-glsl-es-3.2-revision-3">1.1.3. Changes from GLSL ES 3.2 revision 3</h4>
<div class="ulist">
<ul>
<li>
<p>Matching of default uniforms when shaders are linked.</p>
</li>
<li>
<p><em>gl_DepthRange</em> is only guaranteed to be available in the fragment
stage.</p>
</li>
<li>
<p>Clarification of definition of static use.</p>
</li>
<li>
<p>Sampling behavior in the absence of <strong>sample</strong> and <strong>centroid</strong>.</p>
</li>
<li>
<p>Clarified the requirements when the specification uses the terms
<em>should</em>/<em>should not</em> and <em>undefined behavior</em>.</p>
</li>
<li>
<p>Arrayed blocks cannot have layout location qualifiers on members</p>
</li>
<li>
<p><strong>barrier</strong>() defines a partial order which includes tessellation control
shader outputs.</p>
</li>
<li>
<p>Vertex shader integer output qualification.</p>
</li>
<li>
<p>Incorrect use of predefined pragmas.</p>
</li>
<li>
<p>Clarified use of <strong>readonly</strong> and <strong>writeonly</strong> qualifiers.</p>
</li>
<li>
<p>USAMPLERBUFFER added to grammar.</p>
</li>
<li>
<p>Clarified precision qualifiers can be used in interface blocks.</p>
</li>
<li>
<p>Clarified <strong>memoryBarrierShared</strong> only applies to the current workgroup.</p>
</li>
<li>
<p>The layout qualifier <em>invocations</em> must not be zero.</p>
</li>
<li>
<p>The layout qualifier <em>local_size</em> must not be zero.</p>
</li>
<li>
<p>Clarified the definition of static assignment.</p>
</li>
<li>
<p>Removed list of types with no default precision.</p>
</li>
<li>
<p>Removed scoping rules from the grammar. Refer instead to the <a href="#scoping">scoping</a> section.</p>
</li>
<li>
<p>Require a statement after the final label of a switch.</p>
</li>
<li>
<p>Define <strong>gl_BoundingBox</strong>.</p>
</li>
<li>
<p><strong>length</strong>() expressions returning a constant-value may not include side effects.</p>
</li>
<li>
<p>Clarified that variables may be declared <strong>readonly writeonly</strong>.</p>
</li>
<li>
<p>Use of constant expressions within <strong>#line</strong> directives is undefined.</p>
</li>
<li>
<p><strong>gl_in</strong> can be redeclared using unsized-array syntax.</p>
</li>
<li>
<p>Clarified which sampler types may be used for depth and stencil textures.</p>
</li>
<li>
<p>Added order-of-operation and other explanations to the
<a href="#the-precise-qualifier">Precise Qualifier</a> section.</p>
</li>
<li>
<p>The <strong>precise</strong> qualifier applied to a block/struct applies recursively to the members.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="changes-from-glsl-es-3.2-revision-2">1.1.4. Changes from GLSL ES 3.2 revision 2</h4>
<div class="ulist">
<ul>
<li>
<p>Updated value for <em>gl_MaxTessControlTotalOutputComponents</em></p>
</li>
<li>
<p>Clarified the allowed character set for pre-processing</p>
</li>
<li>
<p>Integer division wrapping behavior</p>
</li>
<li>
<p>Clarified pre-processor expressions (<em>pp-constant-expression</em>)</p>
</li>
<li>
<p>UBO and SSBO precisions do not need to match for linked shaders
(consistent with GLSL ES 3.1)</p>
</li>
<li>
<p><strong>modf</strong> function</p>
</li>
<li>
<p>Sequence and ternary operators with <strong>void</strong> type</p>
</li>
<li>
<p>Sequence and ternary operators with array types</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="changes-from-glsl-es-3.2-revision-1">1.1.5. Changes from GLSL ES 3.2 revision 1</h4>
<div class="ulist">
<ul>
<li>
<p>Signed zeros must be supported</p>
</li>
<li>
<p>Layout qualifier table</p>
</li>
<li>
<p>Allowed optimizations when evaluating expressions</p>
</li>
<li>
<p>Updated value for <em>gl_MaxTessControlInputComponents</em></p>
</li>
<li>
<p>Updated value for <em>gl_MaxTessControlOutputComponents</em></p>
</li>
<li>
<p>Updated value for <em>gl_MaxTessEvaluationInputComponents</em></p>
</li>
<li>
<p>Updated value for <em>gl_MaxTessEvaluationOutputComponents</em></p>
</li>
<li>
<p>Updated value for <em>gl_MaxGeometryOutputComponents</em></p>
</li>
<li>
<p>Require precisions in blocks to match when linking</p>
</li>
<li>
<p>Updated conclusions in issues section</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="changes-from-glsl-es-3.1-revision-4">1.1.6. Changes from GLSL ES 3.1 revision 4</h4>
<div class="ulist">
<ul>
<li>
<p>Added the following extensions:</p>
<div class="ulist">
<ul>
<li>
<p><a href="https://www.opengl.org/registry/specs/KHR/blend_equation_advanced.txt">KHR_blend_equation_advanced</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_sample_variables.txt">OES_sample_variables</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_shader_image_atomic.txt">OES_shader_image_atomic</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_shader_multisample_interpolation.txt">OES_shader_multisample_interpolation</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_texture_storage_multisample_2d_array.txt">OES_texture_storage_multisample_2d_array</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_geometry_shader.txt">OES_geometry_shader</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_gpu_shader5.txt">OES_gpu_shader5</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_primitive_bounding_box.txt">OES_primitive_bounding_box</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_shader_io_blocks.txt">OES_shader_io_blocks</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_tessellation_shader.txt">OES_tessellation_shader</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_texture_buffer.txt">OES_texture_buffer</a></p>
</li>
<li>
<p><a href="https://www.khronos.org/registry/gles/extensions/OES/OES_texture_cube_map_array.txt">OES_texture_cube_map_array</a></p>
</li>
<li>
<p><a href="https://www.opengl.org/registry/specs/KHR/robustness.txt">KHR_robustness</a></p>
</li>
</ul>
</div>
</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 ES Shading Language, version 3.20</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.
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.</p>
</div>
<div class="paragraph">
<p>The compilation process is implementation-dependent but is generally split
into a number of stages, each of which occurs at one of the following times:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A call to <em>glCompileShader</em></p>
</li>
<li>
<p>A call to <em>glLinkProgram</em></p>
</li>
<li>
<p>A draw call or a call to <em>glValidateProgram</em></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The implementation should report errors as early a possible but in any case
must satisfy the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>All lexical, grammatical and semantic errors must have been detected
following a call to <em>glLinkProgram</em></p>
</li>
<li>
<p>Errors due to mismatch between the shaders (link-time errors) must have
been detected following a call to <em>glLinkProgram</em></p>
</li>
<li>
<p>Errors due to exceeding resource limits must have been detected
following any draw call or a call to <em>glValidateProgram</em></p>
</li>
<li>
<p>A call to <em>glValidateProgram</em> must report all errors associated with a
program object given the current GL state.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Where the specification uses the terms <em>required</em>, <em>must</em>/<em>must</em> <em>not</em>,
<em>does</em>/<em>does</em> <em>not</em>, <em>disallowed</em>, or <em>not</em> <em>supported</em>, the compiler or
linker is required to detect and report any violations.
Similarly when a condition or situation is an <strong>error</strong>, it must be reported.
Use of any feature marked as <em>reserved</em> is an error.
Where the specification uses the terms <em>should</em>/<em>should</em> <em>not</em>, <em>undefined</em>
<em>behavior</em>, <em>undefined</em> <em>value</em> or <em>undefined</em> <em>*results*</em>, implementations
will not produce a compile-time error but are encouraged to issue a warning
for violations.
The run-time behavior of the program in these cases is not constrained (and
so may include termination or system instability).
It is expected that systems will be designed to handle these cases
gracefully but specification of this is outside the scope of this
specification.</p>
</div>
<div class="paragraph">
<p>Implementations may not in general support functionality beyond the mandated
parts of the specification without use of the relevant extension.
The only exceptions are:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>If a feature is marked as optional.</p>
</li>
<li>
<p>Where a maximum value is stated (e.g. the maximum number of vertex
outputs), the implementation may support a higher value than that
specified.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Where the implementation supports more than the mandated specification,
off-target compilers are encouraged to issue warnings if these features are
used.</p>
</div>
<div class="paragraph">
<p>The compilation process is split between the compiler and linker.
The allocation of tasks between the compiler and linker is implementation
dependent.
Consequently there are many errors which may be detected either at compile
or link time, depending on the implementation.</p>
</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="compatibility">1.5. Compatibility</h3>
<div class="paragraph">
<p>The OpenGL ES 3.2 API is designed to work with GLSL ES v1.00,
GLSL ES 3.00, GLSL ES 3.10 and GLSL ES 3.20.
In general a shader written for versions prior to OpenGL ES 3.2
should work without modification in OpenGL ES 3.2.</p>
</div>
<div class="paragraph">
<p>When porting applications from an earlier to later version of the GLSL ES,
the following points should be noted:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Not all language constructs present in earlier versions of the language
are available in later versions e.g. attribute and varying qualifiers
are present in v1.00 but not v3.00.
However, the functionality of GLSL ES 3.20 is a super-set of
GLSL ES 3.10.</p>
</li>
<li>
<p>Some features of later versions of the API require language features
that are not present in earlier version of the language.</p>
</li>
<li>
<p>It is an error to link shaders if they are written in different versions
of the language.</p>
</li>
<li>
<p>The OpenGL ES 2.0 and 3.0 APIs do not support shaders written in GLSL ES
3.20.</p>
</li>
<li>
<p>Using GLSL ES 1.00 shaders within OpenGL ES 3.x may extend the resources
available beyond the minima specified in GLSL ES 1.0.
Shaders which make use of this will not necessarily run on an OpenGL ES
2.0 implementation: Similarly for GLSL ES 3.00 shaders running within
OpenGL ES 3.2.</p>
</li>
<li>
<p>Support of line continuation and support of UTF-8 characters within
comments is optional in GLSL ES 1.00 when used with the OpenGL ES 2.0
API.
However, support is mandated for both of these when a GLSL ES 1.00
shader is used with the OpenGL ES 3.x APIs.</p>
</li>
</ul>
</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 ES 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>Compilation units for these processors are referred to as <em>shaders</em> and the
processors themselves are also referred to as <em>shader stages</em>.
Only one shader can be run on a processor at any one time; there is no
support for linking multiple compilation units together for a single shader
stage.
One or more shaders are linked together to form a single program and each
program contains shader <em>executables</em> for one or more consecutive shader
stages.</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 ES Shading Language to run on this processor are called
<em>vertex shaders</em>.</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 ES Shading Language to run on this processor are called
tessellation control shaders.</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
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 ES Shading Language to run on this processor are called
tessellation evaluation shaders.</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 ES Shading Language to run on this processor are called
<em>geometry shaders</em>.</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 ES Shading Language to run on this processor are called
<em>fragment shaders</em>.</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 ES Shading Language to run on this processor are called
<em>compute shaders</em>.</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</h3>
<div class="paragraph">
<p>The source character set used for the OpenGL ES Shading Language is Unicode in the UTF-8
encoding scheme.
Invalid UTF-8 characters are ignored.
During pre-processing, the following applies:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A byte with the value zero is always interpreted as the end of the
string</p>
</li>
<li>
<p>Backslash ('\'), is used to indicate line continuation when immediately
preceding a new-line.</p>
</li>
<li>
<p>White space consists of one or more of the following characters: the
space character, horizontal tab, vertical tab, form feed,
carriage-return, line-feed.</p>
</li>
<li>
<p>The number sign (<strong>#</strong>) is used for preprocessor directives</p>
</li>
<li>
<p>Macro names are restricted to:</p>
<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>, except for the first character of a macro name.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>After preprocessing, only the following characters are allowed in the
resulting stream of GLSL ES 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>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>
<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.</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="version-declaration">3.3. Version Declaration</h3>
<div class="paragraph">
<p>Shaders must declare the version of the language they are written to.
The version is specified in the first line of a shader by a character
string:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#version</span> number es</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 320 es</strong>&#8221; is required in any shader that
uses version 3.20 of the language.
Any <em>number</em> representing a version of the language a compiler does not
support will cause an error to be generated.
Version 1.00 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.00.</p>
</div>
<div class="paragraph">
<p>Shaders declaring version 3.20 of the shading language cannot be
linked with shaders declaring a previous version.</p>
</div>
<div class="paragraph">
<p>The <strong>#version</strong> directive must be present in the first line of a shader and
must be followed by a newline.
It may contain optional white-space as specified below but no other
characters are allowed.
The directive is only permitted in the first line of a shader.</p>
</div>
<div class="paragraph">
<p>Processing of the #version directive occurs before all other preprocessing,
including line concatenation and comment processing.</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>version-declaration</em> : </dt>
<dd>
<p><em>whitespace<sub>opt</sub></em> POUND <em>whitespace<sub>opt</sub></em> VERSION <em>whitespace</em> <em>number</em>
<em>whitespace</em> ES <em>whitespace<sub>opt</sub></em></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>Tokens:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>POUND <strong>#</strong><br>
VERSION <strong>version</strong><br>
ES <strong>es</strong></p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="preprocessor">3.4. 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></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p>#line</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The following
operator is
also available:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p>defined<br></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Note that the version directive is not considered to be a preprocessor
directive and so is not listed here.</p>
</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.</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 an 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>
GL_ES</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 ES Shading Language.
The version of the shading language described in this document will have
__VERSION__ substitute the decimal integer 320.</p>
</div>
<div class="paragraph">
<p>GL_ES will be defined and set to 1.
This is not true for the non-ES OpenGL Shading Language, so it can be used
to do a compile time test to determine if a shader is compiling as an
GLSL ES shader.</p>
</div>
<div class="paragraph">
<p>By convention, all macro names 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.
All macro names prefixed with &#8220;GL_&#8221; (&#8220;GL&#8221; followed by a single
underscore) are also reserved, and defining
such a name results in a compile-time error.</p>
</div>
<div class="paragraph">
<p>It is an error to undefine or to redefine a built-in (pre-defined) macro
name.</p>
</div>
<div class="paragraph">
<p>Implementations must support macro-name lengths of up to 1024 characters.
It is an error to declare a name with a length greater than this.</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
restricted to <em>pp-constant-expressions</em> as defined below.</p>
</li>
<li>
<p>Undefined identifiers not consumed by the <strong>defined</strong> operator do not
default to '0'.
Use of such identifiers causes an error.</p>
</li>
<li>
<p>Character constants are not supported.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>As in C++, a macro name defined with an empty replacement list does not
default to '0' when used in a preprocessor expression.</p>
</div>
<div class="paragraph">
<p>A <em>pp-constant-expression</em> is an integral expression, evaluated at
compile-time during preprocessing and formed from literal integer constants
and 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">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>There are no number sign based operators (e.g. no <strong><mark></strong> or <strong></mark>@</strong>), no <strong>##</strong>
operator, nor is there a <strong>sizeof</strong> operator.</p>
</div>
<div class="paragraph">
<p>The semantics of applying operators in the preprocessor match those standard
in the C++ preprocessor with the following exceptions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The 2<sup>nd</sup> operand in a logical and ('&amp;&amp;') operation is evaluated if and
only if the 1<sup>st</sup> operand evaluates to non-zero.</p>
</li>
<li>
<p>The 2<sup>nd</sup> operand in a logical or ('||') operation is evaluated if and
only if the 1<sup>st</sup> operand evaluates to zero.</p>
</li>
<li>
<p>There is no boolean type and no boolean literals.
A <em>true</em> or <em>false</em> result is returned as integer <em>one</em> or <em>zero</em>
respectively.
Wherever a boolean operand is expected, any non-zero integer is
interpreted as <em>true</em> and a zero integer as <em>false</em>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If an operand is not evaluated, the presence of undefined identifiers in the
operand will not cause an error.</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 ES 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>The scope as well as the effect of the optimize and debug pragmas is
implementation-dependent except that their use must not generate an error.
Incorrect use of predefined pragmas does not cause an error.</p>
</div>
<div class="paragraph">
<p>By default, compilers of this language must issue compile-time
syntactic, semantic,
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 an 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>For each extension there is an associated macro.
The macro is always defined in an implementation that supports the
extension.
This allows the following construct to be used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#ifdef</span> OES_extension_name
<span class="preprocessor">#extension</span> OES_extension_name : enable
<span class="comment">// code that requires the extension</span>
<span class="preprocessor">#else</span>
<span class="comment">// alternative code</span>
<span class="preprocessor">#endif</span></code></pre>
</div>
</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
<em>pp-constant-expressions</em>.
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 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 class="paragraph">
<p>If during macro expansion a preprocessor directive is encountered, the
results are undefined; the compiler may or may not report an error in such
cases.</p>
</div>
</div>
<div class="sect2">
<h3 id="comments">3.5. Comments</h3>
<div class="paragraph">
<p>Comments are delimited by <strong>/*</strong> and <strong>*/</strong>, or by <strong>//</strong> and a new-line.
// style comments include the initial // marker and continue up to, but
not including, the terminating newline.
/*...*/ comments include both the start and end marker.
The begin comment delimiters (/* or //) are not recognized as comment
delimiters inside of a comment, hence comments cannot be nested.
Comments are treated syntactically as a single space.</p>
</div>
</div>
<div class="sect2">
<h3 id="tokens">3.6. 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.7. 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 an 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></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></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>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></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>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>lowp</strong> <strong>mediump</strong> <strong>highp</strong> <strong>precision</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>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>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>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>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>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 an error:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><strong>attribute</strong> <strong>varying</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>noperspective</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>subroutine</strong></p>
</dd>
<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>
<strong>double</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>dvec2</strong> <strong>dvec3</strong> <strong>dvec4</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>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>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>sampler2DRect</strong> <strong>sampler2DRectShadow</strong> <strong>isampler2DRect</strong> <strong>usampler2DRect</strong></p>
</dd>
<dt class="hdlist1"></dt>
<dd>
<p><strong>sampler3DRect</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>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>
</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.8. 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 an 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.
It is an error if the length exceeds this value.</p>
</div>
</div>
<div class="sect2">
<h3 id="definitions">3.9. 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.9.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="uniform-and-non-uniform-control-flow">3.9.2. Uniform and Non-Uniform Control Flow</h4>
<div class="paragraph">
<p>When executing statements in a fragment shader, control flow starts as
<em>uniform control flow</em>; all fragments enter the same control path into
<em>main()</em>.
Control flow becomes <em>non-uniform</em> when different fragments take different
paths through control-flow statements (selection, iteration, and jumps).
Control flow subsequently returns to being uniform after such divergent
sub-statements or skipped code completes, until the next time different
control paths are taken.</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>Other examples of non-uniform control flow can occur within switch
statements and after conditional breaks, continues, early returns, and after
fragment discards, when the condition is true for some fragments but not
others.
Loop iterations that only some fragments execute are also non-uniform
control flow.</p>
</div>
<div class="paragraph">
<p>This is similarly defined for other shader stages, based on the per-instance
data items they process.</p>
</div>
</div>
<div class="sect3">
<h4 id="dynamically-uniform-expressions">3.9.3. Dynamically Uniform Expressions</h4>
<div class="paragraph">
<p>A fragment-shader expression is <em>dynamically uniform</em> if all fragments
evaluating it get the same resulting value.
When loops are involved, this refers to the expression&#8217;s value for the same
loop iteration.
When functions are involved, this refers to calls from the same call point.</p>
</div>
<div class="paragraph">
<p>This is similarly defined for other shader stages, based on the per-instance
data they process.</p>
</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 class="sect2">
<h3 id="logical-phases-of-compilation">3.10. Logical Phases of Compilation</h3>
<div class="paragraph">
<p>The compilation units for the shader processors are processed separately
before optionally being linked together in the final stage of compilation.
The logical phases of compilation are:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Source strings are input as byte sequences.
The value 'zero' is interpreted as a terminator.</p>
</li>
<li>
<p>Source strings are concatenated to form a single input.
Zero bytes are discarded but all other values are retained.</p>
</li>
<li>
<p>Each string is interpreted according to the UTF-8 standard, with the
exception that all invalid byte sequences are retained in their original
form for subsequent processing.</p>
</li>
<li>
<p>Each {carriage-return, line-feed} and {line-feed, carriage return}
sequence is replaced by a single newline.
All remaining carriage-return and line-feed characters are then each
replaced by a newline.</p>
</li>
<li>
<p>Line numbering for each character, which is equal to the number of
preceding newlines plus one, is noted.
Note this can only be subsequently changed by the #line directive and is
not affected by the removal of newlines in phase 6 of compilation.</p>
</li>
<li>
<p>Wherever a backslash ('\') occurs immediately before a newline, both are
deleted.
Note that no whitespace is substituted, thereby allowing a single
preprocessing token to span a newline.
This operation is not recursive; any new {backslash newline} sequences
generated are not removed.</p>
</li>
<li>
<p>All comments are replaced with a single space.
All (non-zero) characters and invalid UTF-8 byte sequences are allowed
within comments.
'//' style comments include the initial '//' marker and continue up to,
but not including, the terminating newline.
'/<strong>&#8230;&#8203;</strong>/' comments include both the start and end marker.</p>
</li>
<li>
<p>The source string is converted into a sequence of preprocessing tokens.
These tokens include preprocessing numbers, identifiers and
preprocessing operations.
The line number associated with each token is copied from the line
number of the first character of the token.</p>
</li>
<li>
<p>The preprocessor is run.
Directives are executed and macro expansion is performed.</p>
</li>
<li>
<p>White space and newlines are discarded.</p>
</li>
<li>
<p>Preprocessing tokens are converted into tokens.</p>
</li>
<li>
<p>The syntax is analyzed according to the GLSL ES grammar.</p>
</li>
<li>
<p>The result is checked according to the semantic rules of the language.</p>
</li>
<li>
<p>Optionally, the shaders are linked together to form one or more programs
or separable programs.
When a pair of shaders from consecutive stages are linked into the same
program, any outputs and corresponding inputs not used in both shaders
may be discarded.</p>
</li>
<li>
<p>The binary is generated.</p>
</li>
</ol>
</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 ES Shading Language is type safe.
There are no implicit conversions between types.</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 ES 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>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>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>
</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>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></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></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>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>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></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></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>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>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></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></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>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="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 an 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><strong>highp</strong>
unsigned integers have exactly 32 bits of precision.</p>
</div>
<div class="paragraph">
<p><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.
Otherwise, <strong>mediump</strong> and <strong>lowp</strong> integers have implementation-defined numbers of bits.
See &#8220;<a href="#range-and-precision">Range and Precision</a>&#8221; for details.</p>
</div>
<div class="paragraph">
<p>For all precisions, addition,
subtraction and multiplication resulting in overflow or
underflow will result in the low-order
n
bits of the correct result R, where
n is the size in bits of the integer and
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 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 an 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="dlist">
<dl>
<dt class="hdlist1">Definition</dt>
<dd>
<p>A <em>floating-point type</em> is any floating-point scalar, vector or matrix type.
It excludes arrays and structures.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Floats are available for use in a variety of scalar calculations.
Floating-point variables are defined 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">float</span> a, b = <span class="float">1</span><span class="float">.5</span>;</code></pre>
</div>
</div>
<div class="paragraph">
<p>As an input value to one of the processing units, a floating-point variable
is expected to match the IEEE 754 single precision floating-point definition
for precision and dynamic range.
<strong>highp</strong> floating-point variables within a shader are encoded according to
the IEEE 754 specification for single-precision floating-point values
(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></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.
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 class="paragraph">
<p>There is no limit on the number of digits in any <em>digit-sequence</em>.
If the value of the floating-point number is too large (small) to be stored
as a single precision value, it is converted to positive (negative)
infinity.
A value with a magnitude too small to be represented as a mantissa and
exponent is converted to zero.
Implementations may also convert subnormal (denormalized) numbers to zero.</p>
</div>
</div>
<div class="sect3">
<h4 id="vectors">4.1.5. Vectors</h4>
<div class="paragraph">
<p>The OpenGL ES 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 ES 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.
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></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 class="paragraph">
<p><strong>mat2</strong> is an alias for <strong>mat2x2</strong>, not a distinct type.
Similarly for <strong>mat3</strong> and <strong>mat4.</strong> The following is legal:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">mat2 a;
mat2x2 b = a;</code></pre>
</div>
</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>When aggregated into arrays within a shader, opaque types can only be
indexed with a dynamically uniform integral expression (see &#8220;Dynamically
Uniform Expressions&#8221;) unless otherwise noted; otherwise, results are
undefined.</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.</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 constant integral expression.</p>
</div>
<div class="paragraph">
<p>Image variables are handles to
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>).
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.22
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL ES 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>The default precision of all atomic types is <strong>highp</strong>.
It is an error to declare an atomic type with a different precision or to
specify the default precision for an atomic type to be <strong>lowp</strong> or <strong>mediump</strong>.</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
an 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 an error.
Bit fields are not supported.
Member types must be already defined (there are no forward references).
Member declarations cannot contain initializers.
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.</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 class="paragraph">
<p>Structures can contain variables of any type except:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>atomic_uint</strong> (since there is no mechanism to specify the binding)</p>
</li>
<li>
<p>image types (since there is no mechanism to specify the format
qualifier)</p>
</li>
</ul>
</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.</p>
</div>
<div class="paragraph">
<p>When present, the array size must be a constant integral expression (see
&#8220;<a href="#constant-expressions">Constant Expressions</a>&#8221;) greater than zero.
The type of the size parameter can be a signed or unsigned integer and the
choice of type does not affect the type of the resulting array.
Arrays only have a single dimension (a single number within &#8220;[ ]&#8221;),
however, arrays of arrays can be declared.
Any type can be formed into an array.</p>
</div>
<div class="paragraph">
<p>Arrays are sized either at compile-time or at run-time.
To size an array at compile-time, either the size must be specified within
the brackets as above or must be inferred from the type of the initializer.</p>
</div>
<div class="paragraph">
<p>If an array is declared as the last member of a shader storage block and the
size is not specified at compile-time, it is sized at run-time.
In all other cases, arrays are sized only at compile-time.
An array declaration sized at compile-time which leaves the size of the
array unspecified is an error.</p>
</div>
<div class="paragraph">
<p>For compile-time sized arrays, it is illegal to index an array with a
constant integral expression greater than or equal to the declared size or
with a negative constant expression.
Arrays declared as formal parameters in a function declaration must also
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.
If robust buffer access is enabled (see section 10.3.5 &#8220;Robust Buffer
Access&#8221; of the <a href="#references">OpenGL ES Specification</a>), such indexing must not result in
abnormal program termination.
The results are still undefined, but implementations are encouraged to
produce zero values for such accesses.</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>u];
<span class="directive">const</span> <span class="predefined-type">int</span> numLights = <span class="integer">2</span>;
light lights[numLights];
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>
<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</span>
vec4 v[]; <span class="comment">// okay, v will be sized at run-time</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>When the <strong>length</strong>() method will return a compile-time constant, the
expression in brackets (x above) will be evaluated and subject 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.</p>
</div>
<div class="paragraph">
<p>An array type can be formed by specifying a non-array type
(<a href="#type_specifier_nonarray">[type_specifier_nonarray]</a>) followed by an <a href="#array_specifier">[array_specifier]</a>.</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>]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the construct <em>type [size]</em> does not always result in an array of
length <em>size</em> of type <em>type</em>:</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">2</span>][<span class="integer">3</span>] <span class="comment">// an array of size [2] of array of size [3] of float,</span>
<span class="comment">// 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>An array type can also be formed without specifying a size if the definition
includes an initializer:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> x[] = <span class="predefined-type">float</span>[<span class="integer">2</span>] (<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>); <span class="comment">// declares an array of size 2</span>
<span class="predefined-type">float</span> y[] = <span class="predefined-type">float</span>[] (<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">// declares an array of size 3</span>
<span class="predefined-type">float</span> a[<span class="integer">5</span>];
<span class="predefined-type">float</span> b[] = a;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the initializer itself does not need to be a constant expression
but the length of the initializer will be a constant expression.</p>
</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 last member of a shader storage block (see &#8220;<a href="#buffer-variables">Buffer
Variables</a>&#8221;), may be declared without specifying a size.
For such arrays, the effective array size is inferred at run-time from the
size of the data store backing the shader storage block.
Such runtime-sized arrays may be indexed with general integer expressions,
but may not be passed as an argument to a function or indexed with a
negative constant expression.</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; };
buffer ShaderStorageBlock1
{
vec4 a[]; <span class="comment">// illegal</span>
vec4 b[]; <span class="comment">// legal, runtime-sized arrays are last member</span>
};
buffer ShaderStorageBlock2
{
vec4 a[<span class="integer">4</span>]; <span class="comment">// legal, size declared</span>
S b[]; <span class="comment">// legal, runtime-sized arrays are allowed,</span>
<span class="comment">// including arrays of structures</span>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>However, it is a compile-time error to assign to a runtime-sized array.
Assignments to individual elements of the array is allowed.</p>
</div>
<div class="paragraph">
<p>Arrays have a fixed number of elements.
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>The return value is a signed integral expression.
For compile-time sized arrays, the value returned by the length method is a
constant expression.
For run-time sized arrays , the value returned will not be constant
expression and will be determined at run time based on the size of the
buffer object providing storage for the block.</p>
</div>
<div class="paragraph">
<p>The precision is determined using the same rules as for other cases where
there is no intrinsic precision.
See &#8220;<a href="#precision-qualifiers">Precision Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>Any restrictions on the usage of a type also apply to arrays of that type.
This applies recursively.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="scoping">4.2. Scoping</h3>
<div class="paragraph">
<p>The scope of a declaration determines where the declaration is visible.
GLSL ES uses a system of statically nested scopes.
This allows names to be redefined within a shader.</p>
</div>
<div class="sect3">
<h4 id="definition-of-terms">4.2.1. Definition of Terms</h4>
<div class="paragraph">
<p>The term <em>scope</em> refers to a specified region of the program where names are
guaranteed to be visible.
For example, a <em>compound_statement_with_scope</em> ('{' <em>statement</em> <em>statement</em>
&#8230;&#8203;
'}') defines a scope.</p>
</div>
<div class="paragraph">
<p>A <em>nested scope</em> is a scope defined within an outer scope.</p>
</div>
<div class="paragraph">
<p>The terms '<em>same scope'</em> and '<em>current scope</em>' are equivalent to the term
'<em>scope</em>' but used to emphasize that nested scopes are excluded.</p>
</div>
<div class="paragraph">
<p>The <em>scope of a declaration</em> is the region or regions of the program where
that declaration is visible.</p>
</div>
<div class="paragraph">
<p>A <em>name space</em> defines where names may be defined.
Within a single name space, a name has at most one entry, specifying it to
be one of: structure, variable, or function.</p>
</div>
<div class="paragraph">
<p>In general, each scope has an associated name space.
However, in certain cases e.g. for uniforms, multiple scopes share the same
name space.
In these cases, conflicting declarations are an error, even though the name
is only visible in the scopes where it is declared.</p>
</div>
</div>
<div class="sect3">
<h4 id="types-of-scope">4.2.2. Types of Scope</h4>
<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 (specified as
<em>statement-no-new-scope</em> in the grammar).
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.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><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 for and while 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 do and while (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>Representing the if construct as:</p>
</div>
<div class="paragraph">
<p><strong>if</strong> if-expression <strong>then</strong> if-statement <strong>else</strong> else-statement,</p>
</div>
<div class="paragraph">
<p>a variable declared in the if-statement is scoped to the end of the
if-statement.
A variable declared in the else-statement is scoped to the end of the
else-statement.
This applies both when these statements are simple statements and when they
are compound statements.
The if-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>,<span class="comment">/* 2nd x visible here */</span> y = x; <span class="comment">// y is initialized to 2</span>
<span class="predefined-type">int</span> z = z; <span class="comment">// error if z not previously defined.</span>
}
{
<span class="predefined-type">int</span> x = x; <span class="comment">// x is initialized to '1'</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>A structure name declaration is visible at the end of the <em>struct_specifier</em>
in which it was declared:</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">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></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="redeclaring-names">4.2.3. Redeclaring Names</h4>
<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.
Otherwise, within a shader, a declared name cannot be redeclared in the same
scope; doing so results in a redeclaration 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>Names of built-in functions cannot be redeclared as functions.
Therefore overloading or redefining built-in functions is an error.</p>
</div>
<div class="paragraph">
<p>A <em>declaration</em> is considered to be a statement that adds a name or
signature to the symbol table.
A <em>definition</em> is a statement that fully defines that name or signature.
E.g.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> f();<span class="comment">// declaration;</span>
<span class="predefined-type">int</span> f() {<span class="keyword">return</span> <span class="integer">0</span>;}<span class="comment">// declaration and definition</span>
<span class="predefined-type">int</span> x; <span class="comment">// declaration and definition</span>
<span class="predefined-type">int</span> a[<span class="integer">4</span>];<span class="comment">// array declaration and definition</span>
<span class="keyword">struct</span> S {<span class="predefined-type">int</span> x;};<span class="comment">// structure declaration and definition</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The determination of equivalence of two declarations depends on the type of
declaration.
For functions, the whole function signature must be considered (see
&#8220;Function Definitions&#8221;).
For variables (including arrays) and structures only the names must match.</p>
</div>
<div class="paragraph">
<p>Within each scope, a name may be declared either as a variable declaration
<em>or</em> as function declarations <em>or</em> as a structure.</p>
</div>
<div class="paragraph">
<p>Examples of combinations that are allowed:</p>
</div>
<div class="paragraph">
<p>1.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> f(<span class="predefined-type">int</span>) {...}
<span class="directive">void</span> f(<span class="predefined-type">float</span>) {...}<span class="comment">// function overloading allowed</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>2.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> f(<span class="predefined-type">int</span>);<span class="comment">// 1^st^ declaration (allowed)</span>
<span class="directive">void</span> f(<span class="predefined-type">int</span>);<span class="comment">// repeated declaration (allowed)</span>
<span class="directive">void</span> f(<span class="predefined-type">int</span>) {...}<span class="comment">// single definition (allowed)</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Examples of combinations that are disallowed:</p>
</div>
<div class="paragraph">
<p>1.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> f(<span class="predefined-type">int</span>) {...}
<span class="directive">void</span> f(<span class="predefined-type">int</span>) {...}<span class="comment">// Error: repeated definition</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>2.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> f(<span class="predefined-type">int</span>);
<span class="keyword">struct</span> f {<span class="predefined-type">int</span> x;};<span class="comment">// Error: type 'f' conflicts with function 'f'</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>3.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> f {<span class="predefined-type">int</span> x;};
<span class="predefined-type">int</span> f;<span class="comment">// Error: conflicts with the type 'f'</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>4.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> a[<span class="integer">3</span>];
<span class="predefined-type">int</span> a[<span class="integer">3</span>];<span class="comment">// Error: repeated array definition</span></code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>5.</p>
</div>
<div class="openblock">
<div class="content">
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> x;
<span class="predefined-type">int</span> x;<span class="comment">// Error: repeated variable definition</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="global-scope">4.2.4. Global Scope</h4>
<div class="paragraph">
<p>The built-in functions are scoped in the global scope users declare global
variables in.
That is, a shader&#8217;s global scope, available for user-defined functions and
global variables, is the same as the scope containing the built-in
functions.
Function declarations (prototypes) cannot occur inside of functions; they
must be at global scope.
Hence it is not possible to hide a name with a function.</p>
</div>
</div>
<div class="sect3">
<h4 id="shared-globals">4.2.5. Shared Globals</h4>
<div class="paragraph">
<p>Shared globals are variables that can be accessed by multiple compilation
units.
In GLSL ES the only shared globals are uniforms.
Vertex shader outputs are not considered to be shared globals since they
must pass through the rasterization stage before they are used as input by
the fragment shader.</p>
</div>
<div class="paragraph">
<p>Shared globals share the same name space, and must be declared with the same
type and precision.
They will share the same storage.
Shared global arrays must have the same base type and the same explicit
size.
Scalars must have exactly the same precision, 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.</p>
</div>
</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 compile-time constant</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>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>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>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>Data types for communication from one run of a shader executable to its next
run (to communicate between fragments or between vertices) do not exist.
This would prevent parallel execution of the same shader executable on
multiple vertices or fragments.</p>
</div>
<div class="paragraph">
<p>In declarations of global variables with no storage qualifier or with a
const qualifier, any initializer must be a constant expression.
Declarations of global variables with other storage qualifiers may not
contain initializers.
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="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
can be declared using
the <strong>const</strong> qualifier.
Any variables qualified as constant are read-only variables for that shader.
Declaring variables as constant allows more descriptive shaders than using
hard-wired numerical constants.
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 an 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>);</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.</p>
</div>
<div class="paragraph">
<p>Initializers for <strong>const</strong> declarations
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 ES 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>The <strong>length</strong>() method on a compile-time sized array, whether or not the
object itself is constant.</p>
</li>
<li>
<p>A constructor whose arguments are all constant expressions.</p>
</li>
<li>
<p>For non-specialization constants only:
A built-in function call whose arguments are all constant expressions,
with the exception of the texture lookup functions.
This rule excludes functions with a <strong>void</strong> return or functions that have
an <strong>out</strong> parameter.
The built-in functions <strong>dFdx</strong>, <strong>dFdy</strong>, and <strong>fwidth</strong> must return 0 when
evaluated inside an initializer with an argument that is a constant
expression.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Function calls to user-defined functions (non-built-in functions) cannot be
used to form constant expressions.</p>
</div>
<div class="paragraph">
<p>Scalar, vector, matrix, array and structure variables are constant
expressions if qualified as <strong>const</strong>.
Opaque types cannot be constant expressions.</p>
</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 an error to write to a variable declared as an input.</p>
</div>
<div class="paragraph">
<p>Only the input variables that are
actually
read need to be written by the
previous stage; it is allowed to have superfluous declarations of input
variables.</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 an 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>An array</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 ES 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>
<li>
<p>A structure containing an array</p>
</li>
<li>
<p>A structure containing a structure</p>
</li>
<li>
<p>For per-vertex-arrayed variables:</p>
<div class="ulist">
<ul>
<li>
<p>Per-vertex-arrayed arrays of arrays</p>
</li>
<li>
<p>Per-vertex-arrayed arrays of structures</p>
</li>
</ul>
</div>
</li>
<li>
<p>For non-per-vertex-arrayed variables:</p>
<div class="ulist">
<ul>
<li>
<p>An array of arrays</p>
</li>
<li>
<p>An array of structures</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment shader inputs get per-fragment values, typically interpolated from
a previous stage&#8217;s outputs.</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>
<li>
<p>An array of arrays</p>
</li>
<li>
<p>An array of structures</p>
</li>
<li>
<p>A structure containing an array</p>
</li>
<li>
<p>A structure containing a structure</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment shader inputs that are, or contain, integral
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;
flat in vec3 myColor;</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,
auxiliary qualification (e.g. <strong>centroid</strong>) may differ.
When
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,
attempting to use the two programs in the same program pipeline will result
in program pipeline validation failures, as described in section 7.4.1
&#8220;Shader Interface Matching&#8221; of the <a href="#references">OpenGL ES Specification</a>.</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 ES 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.</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.
Except for variables declared within a uniform block, all uniform variables
are initialized to 0 at link time and may be updated through the API.
When targeting Vulkan, it is an 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;</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
statically
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,
precisions,
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
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 class="paragraph">
<p>A compile or link-time error is generated if any of the explicitly given or
compiler generated uniform locations is greater than the
implementation-defined maximum number of uniform locations minus one.</p>
</div>
<div class="paragraph">
<p>Unlike locations for inputs and outputs, uniform locations are logical
values, not register locations, and there is no concept of overlap.
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>) uniform mat4 x;
layout(location = <span class="integer">3</span>) uniform mat4 y; <span class="comment">// No overlap with x</span>
layout(location = <span class="integer">2</span>) in mat4 x;
layout(location = <span class="integer">3</span>) in mat4 y; <span class="comment">// Error, locations conflict with x</span></code></pre>
</div>
</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>
<li>
<p>A structure containing an array</p>
</li>
<li>
<p>A structure containing a structure</p>
</li>
<li>
<p>For per-vertex-arrayed variables (applies to tessellation control,
tessellation evaluation and geometry shaders):</p>
<div class="ulist">
<ul>
<li>
<p>Per-vertex-arrayed arrays of arrays</p>
</li>
<li>
<p>Per-vertex-arrayed arrays of structures</p>
</li>
</ul>
</div>
</li>
<li>
<p>For non-per-vertex-arrayed variables:</p>
<div class="ulist">
<ul>
<li>
<p>An array of arrays</p>
</li>
<li>
<p>An array of structures</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Vertex shader outputs may be qualified with the interpolation qualifier
<strong>flat</strong><sup>1</sup>.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">1</dt>
<dd>
<p>Unlike previous versions of the OpenGL ES Shading Language, there is no requirement for
outputs containing integers to be qualified as <strong>flat</strong>, since the vertex
shader may interface with the tessellation control shader.
However, in all cases, the qualifier must match across interfaces.</p>
</dd>
</dl>
</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 an 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>An <a href="#opaque-types">opaque type</a></p>
</li>
<li>
<p>A matrix type</p>
</li>
<li>
<p>A structure</p>
</li>
<li>
<p>An array of arrays</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Fragment shader outputs declared as arrays may only be indexed by a constant
integral expression.</p>
</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.
Buffer variables cannot have initializers.</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>The terms <em>shader storage buffer (object)</em>, and <em>shader storage block</em> are
often used interchangeably.
The former generally refers to the underlying storage whereas the latter
refers only to the interface definition in the shader.
Similarly for <em>uniform buffer objects</em> and _uniform blocks.</p>
</div>
</td>
</tr>
</table>
</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 class="paragraph">
<p>Precision qualifiers for such variables need not match.</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 an 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 ES 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>Opaque types are not allowed</p>
</li>
<li>
<p>Structure definitions cannot be nested inside a block</p>
</li>
<li>
<p>Arrays of arrays of blocks are not allowed, except for the case in the
tessellation pipe where the declaration is a per-vertex-array of arrays
of blocks.</p>
</li>
</ul>
</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,
precision 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 an 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
as defined in &#8220;<a href="#matching-of-qualifiers">Matching of Qualifiers</a>&#8221;.
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;
<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></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.
All indices used to index a shader storage block array must be constant
integral expressions.
A uniform 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 ES 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 ES 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>).
See section 7.3.1 &#8220;Program Interfaces&#8221; of the <a href="#references">OpenGL ES Specification</a> for
details.</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</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.
As for other identifiers, they are case sensitive.</p>
</div>
<div class="paragraph">
<p>The set of allowed layout qualifiers depends on the shader, the interface
and the variable type as specified in the following sections.
For example, a sampler in the default uniform block in a fragment shader can
have <strong>location</strong> and <strong>binding</strong> layout qualifiers but no others.
Invalid use of layout qualifiers is an error.</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">Vulkan only</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">Vulkan only</p></td>
<td class="tableblock halign-center valign-middle"><p class="tableblock">Vulkan only</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></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<sup>1</sup></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"><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>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>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>
<td class="tableblock halign-left valign-middle"><p class="tableblock">fragment <strong>in</strong></p></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>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></p>
<p class="tableblock"> <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="2"><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>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>r32f</strong><br>
<strong>rgba8</strong><br>
<strong>rgba8_snorm</strong><br>
<strong>rgba32i</strong><br>
<strong>rgba16i</strong><br>
<strong>rgba8i</strong><br>
<strong>r32i</strong><br>
<strong>rgba32ui</strong><br>
<strong>rgba16ui</strong><br>
<strong>rgba8ui</strong><br>
<strong>r32ui</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>
<tr>
<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>blend_support_multiply</strong><br>
<strong>blend_support_screen</strong><br>
<strong>blend_support_overlay</strong><br>
<strong>blend_support_darken</strong><br>
<strong>blend_support_lighten</strong><br>
<strong>blend_support_colordodge blend_support_colorburn</strong><br>
<strong>blend_support_hardlight</strong><br>
<strong>blend_support_softlight</strong><br>
<strong>blend_support_difference</strong><br>
<strong>blend_support_exclusion</strong><br>
<strong>blend_support_hsl_hue</strong><br>
<strong>blend_support_hsl_saturation</strong><br>
<strong>blend_support_hsl_color blend_support_hsl_luminosity</strong><br>
<strong>blend_support_all_equations</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">fragment <strong>out</strong></p></td>
</tr>
</tbody>
</table>
<div class="dlist">
<dl>
<dt class="hdlist1">1</dt>
<dd>
<p>Location qualifiers are not allowed for members of an arrayed block,
except for per-vertex-arrays (see &#8220;<a href="#interface-blocks">Interface
Blocks</a>&#8221;).</p>
</dd>
</dl>
</div>
<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.</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>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;</code></pre>
</div>
</div>
<div class="paragraph">
<p>will establish that the shader input <em>normal</em> is assigned to vector location
number
3.
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>If a shader input is any scalar or vector type, it will consume a single
location.</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.</p>
</div>
<div class="paragraph">
<p>If an input is declared as an array of blocks, excluding per-vertex-arrays
as required for tessellation, it is an error to declare a member of the
block with a <strong>location</strong> qualifier.</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 ES 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 ES Specification</a> for
more details.</p>
</div>
<div class="paragraph">
<p>It is an error if more than one input or element of a matrix input is bound
to the same location.</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 ES 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.</p>
</div>
<div class="paragraph">
<p>The tessellation evaluation shader object in a program must declare a
primitive mode in its input layout.
Declaring vertex spacing, ordering, or point mode identifiers is optional.
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.
The geometry shader must declare this 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 the geometry shader, it 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>An input can be declared without an array size if there is a previous layout
which specifies the size.
For built-in inputs (e.g. <em>gl_in[]</em>), a layout must be declared before any
use.</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 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 in the geometry shader of a program.</p>
</div>
</div>
<div class="sect4">
<h5 id="fragment-shader-inputs">Fragment Shader Inputs</h5>
<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 13.8.4 &#8220;Early Fragment Tests&#8221; of the
<a href="#references">OpenGL ES 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.
In addition it is an error to statically write to <em>gl_FragDepth</em> in the
fragment shader.
If this is not declared, per-fragment tests will be performed after fragment
shader execution.</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.</p>
</div>
<div class="paragraph">
<p>Furthermore, if a program object contains a compute shader, that shader 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.</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 usage and rules for applying the <strong>location</strong> qualifier
to blocks and structures are exactly as described in
&#8220;<a href="#input-layout-qualifiers">Input Layout Qualifiers</a>&#8221;.</p>
</div>
<div class="paragraph">
<p>The qualifier may appear at most once within a declaration.
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</p>
</div>
<div class="paragraph">
<p>fragment color 3.</p>
</div>
<div class="paragraph">
<p>For fragment shader outputs, the location
specifies
the color output number
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>Declared outputs of scalar or vector type consume a single location.</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>If an output is declared as an array of blocks, excluding per-vertex-arrays
as required for tessellation, it is an error to declare a member of the
block with a <strong>location</strong> qualifier.</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 an error.</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.</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 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 has no location assigned in the shader text, it will
be assigned a location by the linker.
See section 11.1.3 &#8220;Shader Execution&#8221; of the <a href="#references">OpenGL ES Specification</a> for
more details.</p>
</div>
<div class="paragraph">
<p>If there is only a single output, the location does not need to be
specified, in which case it defaults to zero.
This applies for all output types, including arrays.
If there is more than one fragment output, the location must be specified
for all outputs.</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="tessellation-control-outputs">Tessellation Control Outputs</h5>
<div class="paragraph">
<p>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 a tessellation control shader.</p>
</div>
</div>
<div class="sect4">
<h5 id="geometry-outputs">Geometry Outputs</h5>
<div class="paragraph">
<p>Geometry shaders can have two additional types of output layout identifiers:
an output primitive type and a maximum output vertex count.
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.</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></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.
The geometry shader object 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.</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.
The geometry shader object 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.</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>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.</p>
</div>
</div>
<div class="sect4">
<h5 id="fragment-outputs">Fragment Outputs</h5>
<div class="paragraph">
<p>Fragment shaders can have an output layout for redeclaring the built-in
variable <em>gl_FragDepth</em>:</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;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The built-in <em>gl_FragDepth</em> is only predeclared in fragment shaders, so
redeclaring it in any other shader language results in an error.</p>
</div>
<div class="paragraph">
<p>Fragment shaders additionally support layout qualifiers specifying a set of
advanced blend equations supported when the fragment shader is used.
These layout qualifiers are only permitted on the interface qualifier <strong>out</strong>,
and use the identifiers specified in the &#8220;Layout Qualifier&#8221; column of the
table below.</p>
</div>
<div class="paragraph">
<p>If a layout qualifier in the table below is specified in the fragment
shader, the fragment shader may be used with the corresponding advanced
blend equation in the &#8220;Blend Equation(s) Supported&#8221; column.
Additionally, the special qualifier <strong>blend_support_all_equations</strong> indicates
that the shader may be used with any advanced blending equation supported by
the <a href="#references">OpenGL ES Specification</a>.
It is not an error to specify more than one of these identifiers in any
fragment shader.
Specifying more than one qualifier or <strong>blend_support_all_equations</strong> means
that the fragment shader may be used with multiple advanced blend equations.
Additionally, it is not an error to specify any single one of these layout
qualifiers more than once.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Layout Qualifier</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Blend Equations(s) Supported</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_multiply</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">MULTIPLY</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_screen</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SCREEN</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_overlay</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">OVERLAY</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_darken</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">DARKEN</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_lighten</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">LIGHTEN</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_colordodge</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">COLORDODGE</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_colorburn</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">COLORBURN</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_hardlight</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">HARDLIGHT</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_softlight</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">SOFTLIGHT</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_difference</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">DIFFERENCE</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_exclusion</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EXCLUSION</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_hsl_hue</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">HSL_HUE</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_hsl_saturation</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">HSL_SATURATION</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_hsl_color</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">HSL_COLOR</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_hsl_luminosity</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">HSL_LUMINOSITY</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>blend_support_all_equations</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">all blend equations</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect3">
<h4 id="uniform-variable-layout-qualifiers">4.4.3. Uniform Variable Layout Qualifiers</h4>
<div class="paragraph">
<p>The following layout qualifier can be used for all default-block uniform
variables but not for variables in uniform or shader storage blocks.
The layout qualifier identifier for uniform variables is:</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 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.
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.</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.
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 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 an 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="uniform-and-shader-storage-block-layout-qualifiers">4.4.4. 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> // Vulkan only<br>
<strong>align</strong> <strong>=</strong> <em>layout-qualifier-value</em> // Vulkan only</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 they also matched in their <strong>row_major</strong> and/or
<strong>column_major</strong> qualifications.
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
an 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 ES 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 an 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
(but not 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 ES,
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.</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 an 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 an 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 an 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 cannot be used with blocks or block members.</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.
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.5. 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 ES,
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.</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.6. 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>.</p>
</div>
</div>
<div class="sect3">
<h4 id="format-layout-qualifiers">4.4.7. 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>r32f</strong><br>
<strong>rgba8</strong><br>
<strong>rgba8_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>r32i</strong></p>
</dd>
<dt class="hdlist1"><em>uint-image-format-qualifier</em> : </dt>
<dd>
<p><strong>rgba32ui</strong><br>
<strong>rgba16ui</strong><br>
<strong>rgba8ui</strong><br>
<strong>r32ui</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 an 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 must specify 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.8. 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 an 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 an 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>
</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.</p>
</div>
<div class="paragraph">
<p>Interpolation in a perspective correct manner is specified in equations 13.4
of the <a href="#references">OpenGL ES Specification</a>, section 13.4.1 &#8220;Line Segments&#8221; and
equation 13.7, section 13.5.1 &#8220;Polygon Interpolation&#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 ES 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>
<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>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 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>
floating-point variables is defined by the IEEE 754 standard for
32-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>
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>Storage requirements are declared through use of <em>precision qualifiers</em>.
The precision of operations must preserve the storage precisions of the
variables involved.</p>
</div>
<div class="paragraph">
<p><strong>highp</strong> floating-point values are stored in IEEE 754 single precision
floating-point format.
<strong>mediump</strong> and <strong>lowp</strong> floating-point values have minimum range and precision
requirements as detailed below and have maximum range and precision as
defined by IEEE 754.</p>
</div>
<div class="paragraph">
<p>All integral types are assumed to be implemented as integers and so may not
be emulated by floating-point values.
<strong>highp</strong> signed integers are represented as twos-complement 32-bit signed
integers.
<strong>highp</strong> unsigned integers are represented as unsigned 32-bit integers.
<strong>mediump</strong> integers (signed and unsigned) must be represented as an integer
with between 16 and 32 bits inclusive.
<strong>lowp</strong> integers (signed and unsigned) must be represented as an integer with
between 9 and 32 bits inclusive.</p>
</div>
<div class="paragraph">
<p>The required ranges and precisions for precision qualifiers are:</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-top">Qualifier</th>
<th class="tableblock halign-left valign-top">Floating-Point Range</th>
<th class="tableblock halign-left valign-top">Floating-Point Magnitude Range</th>
<th class="tableblock halign-left valign-top">Floating-Point Precision</th>
<th class="tableblock halign-left valign-top">Signed Integer Range</th>
<th class="tableblock halign-left valign-top">Unsigned Integer Range</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">Subset of IEEE-754<br>
<span class="eq">(-2<sup>128</sup>,2<sup>128</sup>)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Subset of IEEE-754<br>
0.0, <span class="eq">[2<sup>-126</sup>,2<sup>128</sup>)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Subset of IEEE-754 relative:<br>
<span class="eq">2<sup>-23</sup></span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[-2<sup>31</sup>,2<sup>31</sup>-1]</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[0,2<sup>32</sup>-1]</span></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mediump</strong> (minimum requirements)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">(-2<sup>14</sup>,2<sup>14</sup>)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">0.0, <span class="eq">[2<sup>-14</sup>,2<sup>14</sup>)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Relative:<br>
<span class="eq">2<sup>-10</sup></span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[-2<sup>15</sup>,2<sup>15</sup>-1]</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[0,2<sup>16</sup>-1]</span></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lowp</strong> (minimum requirements)</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">(-2,2)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">(2<sup>-8</sup>,2)</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Absolute:<br>
<span class="eq">2<sup>-8</sup></span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[-2<sup>8</sup>,2<sup>8</sup>-1]</span></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><span class="eq">[0,2<sup>9</sup>-1]</span></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The semi-open interval notation used for the magnitude ranges means that the
lower end of the interval is included, but the upper end is excluded. Thus the
largest required magnitude is half of the relative precision less than the
value given. The largest required value for highp, for example, is <span class="eq">2<sup>128</sup>
× (1 - 2<sup>-24</sup>)</span>.</p>
</div>
<div class="paragraph">
<p><em>Relative precision</em> is defined as the worst case (i.e. largest) ratio of
the smallest step in relation to the value for all non-zero values in the
required ranges, above:</p>
</div>
<div class="stemblock">
<div class="content">
\[\begin{aligned}
\mathit{Precision}_{relative} = {
\left| {
{ \left| v_1 - v_2 \right| }_{min} } \over { v_1 }
\right|
}_{max}, &amp;
v_1,v_2 \neq 0, v_1 \neq v_2
\end{aligned}\]
</div>
</div>
<div class="paragraph">
<p>It is therefore twice the maximum rounding error when converting from a real
number.
Subnormal numbers may be supported and may have lower relative precision.</p>
</div>
<div class="paragraph">
<p>In addition, the range and precision of a <strong>mediump</strong> floating-point value
must be the same as or greater than the range and precision of a <strong>lowp</strong>
floating-point value.
The range and precision of a <strong>highp</strong> floating-point value must be the same
as or greater than the range and precision of a <strong>mediump</strong> floating-point
value.</p>
</div>
<div class="paragraph">
<p>The range of a <strong>mediump</strong> integer value must be the same as or greater than
the range of a <strong>lowp</strong> integer value.
The range of a <strong>highp</strong> integer value must be the same as or greater than the
range of a <strong>mediump</strong> integer value.</p>
</div>
<div class="paragraph">
<p>Within the above specification, an implementation is allowed to vary the
representation of numeric values, both within a shader and between different
shaders.
If necessary, this variance can be controlled using the invariance
qualifier.</p>
</div>
<div class="paragraph">
<p>The actual ranges and precisions provided by an implementation can be
queried through the API.
See the <a href="#references">normative references</a> for details on how to do
this.</p>
</div>
</div>
<div class="sect3">
<h4 id="conversion-between-precisions">4.7.2. Conversion between precisions</h4>
<div class="paragraph">
<p>Within the same type, conversion from a lower to a higher precision must be
exact.
When converting from a higher precision to a lower precision, if the value
is representable by the implementation of the target precision, the
conversion must also be exact.
If the value is not representable, the behavior is dependent on the type:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>For signed and unsigned integers, the value is truncated; bits in
positions not present in the target precision are set to zero.
(Positions start at zero and the least significant bit is considered to
be position zero for this purpose.)</p>
</li>
<li>
<p>For floating-point values, the value should either clamp to +Inf or
-Inf, or to the maximum or minimum value that the implementation
supports.
While this behavior is implementation-dependent, it should be consistent
for a given implementation.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="precision-qualifiers">4.7.3. Precision Qualifiers</h4>
<div class="paragraph">
<p>Any
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>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Qualifier</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Meaning</p></td>
</tr>
<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">The variable satisfies the minimum requirements for <strong>highp</strong>
described above. <strong>highp</strong> variables have the maximum range and
precision available but may cause operations to run more
slowly on some implementations.</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
the variable satisfies the minimum requirements for <strong>mediump</strong>
described above. <strong>mediump</strong> variables may typically be used to
store high dynamic range colors and low precision geometry.</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
the variable satisfies the minimum requirements for <strong>lowp</strong>
described above. <strong>lowp</strong> variables may typically be used to
store 8-bit color values.</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>Precision qualifiers for outputs in one shader matched to inputs in another
shader need not match when both shaders are linked into the same program.
When both shaders are in separate programs, mismatched precision qualifiers
will result in a program interface mismatch that will result in program
pipeline validation failures, as described in section 7.4.1 &#8220;Shader
Interface Matching&#8221; of the <a href="#references">OpenGL ES Specification</a>.</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.4. 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 an error.
If <em>type</em> is <strong>float</strong>, the directive applies to non-precision-qualified
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>All languages except for the fragment language have the following
predeclared globally scoped default precision statements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">precision highp <span class="predefined-type">float</span>;
precision highp <span class="predefined-type">int</span>;
precision lowp sampler2D;
precision lowp samplerCube;
precision highp atomic_uint;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The fragment language has the following predeclared globally scoped default
precision statements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">precision mediump <span class="predefined-type">int</span>;
precision lowp sampler2D;
precision lowp samplerCube;
precision highp atomic_uint;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The fragment language has no default precision qualifier for floating-point
types.
Hence for <strong>float</strong>, floating-point vector and matrix variable declarations,
either the declaration must include a precision qualifier or the default
float precision must have been previously declared.
Similarly, there is no default precision qualifier in any of the languages
for any type not listed above.</p>
</div>
</div>
<div class="sect3">
<h4 id="available-precision-qualifiers">4.7.5. 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>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 and the same constant 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-within-a-shader">4.8.2. Invariance Within a Shader</h4>
<div class="paragraph">
<p>When a value is stored in a variable, it is usually assumed it will remain
constant unless explicitly changed.
However, during the process of optimization, it is possible that the
compiler may choose to recompute a value rather than store it in a register.
Since the precision of operations is not completely specified (e.g. a low
precision operation may be done at medium or high precision), it would be
possible for the recomputed value to be different from the original value.</p>
</div>
<div class="paragraph">
<p>Values are allowed to be variant within a shader.
To prevent this, the invariant qualifier or invariant pragma must be used.</p>
</div>
<div class="paragraph">
<p>Within a shader, there is no invariance for values generated by different
non-constant expressions, even if those expressions are identical.</p>
</div>
<div class="paragraph">
<p>Example 1:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">precision mediump;
vec4 col;
vec2 a = ...
...
col = texture(tex, a);<span class="comment">// a has a value _a1 _</span>
...
col = texture(tex, a); <span class="comment">// a has a value a2 where possibly a1 != a2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>To enforce invariance in this example use:</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>Example 2:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec2 m = ...;
vec2 n = ...;
vec2 a = m + n;
vec2 b = m + n; <span class="comment">// a and b are not guaranteed to be exactly equal</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>There is no mechanism to enforce invariance between a and b.</p>
</div>
</div>
<div class="sect3">
<h4 id="invariance-of-constant-expressions">4.8.3. 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.
Constant expressions are not invariant with respect to equivalent
non-constant expressions, even when the <strong>invariant</strong> qualifier or pragma is
used.</p>
</div>
</div>
<div class="sect3">
<h4 id="invariance-of-undefined-values">4.8.4. Invariance of Undefined Values</h4>
<div class="paragraph">
<p>Undefined values are not invariant nor can they be made invariant by use of
the invariant qualifier or pragma.
In some implementations, undefined values may cause unexpected behavior if
they are used in control-flow expressions e.g. in the following case, one,
both or neither functions may be executed and this may not be consistent
over multiple invocations of the shader:</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="comment">// undefined value</span>
<span class="keyword">if</span> (x == <span class="integer">1</span>)
{
f(); <span class="comment">// Undefined whether f() is executed</span>
}
<span class="keyword">if</span> (x == <span class="integer">2</span>)
{
g(); <span class="comment">// Undefined whether g() is executed.</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that an undefined value is a value that has not been specified.
A value that has been specified but has a potentially large error due to,
for example, lack of precision in an expression, is not undefined and so can
be made invariant.</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>As stated in &#8220;<a href="#evaluation-of-expressions">Evaluation of Expressions</a>&#8221;,
the compiler may transform expressions even if this changes the resulting
value.
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.</p>
</div>
<div class="paragraph">
<p>As described in section
7.11
&#8220;Shader Memory Access&#8221; of the
<a href="#references">OpenGL ES 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 an 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 an 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>Except for image variables qualified with the format qualifiers <strong>r32f</strong>,
<strong>r32i</strong>, and <strong>r32ui</strong>, image variables must specify a memory qualifier
(<strong>readonly</strong>, <strong>writeonly</strong>, or both).</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.
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 ES 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 an 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>
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>
<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">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></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 an 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
an error to have any other arguments.</p>
</div>
<div class="paragraph">
<p>If the basic type (<strong>bool</strong>, <strong>int</strong>,
or <strong>float</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>
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></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.</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.</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 Components</h3>
<div class="paragraph">
<p>The names of the components of a vector
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.</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
an error so, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">vec2 pos;
pos.x <span class="comment">// is legal</span>
pos.z <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 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 an 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>Note that scalars are not considered to be single-component vectors and
therefore the use of component selection operators on scalars is illegal.</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 an error to access a matrix with a constant expression
that is outside the bounds of the matrix.</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
compile-time
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.
Any type-conversions must be specified explicitly via constructors.
It is an 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 an 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>Arrays with the length 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 operands are integral types, they must both be signed or both be
unsigned.
All arithmetic binary operators result in the same fundamental type
(signed integer, unsigned integer, or floating-point) as the operands
they operate on.
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 an 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.
The operand types must both be signed or both be unsigned.
The operands cannot be vectors of differing size; this is
an 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.
The types of the operands must match.
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.
They result in a scalar Boolean.
The types of the operands must match.
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 an error.
Otherwise,
the second and third expressions can be any type, including <strong>void</strong>, as
long 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 an 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.
The fundamental types of the operands (signed or unsigned) must match,
and 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="specialization-constant-operations">5.11. 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 class="sect2">
<h3 id="evaluation-of-expressions">5.12. Evaluation of Expressions</h3>
<div class="paragraph">
<p>In general expressions must be evaluated in the order specified by the
precedence of operations and may only be regrouped if the result is the same or
where the result is undefined.
No other transforms may be applied that affect the result of an operation.
GLSL ES relaxes these requirements for scalar operations in the following
ways:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Addition and multiplication are assumed to be associative.</p>
</li>
<li>
<p>Multiplication is assumed to be distributive over addition.
Therefore expressions may be expanded and re-factored.</p>
</li>
<li>
<p>Floating-point division may be replaced by reciprocal and
multiplication.</p>
</li>
<li>
<p>Multiplication may be replaced by repeated addition.</p>
</li>
<li>
<p>Within the constraints of invariance (where applicable), the precision
used may vary.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>These rules also apply to the built-in functions.</p>
</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 ES 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>Each of the <em>typeN</em> must include a type and can optionally include a
parameter qualifier and/or <strong>const</strong>.</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
compile-time
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.
When function calls are resolved, an exact type match for all the arguments
is required.</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);
vec4 f(in vec4 x, out uvec4 y); <span class="comment">// allowed, 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>Calling the first two functions above with the following argument types
yields</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(ivec4, vec4) <span class="comment">// error, no exact match.</span>
f(ivec4, uvec4) <span class="comment">// error, no exact match.</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 cannot redefine or overload built-in functions.</p>
</div>
<div class="paragraph">
<p>The function <em>main</em> is used as the entry point to a shader executable.
All shaders must define a function named <em>main</em>.
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>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 an error
results.</p>
</div>
<div class="paragraph">
<p>Only precision qualifiers are allowed on the return type of a function.</p>
</div>
<div class="paragraph">
<p>The syntax for function prototypes can be informally expressed as:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"><em>function_prototype</em> : </dt>
<dd>
<p>[ <em>type_qualifier</em> ] <em>type_specifier</em> <em>IDENTIFIER</em> <em>LEFT_PAREN</em>
<em>parameter_declaration</em> , <em>parameter_declaration</em> , &#8230;&#8203;
, <em>RIGHT_PAREN</em></p>
</dd>
<dt class="hdlist1"><em>parameter_declaration</em> : </dt>
<dd>
<p>[ <em>type_qualifier</em> ] <em>type_specifier</em> [ <em>IDENTIFIER</em> [ <em>array_specifier</em>
] ]</p>
</dd>
<dt class="hdlist1"><em>type_qualifier</em> : </dt>
<dd>
<p><em>single_type_qualifier</em> , <em>single_type_qualifier</em> , &#8230;&#8203;</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="paragraph">
<p>The qualifiers allowed on formal parameters are:</p>
</div>
<div class="openblock bnf">
<div class="content">
<div class="dlist">
<dl>
<dt class="hdlist1"></dt>
<dd>
<p><em>empty</em><br>
<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>
</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
an 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>Static, and hence dynamic recursion, are not allowed.
Static recursion is present if the static function-call graph of a program
contains cycles.
Dynamic recursion occurs if at any time control flow has entered but not
exited a single function more than once.</p>
</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 <em>init-expression</em> must match the type of the <strong>case</strong> labels
within each <strong>switch</strong> statement.
Either signed integers or unsigned integers are allowed but there is no
implicit type conversion between the two.
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 an 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 an 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>For both <strong>for</strong> and <strong>while</strong> loops, the sub-statement does not introduce a new
scope for variable names, so the following has a redeclaration error:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">for</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 <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 highp <span class="predefined-type">int</span> gl_VertexID; <span class="comment">// only present when not targeting Vulkan</span>
in highp <span class="predefined-type">int</span> gl_InstanceID; <span class="comment">// only present when not targeting Vulkan</span>
in highp <span class="predefined-type">int</span> gl_VertexIndex; <span class="comment">// only present when targeting Vulkan</span>
in highp <span class="predefined-type">int</span> gl_InstanceIndex; <span class="comment">// only present when targeting Vulkan</span>
out gl_PerVertex {
out highp vec4 gl_Position;
out highp <span class="predefined-type">float</span> gl_PointSize;
};</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_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 ES 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 ES 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>
<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 {
highp vec4 gl_Position;
} gl_in[gl_MaxPatchVertices];
in highp <span class="predefined-type">int</span> gl_PatchVerticesIn;
in highp <span class="predefined-type">int</span> gl_PrimitiveID;
in highp <span class="predefined-type">int</span> gl_InvocationID;
out gl_PerVertex {
highp vec4 gl_Position;
} gl_out[];
patch out highp <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>];
patch out highp <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>];
patch out highp vec4 gl_BoundingBox[<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> contains the output written in the previous shader stage to
<em>gl_Position</em>.</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> is used in the same fashion as the corresponding output
variable 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 class="paragraph">
<p>The values written to <em>gl_BoundingBox</em> specify the minimum and maximum
clip-space extents of a bounding box containing all primitives generated
from the patch by the primitive generator, geometry shader, and clipping.
Fragments may or may not be generated for portions of these primitives
that extend outside the window-coordinate projection of this bounding
box.</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 {
highp vec4 gl_Position;
} gl_in[gl_MaxPatchVertices];
in highp <span class="predefined-type">int</span> gl_PatchVerticesIn;
in highp <span class="predefined-type">int</span> gl_PrimitiveID;
in highp vec3 gl_TessCoord;
patch in highp <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>];
patch in highp <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>];
out gl_PerVertex {
highp vec4 gl_Position;
};</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> contains the output written in the previous shader stage to
<em>gl_Position</em>.</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><em>gl_TessLevelOuter</em> and <em>gl_TessLevelInner</em> are filled with the
corresponding outputs written by the active tessellation control shader.</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> is used in the same fashion as the corresponding output
variable 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 {
highp vec4 gl_Position;
} gl_in[];
in highp <span class="predefined-type">int</span> gl_PrimitiveIDIn;
in highp <span class="predefined-type">int</span> gl_InvocationID;
out gl_PerVertex {
highp vec4 gl_Position;
};
out highp <span class="predefined-type">int</span> gl_PrimitiveID;
out highp <span class="predefined-type">int</span> gl_Layer;</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> contains the output written in the previous shader stage to
<em>gl_Position</em>.</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> is used in the same fashion as the corresponding output
variable 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.4 &#8220;Geometry Shader Outputs&#8221; of the
<a href="#references">OpenGL ES 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.4 of the <a href="#references">OpenGL ES 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.4 &#8220;Geometry Shader Outputs&#8221; and section 9.8 &#8220;Layered
Framebuffers&#8221; of the <a href="#references">OpenGL ES 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 8.25 of the <a href="#references">OpenGL ES 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>
</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 highp vec4 gl_FragCoord;
in <span class="predefined-type">bool</span> gl_FrontFacing;
out highp <span class="predefined-type">float</span> gl_FragDepth;
in mediump vec2 gl_PointCoord;
in <span class="predefined-type">bool</span> gl_HelperInvocation;
in highp <span class="predefined-type">int</span> gl_PrimitiveID;
in highp <span class="predefined-type">int</span> gl_Layer;
in lowp <span class="predefined-type">int</span> gl_SampleID;
in mediump vec2 gl_SamplePosition;
in highp <span class="predefined-type">int</span> gl_SampleMaskIn[(gl_MaxSamples+<span class="integer">31</span>)/<span class="integer">32</span>];
out highp <span class="predefined-type">int</span> gl_SampleMask[(gl_MaxSamples+<span class="integer">31</span>)/<span class="integer">32</span>];</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>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>
<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>
<div class="sect2">
<h3 id="built-in-constants">7.2. 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> mediump <span class="predefined-type">int</span> gl_MaxVertexAttribs = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexUniformVectors = <span class="integer">256</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexOutputVectors = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxVertexAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlInputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlOutputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlTotalOutputComponents = <span class="integer">2048</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessPatchComponents = <span class="integer">120</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxPatchVertices = <span class="integer">32</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessGenLevel = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationInputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationOutputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryInputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryOutputComponents = <span class="integer">64</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryImageUniforms = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryOutputVertices = <span class="integer">256</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryTotalOutputComponents = <span class="integer">1024</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounters = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounterBuffers = <span class="integer">0</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxFragmentInputVectors = <span class="integer">15</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxFragmentImageUniforms = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxFragmentUniformVectors = <span class="integer">256</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounterBuffers = <span class="integer">1</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxDrawBuffers = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MinProgramTexelOffset = -<span class="integer">8</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxProgramTexelOffset = <span class="integer">7</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxImageUnits = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxSamples = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxComputeImageUniforms = <span class="integer">4</span>;
<span class="directive">const</span> highp ivec3 gl_MaxComputeWorkGroupCount = ivec3(<span class="integer">65535</span>, <span class="integer">65535</span>, <span class="integer">65535</span>);
<span class="directive">const</span> highp ivec3 gl_MaxComputeWorkGroupSize = ivec3(<span class="integer">128</span>, <span class="integer">128</span>, <span class="integer">64</span>);
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxComputeUniformComponents = <span class="integer">1024</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxComputeTextureImageUnits = <span class="integer">16</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxComputeAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxComputeAtomicCounterBuffers = <span class="integer">1</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxCombinedTextureImageUnits = <span class="integer">96</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxCombinedImageUniforms = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxCombinedShaderOutputResources = <span class="integer">4</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounters = <span class="integer">8</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounterBuffers = <span class="integer">1</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxAtomicCounterBindings = <span class="integer">1</span>;
<span class="directive">const</span> mediump <span class="predefined-type">int</span> gl_MaxAtomicCounterBufferSize = <span class="integer">32</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>
<div class="sect2">
<h3 id="built-in-uniform-state">7.3. 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 ES processing state, the following
uniform variables are built into the OpenGL ES 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 12.5.1 &quot;Controlling the Viewport&quot; in the</span>
<span class="comment">// OpenGL ES Specification.</span>
<span class="comment">//</span>
<span class="keyword">struct</span> gl_DepthRangeParameters {
highp <span class="predefined-type">float</span> near; <span class="comment">// n</span>
highp <span class="predefined-type">float</span> far; <span class="comment">// f</span>
highp <span class="predefined-type">float</span> diff; <span class="comment">// f - n</span>
};
uniform gl_DepthRangeParameters gl_DepthRange;
uniform lowp <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>
<div class="sect2">
<h3 id="redeclaring-built-in-blocks">7.4. 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.</p>
</div>
<div class="paragraph">
<p>If the <em>gl_PerVertex</em> block is not redefined in a given program, the
intrinsically declared definition of that block is used for the program
interface.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex {
highp vec4 gl_Position; <span class="comment">// will use gl_Position</span>
highp 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 and
interpolation qualifiers.</p>
</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 ES 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>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.
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.</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>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>)</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>)</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>)</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>)</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>)</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>)</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>)</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>)</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>)</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></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>.
If <em>x</em> has the value +/- Inf, the return value should be NaN and must
be either NaN or 0.0.
For <strong>highp</strong> non-constant expressions, the value returned must be
consistent.</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>
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>
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>
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></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>
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>)</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></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>)</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>)</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 an Inf or NaN is passed in, it will not signal, and the resulting
floating-point value is unspecified.
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></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>)</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></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, the value returned is undefined.
If <em>exp</em> is less than -126, 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>
highp uint <strong>packUnorm4x8</strong>(vec4 <em>v</em>)<br>
highp 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">highp vec2 <strong>unpackUnorm2x16</strong>(highp uint <em>p</em>)<br>
highp vec2 <strong>unpackSnorm2x16</strong>(highp uint <em>p</em>)<br>
mediump vec4 <strong>unpackUnorm4x8</strong>(highp uint <em>p</em>)<br>
mediump 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">highp 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">mediump vec2 <strong>unpackHalf2x16</strong>(highp 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>
</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>)</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>)</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>)</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>)</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>)</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">genFType <strong>faceforward</strong>(genFType <em>N</em>, genFType <em>I</em>, genFType <em>Nref</em>)<br></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>)</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></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</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">lowp genIType <strong>bitCount</strong>(genIType <em>value</em>)<br>
lowp 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">lowp genIType <strong>findLSB</strong>(genIType <em>value</em>)<br>
lowp 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">lowp genIType <strong>findMSB</strong>(highp genIType <em>value</em>)<br>
lowp 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
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.20
&#8220;Texture Comparison Modes&#8221; of the
<a href="#references">OpenGL ES 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
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 ES 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>
<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 ivec2 <strong>textureSize</strong>(gsampler2D <em>sampler</em>, int <em>lod</em>)<br>
highp ivec3 <strong>textureSize</strong>(gsampler3D <em>sampler</em>, int <em>lod</em>)<br>
highp ivec2 <strong>textureSize</strong>(gsamplerCube <em>sampler</em>, int <em>lod</em>)<br>
highp ivec2 <strong>textureSize</strong>(sampler2DShadow <em>sampler</em>, int <em>lod</em>)<br>
highp ivec2 <strong>textureSize</strong>(samplerCubeShadow <em>sampler</em>, int <em>lod</em>)
highp ivec3 <strong>textureSize</strong>(gsamplerCubeArray <em>sampler</em>, int <em>lod</em>)<br>
highp ivec3 <strong>textureSize</strong>(samplerCubeArrayShadow <em>sampler</em>, int <em>lod</em>)<br>
highp ivec3 <strong>textureSize</strong>(gsampler2DArray <em>sampler</em>, int <em>lod</em>)<br>
highp ivec3 <strong>textureSize</strong>(sampler2DArrayShadow <em>sampler</em>, int <em>lod</em>)<br>
highp int <strong>textureSize</strong>(gsamplerBuffer <em>sampler</em>)<br>
highp ivec2 <strong>textureSize</strong>(gsampler2DMS <em>sampler</em>)<br>
highp 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 ES 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>
</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>(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>(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>
float <strong>texture</strong>(sampler2DArrayShadow <em>sampler</em>, vec4 <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>.</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>(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>(sampler2DShadow <em>sampler</em>, vec4 <em>P</em> [, float <em>bias</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>(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>
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 ES 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>(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>(gsampler2DArray <em>sampler</em>, vec3 <em>P</em>, ivec2 <em>offset</em> [, float <em>bias</em>] )<br></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 ES 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>(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>(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 ES Specification</a>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">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>(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>(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>
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>(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>(sampler2DShadow <em>sampler</em>, vec3 <em>P</em>, float <em>lod</em>, ivec2 <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></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>(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>(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>(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>(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>(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>
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>(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>
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>
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>(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>
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>(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>
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; = \frac{\partial{P.s}}{\partial{x}} \\[0.8em]
\frac{\partial{s}}{\partial{y}} &amp; = \frac{\partial{P.s}}{\partial{y}} \\[0.8em]
\frac{\partial{t}}{\partial{x}} &amp; = \frac{\partial{P.t}}{\partial{x}} \\[0.8em]
\frac{\partial{t}}{\partial{y}} &amp; = \frac{\partial{P.t}}{\partial{y}} \\[0.8em]
\frac{\partial{r}}{\partial{x}} &amp; =
\begin{cases}
0.0, &amp; \text{for 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 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 ES 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 ES 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>The selected component is identified by the optional <em>comp</em> argument, where
the values zero, one, two, and three identify the <em>R<sub>s</sub></em>, <em>G<sub>s</sub></em>, <em>B<sub>s</sub></em>, or
<em>A<sub>s</sub></em> component, respectively.
If <em>comp</em> is omitted, it is treated as identifying the <em>R<sub>s</sub></em> component.</p>
</div>
<div class="paragraph">
<p>Incomplete textures (see section 8.16 &#8220;Texture Completeness&#8221; of the
<a href="#references">OpenGL ES Specification</a>) return a texture source color of (0,0,0,1) for all
four source texels.</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>
<div class="paragraph">
<p>The <strong>textureGatherOffset</strong> built-in functions from the OpenGL ES Shading Language return a vector
derived from sampling four texels in the image array of level <em>level<sub>base</sub></em>.
For each of the four texel offsets specified by the <em>offsets</em> argument, the
rules for the LINEAR minification filter are applied to identify a 2 ×
2 texel footprint, from which the single texel T<sub>i0j0</sub> is selected.
A four-component vector is then assembled by taking a single component from
each of the four T<sub>i0j0</sub> texels in the same manner as for the
<strong>textureGather</strong> function.</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>
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></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></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></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>
<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>
</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>.
The coordinates
are used to select an individual texel in the manner described in section
8.22
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL ES 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
18
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>
</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>
specify the individual texel to operate on.
The method for identifying the individual texel operated on from <em>image</em>,
<em>P</em>,
and the method for reading and writing the texel are specified in section
8.22
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL ES 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">highp ivec2 <strong>imageSize</strong>(readonly writeonly gimage2D <em>image</em>)<br>
highp ivec3 <strong>imageSize</strong>(readonly writeonly gimage3D <em>image</em>)<br>
highp ivec2 <strong>imageSize</strong>(readonly writeonly gimageCube <em>image</em>)<br>
highp ivec3 <strong>imageSize</strong>(readonly writeonly gimageCubeArray <em>image</em>)<br>
highp ivec3 <strong>imageSize</strong>(readonly writeonly gimage2DArray <em>image</em>)<br>
highp 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">highp 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>).
When <em>image</em> and <em>P</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.23
&#8220;Texture Image Loads and Stores&#8221; of the
<a href="#references">OpenGL ES 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>.
When <em>image</em> and <em>P</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.23
&#8220;Texture Image Loads and Stores&#8221; of the <a href="#references">OpenGL ES Specification</a>
and stored to the specified texel.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">highp uint <strong>imageAtomicAdd</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicMin</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicMax</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicAnd</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicOr</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicXor</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicExchange</strong>(<em>IMAGE_PARAMS</em>, uint <em>data</em>)<br>
highp int <strong>imageAtomicExchange</strong>(<em>IMAGE_PARAMS</em>, int <em>data</em>)<br>
highp 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">highp uint <strong>imageAtomicCompSwap</strong>(<em>IMAGE_PARAMS</em>, uint <em>compare</em>, uint <em>data</em>)<br>
highp 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>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.
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.
No vertex is emitted.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The function <strong>EmitVertex</strong>() specifies that a vertex is completed.
A vertex is added to the current output primitive using the current values
of all built-in and user-defined output variables.
The values of all output variables are undefined after a call to
<strong>EmitVertex</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>EmitVertex</strong>() are undefined.</p>
</div>
<div class="paragraph">
<p>The function <strong>EndPrimitive</strong>() specifies that the current output primitive is
completed and a new output primitive (of the same type) will be started by
any subsequent <strong>EmitVertex</strong>().
This function does not emit a vertex.
If the output layout is declared to be <strong>points</strong>, calling <strong>EndPrimitive</strong>() is
optional.</p>
</div>
<div class="paragraph">
<p>A geometry shader starts with an output primitive containing no vertices.
When a geometry shader terminates, the current output primitive is
automatically completed.
It is not necessary to call <strong>EndPrimitive</strong>() if the geometry shader writes
only a single primitive.</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>An implementation may use the above or other methods to perform
the calculation, subject to the following conditions:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>The method may use piecewise linear approximations.
Such linear approximations imply that higher order derivatives,
<strong>dFdx</strong>(<strong>dFdx</strong>(<em>x</em>)) and above, are undefined.</p>
</li>
<li>
<p>The method may assume that the function evaluated is continuous.
Therefore derivatives within the body of a non-uniform conditional are
undefined.</p>
</li>
<li>
<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 13.2 &#8220;Invariance&#8221; of
the <a href="#references">OpenGL ES Specification</a>, is relaxed for derivative calculations,
because the method may be a function of fragment location.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Other properties that are desirable, but not required, are:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Functions should be evaluated within the interior of a primitive
(interpolated, not extrapolated).</p>
</li>
<li>
<p>Functions for <strong>dFdx</strong> should be evaluated while holding <em>y</em> constant.
Functions for <strong>dFdy</strong> should be evaluated while holding <em>x</em> constant.
However, mixed higher order derivatives, like <strong>dFdx</strong>(<strong>dFdy</strong>(<em>y</em>)) and
<strong>dFdy</strong>(<strong>dFdx</strong>(<em>x</em>)) are undefined.</p>
</li>
<li>
<p>Derivatives of constant arguments should be 0.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>In some implementations, varying degrees of derivative accuracy may be
obtained by providing GL hints (see section 19.1 &#8220;Hints&#8221; of the
<a href="#references">OpenGL ES Specification</a>), allowing a user to make an image quality versus
speed trade off.</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 the derivative in x using local differencing for the input
argument <em>p</em>.</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 the derivative in y using local differencing for the input
argument <em>p</em>.<br>
<br>
These two functions are commonly used to estimate the filter width used
to anti-alias procedural textures. We are assuming that the expression
is being evaluated in parallel on a SIMD array so that at any given
point in time the value of the function is known at the grid points
represented by the SIMD array. Local differencing between SIMD array
elements can therefore be used to derive <strong>dFdx</strong>, <strong>dFdy</strong>, etc.</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 the sum of the absolute derivative in x and y using local
differencing for the input argument <em>p</em>, i.e., <strong>abs</strong>(<strong>dFdx</strong>(<em>p</em>))
+ <strong>abs</strong>(<strong>dFdy</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.
For the <strong>interpolateAt*</strong> functions, the call will return a precision
qualification matching the precision of the <em>interpolant</em> argument to the
function call.</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 be either a variable, or an array element.
Component selection operators (e.g. <strong>.xy</strong>) may not be used when specifying <em>interpolant</em>.</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.</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="shader-invocation-control-functions">8.15. 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.16. 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.17. 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>
</div>
<div class="sect1">
<h2 id="shader-interface-matching">9. Shader Interface Matching</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As described in chapter 7 of the <a href="#references">OpenGL ES Specification</a>, shaders may be
linked together to form a <em>program object</em> before being bound to the
pipeline or may be linked and bound individually as <em>separable program
objects</em>.</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>These were previously known as separate shader objects (SSOs) but the
mechanism has been extended to support future versions of the specification
that have more than two shader stages.
It allows a subset of the shaders to be linked together.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Within a <em>program object</em> or a <em>separable program object</em>, qualifiers for
matching variables must themselves match according to the rules specified in
this section.
There are also matching rules for qualifiers of matching variables between
separable program objects but only for variables across an input/output
boundary between shader stages.
For other shader interface variables such as uniforms, each program object
or separable program object has its own name space and so the same name can
refer to multiple independent variables.
Consequently, there are no matching rules for qualifiers in these cases.</p>
</div>
<div class="sect2">
<h3 id="input-output-matching-by-name-in-linked-programs">9.1. Input Output Matching by Name in Linked Programs</h3>
<div class="paragraph">
<p>When linking shaders, the type of declared vertex outputs and fragment
inputs with the same name must match, otherwise the link command will fail.
Only those fragment inputs statically used (i.e. read) in the fragment
shader must be declared as outputs in the vertex shader; declaring
superfluous vertex shader outputs is permissible.</p>
</div>
<div class="paragraph">
<p>The following table summarizes the rules for matching shader outputs to
shader inputs in consecutive stages when shaders are linked together.</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">error</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Declares; 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">Declares 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>See &#8220;<a href="#static-use">Static Use</a>&#8221; for the definition of <em>static use</em>.</p>
</div>
<div class="paragraph">
<p>The precision of a vertex output does not need to match the precision of the
corresponding fragment input.
The minimum precision at which vertex outputs are interpolated is the
minimum of the vertex output precision and the fragment input precision,
with the exception that for <strong>highp</strong>, implementations do not have to support
full IEEE 754 precision.</p>
</div>
<div class="paragraph">
<p>The precision of values exported to a transform feedback buffer is the
precision of the outputs of the vertex shader.
However, they are converted to <strong>highp</strong> format before being written.</p>
</div>
</div>
<div class="sect2">
<h3 id="matching-of-qualifiers">9.2. Matching of Qualifiers</h3>
<div class="paragraph">
<p>The following tables summarize the requirements for matching of qualifiers.
It applies whenever there are two or more matching variables in a shader
interface.</p>
</div>
<div class="paragraph">
<p>Notes:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><em>Yes</em> means the qualifiers must match.</p>
</li>
<li>
<p><em>No</em> means the qualifiers do not need to match.</p>
</li>
<li>
<p><em>Consistent</em> means qualifiers may be missing from a subset of
declarations but they cannot conflict</p>
</li>
<li>
<p>If there are conflicting qualifiers, only the last of these is
significant.</p>
</li>
<li>
<p>Matching is based only on the resulting qualification, not on the
presence or otherwise of qualifiers.</p>
</li>
<li>
<p>The rules apply to all declared variables, irrespective of whether they
are statically used, with the exception of inputs and outputs when
shaders are linked (see
&#8220;<a href="#input-output-matching-by-name-in-linked-programs">Input Output
Matching by Name in Linked Programs</a>&#8221;).</p>
</li>
<li>
<p>Errors are generated for any conflicts.</p>
</li>
</ol>
</div>
<div class="sect3">
<h4 id="linked-shaders">9.2.1. Linked Shaders</h4>
<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-top">Qualifier Class</th>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top"><strong>in</strong>/<strong>out</strong></th>
<th class="tableblock halign-left valign-top">Default Uniforms</th>
<th class="tableblock halign-left valign-top"><strong>uniform</strong> Block</th>
<th class="tableblock halign-left valign-top"><strong>buffer</strong> Block</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Storage<sup>1</sup></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong><br>
<strong>out</strong><br>
<strong>uniform</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Auxiliary</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>centroid</strong><br>
<strong>sample</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</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">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top" rowspan="5"><p class="tableblock">Layout</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>location</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes<sup>2</sup></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Consistent</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Block layout<sup>3,4</sup></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>binding</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Consistent</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>offset</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">format</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Interpolation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>smooth</strong><br>
<strong>flat</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Precision</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lowp</strong><br>
<strong>mediump</strong><br>
<strong>highp</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Variance</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>invariant</strong><br>
<strong>precise</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Memory</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">all</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
</tbody>
</table>
<div class="dlist">
<dl>
<dt class="hdlist1">1</dt>
<dd>
<p>Storage qualifiers determine <em>when</em> variables match rather than being
<em>required</em> to match for matching variables.
Note also that each shader interface has a separate name space so for
example, it is possible to use the same name for a vertex output and
fragment uniform.</p>
</dd>
<dt class="hdlist1">2</dt>
<dd>
<p>If present, the <strong>location</strong> qualifier determines the matching of inputs
and outputs.
See section 7.4.1 &#8220;Shader interface Matching&#8221; of the
<a href="#references">OpenGL ES Specification</a> for details.]</p>
</dd>
<dt class="hdlist1">3</dt>
<dd>
<p>The <strong>row_major</strong> and <strong>column_major</strong> layout qualifiers do not need to
match when applied to non-matrix types.</p>
</dd>
<dt class="hdlist1">4</dt>
<dd>
<p>In cases where a layout qualifier overrides a previous layout qualifier
or a default, only the resulting qualification must match.</p>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="separable-programs">9.2.2. Separable Programs</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Qualifier Class</th>
<th class="tableblock halign-left valign-top">Qualifier</th>
<th class="tableblock halign-left valign-top"><strong>in</strong>/<strong>out</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Storage</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong><br>
<strong>out</strong><br>
<strong>uniform</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top" rowspan="2"><p class="tableblock">Auxiliary</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>centroid</strong><br>
<strong>sample</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</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">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top" rowspan="5"><p class="tableblock">Layout</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>location</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Block layout</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>binding</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>offset</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">format</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Interpolation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>smooth</strong><br>
<strong>flat</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Precision</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lowp</strong><br>
<strong>mediump</strong><br>
<strong>highp</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Yes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Variance</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>invariant</strong><br>
<strong>precise</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">No</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Memory</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">all</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">N/A</p></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="shading-language-grammar">10. 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</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>CENTROID IN OUT INOUT UNIFORM PATCH SAMPLE BUFFER SHARED
COHERENT VOLATILE RESTRICT READONLY WRITEONLY
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>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>STRUCT VOID</p>
</div>
<div class="paragraph">
<p>WHILE BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT</p>
</div>
<div class="paragraph">
<p>IDENTIFIER TYPE_NAME
FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
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 ES Shading Language in terms of the above
tokens.
The starting rule is <em>translation_unit</em>.</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>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>) 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></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>INTCONSTANT</em><br>
<em>IDENTIFIER</em> <em>EQUAL</em> <em>UINTCONSTANT</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></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>INT</em><br>
<em>UINT</em><br>
<em>BOOL</em><br>
<em>VEC2</em><br>
<em>VEC3</em><br>
<em>VEC4</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>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>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>IMAGE2DARRAY</em><br>
<em>IIMAGE2DARRAY</em><br>
<em>UIMAGE2DARRAY</em><br>
<em>IMAGECUBEARRAY</em><br>
<em>IIMAGECUBEARRAY</em><br>
<em>UIMAGECUBEARRAY</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></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></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 ES 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="counting-of-inputs-and-outputs">11. Counting of Inputs and Outputs</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This section applies to outputs from the last active vertex processing stage
and inputs to the fragment stage.
GLSL ES 3.20 specifies the storage available for such variables in terms of
an array of 4-vectors.
The assumption is that variables will be packed into these arrays without
wasting space.
This places significant burden on implementations since optimal packing is
computationally intensive.
Implementations may have more internal resources than exposed to the
application and so avoid the need to perform packing but this is also
considered an expensive solution.</p>
</div>
<div class="paragraph">
<p>GLSL ES 3.20 therefore relaxes the requirements for packing by
specifying a simpler algorithm that may be used.
This algorithm specifies a minimum requirement for when a set of variables
must be supported by an implementation.
The implementation is allowed to support more than the minimum and so may
use a more efficient algorithm and/or may support more registers than the
virtual target machine.</p>
</div>
<div class="paragraph">
<p>Outputs from the last active vertex stage and inputs to the fragment stage are
counted separately.
If statically used in the fragment shader, the built-in special variables
(<em>gl_FragCoord</em>, <em>gl_FrontFacing</em> and <em>gl_PointCoord</em>) are included when
calculating the storage requirements of fragment inputs.</p>
</div>
<div class="paragraph">
<p>If the last active vertex-pipeline shader and fragment shader are linked
together, inputs and outputs are only counted if they are statically used
within the shader.
If the shaders are each compiled into a separable program, all declared inputs
and outputs are counted.</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>GLSL ES 3.20 does not require the implementation to remove
outputs which are not statically used in the fragment shader.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For the algorithm used, failing resource allocation for a variable must
result in an error.</p>
</div>
<div class="paragraph">
<p>The resource allocation of variables must succeed for all cases where the
following packing algorithm succeeds:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The target architecture consists of a grid of registers, 16 rows by 4
columns.
Each register can contain a scalar value, i.e. a float, int or uint.</p>
</li>
<li>
<p>Variables with an explicit location are allocated first.
When attempting to allocate a location for other variables, if there is
a conflict, the search moves to the next available free location.</p>
</li>
<li>
<p>Structures are assumed to be flattened.
Each data member is treated as if it were at global scope.</p>
</li>
<li>
<p>Variables are packed into the registers one at a time so that they each
occupy a contiguous sub-rectangle.
No splitting of variables is permitted.</p>
</li>
<li>
<p>The orientation of variables is fixed.
Vectors always occupy registers in a single row.
Elements of an array must be in different rows.
E.g. <strong>vec4</strong> will always occupy one row; float[16] will occupy one
column.
Since it is not permitted to split a variable, large arrays e.g.
float[32] will always fail with this algorithm.</p>
</li>
<li>
<p>Non-square matrices of type <strong>matCxR</strong> consume the same space as a square
matrix of type <strong>matN</strong> where N is the greater of C and R.
Variables of type <strong>mat2</strong> occupies 2 complete rows.
These rules allow implementations more flexibility in how variables are
stored.
+ Other variables consume only the minimum space required.</p>
</li>
<li>
<p>Arrays of size N are assumed to take N times the size of the base type.</p>
</li>
<li>
<p>Variables are packed in the following order:</p>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>mat4</strong> and arrays of <strong>mat4</strong>.</p>
</li>
<li>
<p><strong>mat2</strong> and arrays of <strong>mat2</strong> (since they occupy full rows)</p>
</li>
<li>
<p><strong>vec4</strong> and arrays of <strong>vec4</strong></p>
</li>
<li>
<p><strong>mat3</strong> and arrays of <strong>mat3</strong></p>
</li>
<li>
<p><strong>vec3</strong> and arrays of <strong>vec3</strong></p>
</li>
<li>
<p><strong>vec2</strong> and arrays of <strong>vec2</strong></p>
</li>
<li>
<p>Scalar types and arrays of scalar types</p>
</li>
</ol>
</div>
</li>
<li>
<p>For each of the above types, the arrays are processed in order of size,
largest first.
Arrays of size 1 and the base type are considered equivalent.
The first type to be packed will be mat4[4], mat4[3], mat[2] followed by
mat4, mat2[4]&#8230;&#8203;mat2[2], mat2, vec4[8], vec4[7],&#8230;&#8203;vec4[1], vec4,
mat3[2], mat3 and so on.
The last variables to be packed will be float (and float[1]).</p>
</li>
<li>
<p>For 2,3 and 4 component variables packing is started using the 1<sup>st</sup>
column of the 1<sup>st</sup> row.
Variables are then allocated to successive rows, aligning them to the
1<sup>st</sup> column.</p>
</li>
<li>
<p>For 2 component variables, when there are no spare rows, the strategy is
switched to using the highest numbered row and the lowest numbered
column where the variable will fit.
(In practice, this means they will be aligned to the x or z component.)
Packing of any further 3 or 4 component variables will fail at this
point.</p>
</li>
<li>
<p>1 component variables (e.g. floats and arrays of floats) have their own
packing rule.
They are packed in order of size, largest first.
Each variable is placed in the column that leaves the least amount of
space in the column and aligned to the lowest available rows within that
column.
During this phase of packing, space will be available in up to 4
columns.
The space within each column is always contiguous in the case where no
variables have explicit locations.</p>
</li>
<li>
<p>For each type, variables with the 'smooth' property are packed first,
followed by variables with the 'flat' property.</p>
</li>
<li>
<p>Each row can contain either values with the 'smooth' property or the
'flat' property but not both.
If this situation is encountered during allocation, the algorithm skips
the component location and continues with the next available location.
These skipped locations may be used for other values later in the
allocation process.</p>
</li>
<li>
<p>There is no backtracking.
Once a value is assigned a location, it cannot be changed, even if such
a change is required for a successful allocation.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Example: pack the following types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++">out vec4 a; <span class="comment">// top left</span>
out mat3 b; <span class="comment">// align to left, lowest numbered rows</span>
out mat2x3 c; <span class="comment">// same size as mat3, align to left</span>
out vec2 d[<span class="integer">6</span>]; <span class="comment">// align to left, lowest numbered rows</span>
out vec2 e[<span class="integer">4</span>]; <span class="comment">// Cannot align to left so align to z column, highest</span>
<span class="comment">// numbered rows</span>
out vec2 f; <span class="comment">// Align to left, lowest numbered rows.</span>
out <span class="predefined-type">float</span> g[<span class="integer">3</span>] <span class="comment">// Column with minimum space</span>
out <span class="predefined-type">float</span> h[<span class="integer">2</span>]; <span class="comment">// Column with minimum space (choice of 3, any</span>
<span class="comment">// can be used)</span>
out <span class="predefined-type">float</span> i; <span class="comment">// Column with minimum space</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In this example, the variables happen to be listed in the order in which
they are packed.
Packing is independent of the order of declaration.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>x</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>y</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>z</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>w</strong></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>a</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>a</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>a</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>a</strong></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"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>b</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>c</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>g</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>g</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>g</strong></p></td>
<td class="tableblock halign-left valign-top"></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"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></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">11</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></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">12</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>d</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></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"><strong>f</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>f</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></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"><strong>h</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>i</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></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"><strong>h</strong></p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><strong>e</strong></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Some types e.g. mat4[8] will be too large to fit.
These always fail with this algorithm.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="acknowledgments">12. 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>Acorn Pooley, NVIDIA<br>
Alberto Moreira, Qualcomm<br>
Aleksandra Krstic, Qualcomm<br>
Alon Or-bach, Nokia &amp; Samsung<br>
Andrzej Kacprowski, Intel<br>
Arzhange Safdarzadeh, Intel<br>
Aske Simon Christensen, ARM<br>
Avi Shapira, Graphic Remedy<br>
Barthold Lichtenbelt, NVIDIA<br>
Ben Bowman, Imagination Technologies<br>
Ben Brierton, Broadcom<br>
Benj Lipchak, Apple<br>
Benson Tao, Vivante<br>
Bill Licea-Kane, Qualcomm<br>
Brent Insko, Intel<br>
Brian Murray, Freescale<br>
Bruce Merry, ARM<br>
Carlos Santa, TI<br>
Cass Everitt, Epic Games &amp; NVIDIA<br>
Cemil Azizoglu, TI<br>
Chang-Hyo Yu, Samsung<br>
Chris Dodd, NVIDIA<br>
Chris Knox, NVIDIA<br>
Chris Tserng, TI<br>
Clay Montgomery, TI<br>
Daniel Kartch, NVIDIA<br>
Daniel Koch, Transgaming&amp; NVIDIA<br>
Daoxiang Gong, Imagination Technologies<br>
Dave Shreiner, ARM<br>
David Garcia, AMD<br>
David Jarmon, Vivante<br>
Derek Cornish, Epic Games<br>
Dominick Witczak, Mobica<br>
Eben Upton, Broadcom<br>
Ed Plowman, ARM<br>
Eisaku Ohbuchi, DMP<br>
Elan Lennard, ARM<br>
Erik Faye-Lund, ARM<br>
Graham Connor, Imagination Technologies<br>
Graham Sellers, AMD<br>
Greg Roth, NVIDIA<br>
Guillaume Portier, Hi Corporation<br>
Guofang Jiao, Qualcomm<br>
Hans-Martin Will, Vincent<br>
Hwanyong Lee, Huone<br>
I-Gene Leong, NVIDIA<br>
Ian Romanick, Intel<br>
Ian South-Dickinson, NVIDIA<br>
Ilan Aelion-Exch, Samsung<br>
Inkyun Lee, Huone<br>
Jacob Strm, Ericsson<br>
James Adams, Broadcom<br>
James Jones, Imagination Technologies<br>
James McCombe, Imagination Technologies<br>
Jamie Gennis, Google<br>
Jan-Harald Fredriksen, ARM<br>
Jani Vaisanen, Nokia<br>
Jarkko Kemppainen, Symbio<br>
Jeff Bolz, NVIDIA<br>
Jeff Leger, Qualcomm<br>
Jeff Vigil, Qualcomm<br>
Jeremy Sandmel, Apple<br>
Jeremy Thorne, Broadcom<br>
Jim Hauxwell, Broadcom<br>
Jinsung Kim, Huone<br>
Jiyoung Yoon, Huone<br>
John Kessenich, Google<br>
Jon Kennedy, 3DLabs<br>
Jon Leech, Khronos<br>
Jonathan Putsman, Imagination Technologies<br>
Joohoon Lee, Samsung<br>
JoukoKylmäoja, Symbio<br>
Jrn Nystad, ARM<br>
Jussi Rasanen, NVIDIA<br>
Kalle Raita, drawElements<br>
Kari Pulli, Nokia<br>
Keith Whitwell, VMware<br>
Kent Miller, Netlogic Microsystems<br>
Kimmo Nikkanen, Nokia<br>
Konsta Karsisto, Nokia<br>
Krzysztof Kaminski, Intel<br>
Larry Seiler, Intel<br>
Lars Remes, Symbio<br>
Lee Thomason, Adobe<br>
Lefan Zhong, Vivante<br>
Marcus Lorentzon, Ericsson<br>
Mark Butler, Imagination Technologies<br>
Mark Callow, Hi Corporation<br>
Mark Cresswell, Broadcom<br>
Mark Snyder, Alt Software<br>
Mark Young, AMD<br>
Mathieu Robart, STM<br>
Matt Netsch, Qualcomm<br>
Matt Russo, Matrox<br>
Maurice Ribble, Qualcomm<br>
Max Kazakov, DMP<br>
Mika Pesonen, Nokia<br>
Mike Cai, Vivante<br>
Mike Weiblen, Zebra Imaging &amp; Qualcomm<br>
Mila Smith, AMD<br>
Nakhoon Baek, Kyungpook Univeristy<br>
Nate Huang, NVIDIA<br>
Neil Trevett, NVIDIA<br>
Nelson Kidd, Intel<br>
Nick Haemel, NVIDIA<br>
Nick Penwarden, Epic Games<br>
Niklas Smedberg, Epic Games<br>
Nizar Romdan, ARM<br>
Oliver Wohlmuth , Fujitsu<br>
Pat Brown, NVIDIA<br>
Paul Ruggieri, Qualcomm<br>
Per Wennersten, Ericsson<br>
Petri Talala, Symbio<br>
Phil Huxley, ZiiLabs<br>
Philip Hatcher, Freescale &amp; Intel<br>
Piers Daniell, NVIDIA<br>
Pyry Haulos, drawElements<br>
Piotr Tomaszewski, Ericsson<br>
Piotr Uminski, Intel<br>
Rami Mayer, Samsung<br>
Rauli Laatikainen, RightWare<br>
Rob Barris, NVIDIA<br>
Rob Simpson, Qualcomm<br>
Roj Langhi, Vivante<br>
Rune Holm, ARM<br>
Sami Kyostila, Nokia<br>
Sean Ellis, ARM<br>
Shereef Shehata, TI<br>
Sila Kayo, Nokia<br>
Slawomir Cygan, Intel<br>
Slawomir Grajewski, Intel<br>
Steve Hill, STM &amp; Broadcom<br>
Steven Olney, DMP<br>
Suman Sharma, Intel<br>
Tapani Palli, Nokia<br>
Teemu Laakso, Symbio<br>
Tero Karras, NVIDIA<br>
Timo Suoranta, Imagination Technologies &amp; Broadcom<br>
Tom Cooksey, ARM<br>
Tom McReynolds, NVIDIA<br>
Tom Olson, TI &amp; ARM<br>
Tomi Aarnio, Nokia<br>
Tommy Asano, Takumi<br>
Wes Bang, Nokia<br>
Yanjun Zhang, Vivante</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="references">13. 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>International Standard ISO/IEC 646:1991.
Information technology - ISO 7-bit coded character set for information
interchange</p>
</li>
<li>
<p>The Unicode Standard Version 6.0 - Core Specification.</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">14. 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">14.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">14.2. Mapping from GLSL to SPIR-V</h3>
<div class="sect3">
<h4 id="_specialization_constants">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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">14.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 3.20.6<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>