| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <meta name="generator" content="Asciidoctor 1.5.7.1"> |
| <meta name="author" content="John Kessenich, Google (Editor and Author) ; Dave Baldwin and Randi Rost (Version 1.1 Authors)"> |
| <title>The OpenGL® Shading Language, Version 4.60.7</title> |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> |
| <style> |
| /* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ |
| /* Uncomment @import statement below to use as custom stylesheet */ |
| /*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ |
| article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} |
| audio,canvas,video{display:inline-block} |
| audio:not([controls]){display:none;height:0} |
| script{display:none!important} |
| html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} |
| a{background:transparent} |
| a:focus{outline:thin dotted} |
| a:active,a:hover{outline:0} |
| h1{font-size:2em;margin:.67em 0} |
| abbr[title]{border-bottom:1px dotted} |
| b,strong{font-weight:bold} |
| dfn{font-style:italic} |
| hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} |
| mark{background:#ff0;color:#000} |
| code,kbd,pre,samp{font-family:monospace;font-size:1em} |
| pre{white-space:pre-wrap} |
| q{quotes:"\201C" "\201D" "\2018" "\2019"} |
| small{font-size:80%} |
| sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} |
| sup{top:-.5em} |
| sub{bottom:-.25em} |
| img{border:0} |
| svg:not(:root){overflow:hidden} |
| figure{margin:0} |
| fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} |
| legend{border:0;padding:0} |
| button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} |
| button,input{line-height:normal} |
| button,select{text-transform:none} |
| button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} |
| button[disabled],html input[disabled]{cursor:default} |
| input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} |
| button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} |
| textarea{overflow:auto;vertical-align:top} |
| table{border-collapse:collapse;border-spacing:0} |
| *,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} |
| html,body{font-size:100%} |
| body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} |
| a:hover{cursor:pointer} |
| img,object,embed{max-width:100%;height:auto} |
| object,embed{height:100%} |
| img{-ms-interpolation-mode:bicubic} |
| .left{float:left!important} |
| .right{float:right!important} |
| .text-left{text-align:left!important} |
| .text-right{text-align:right!important} |
| .text-center{text-align:center!important} |
| .text-justify{text-align:justify!important} |
| .hide{display:none} |
| img,object,svg{display:inline-block;vertical-align:middle} |
| textarea{height:auto;min-height:50px} |
| select{width:100%} |
| .center{margin-left:auto;margin-right:auto} |
| .stretch{width:100%} |
| .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} |
| div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} |
| a{color:#2156a5;text-decoration:underline;line-height:inherit} |
| a:hover,a:focus{color:#1d4b8f} |
| a img{border:none} |
| p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} |
| p aside{font-size:.875em;line-height:1.35;font-style:italic} |
| h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} |
| h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} |
| h1{font-size:2.125em} |
| h2{font-size:1.6875em} |
| h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} |
| h4,h5{font-size:1.125em} |
| h6{font-size:1em} |
| hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} |
| em,i{font-style:italic;line-height:inherit} |
| strong,b{font-weight:bold;line-height:inherit} |
| small{font-size:60%;line-height:inherit} |
| code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} |
| ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} |
| ul,ol{margin-left:1.5em} |
| ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} |
| ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} |
| ul.square{list-style-type:square} |
| ul.circle{list-style-type:circle} |
| ul.disc{list-style-type:disc} |
| ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} |
| dl dt{margin-bottom:.3125em;font-weight:bold} |
| dl dd{margin-bottom:1.25em} |
| abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} |
| abbr{text-transform:none} |
| blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} |
| blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} |
| blockquote cite::before{content:"\2014 \0020"} |
| blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} |
| blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} |
| @media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} |
| h1{font-size:2.75em} |
| h2{font-size:2.3125em} |
| h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} |
| h4{font-size:1.4375em}} |
| table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} |
| table thead,table tfoot{background:#f7f8f7} |
| table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} |
| table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} |
| table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} |
| table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} |
| h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} |
| h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} |
| .clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} |
| .clearfix::after,.float-group::after{clear:both} |
| *:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} |
| *:not(pre)>code.nobreak{word-wrap:normal} |
| *:not(pre)>code.nowrap{white-space:nowrap} |
| pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} |
| em em{font-style:normal} |
| strong strong{font-weight:400} |
| .keyseq{color:rgba(51,51,51,.8)} |
| kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} |
| .keyseq kbd:first-child{margin-left:0} |
| .keyseq kbd:last-child{margin-right:0} |
| .menuseq,.menuref{color:#000} |
| .menuseq b:not(.caret),.menuref{font-weight:inherit} |
| .menuseq{word-spacing:-.02em} |
| .menuseq b.caret{font-size:1.25em;line-height:.8} |
| .menuseq i.caret{font-weight:bold;text-align:center;width:.45em} |
| b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} |
| b.button::before{content:"[";padding:0 3px 0 2px} |
| b.button::after{content:"]";padding:0 2px 0 3px} |
| p a>code:hover{color:rgba(0,0,0,.9)} |
| #header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} |
| #header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} |
| #header::after,#content::after,#footnotes::after,#footer::after{clear:both} |
| #content{margin-top:1.25em} |
| #content::before{content:none} |
| #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} |
| #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} |
| #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} |
| #header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} |
| #header .details span:first-child{margin-left:-.125em} |
| #header .details span.email a{color:rgba(0,0,0,.85)} |
| #header .details br{display:none} |
| #header .details br+span::before{content:"\00a0\2013\00a0"} |
| #header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} |
| #header .details br+span#revremark::before{content:"\00a0|\00a0"} |
| #header #revnumber{text-transform:capitalize} |
| #header #revnumber::after{content:"\00a0"} |
| #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} |
| #toc{border-bottom:1px solid #efefed;padding-bottom:.5em} |
| #toc>ul{margin-left:.125em} |
| #toc ul.sectlevel0>li>a{font-style:italic} |
| #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} |
| #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} |
| #toc li{line-height:1.3334;margin-top:.3334em} |
| #toc a{text-decoration:none} |
| #toc a:active{text-decoration:underline} |
| #toctitle{color:#7a2518;font-size:1.2em} |
| @media screen and (min-width:768px){#toctitle{font-size:1.375em} |
| body.toc2{padding-left:15em;padding-right:0} |
| #toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} |
| #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} |
| #toc.toc2>ul{font-size:.9em;margin-bottom:0} |
| #toc.toc2 ul ul{margin-left:0;padding-left:1em} |
| #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} |
| body.toc2.toc-right{padding-left:0;padding-right:15em} |
| body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} |
| @media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} |
| #toc.toc2{width:20em} |
| #toc.toc2 #toctitle{font-size:1.375em} |
| #toc.toc2>ul{font-size:.95em} |
| #toc.toc2 ul ul{padding-left:1.25em} |
| body.toc2.toc-right{padding-left:0;padding-right:20em}} |
| #content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} |
| #content #toc>:first-child{margin-top:0} |
| #content #toc>:last-child{margin-bottom:0} |
| #footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} |
| #footer-text{color:rgba(255,255,255,.8);line-height:1.44} |
| #content{margin-bottom:.625em} |
| .sect1{padding-bottom:.625em} |
| @media screen and (min-width:768px){#content{margin-bottom:1.25em} |
| .sect1{padding-bottom:1.25em}} |
| .sect1:last-child{padding-bottom:0} |
| .sect1+.sect1{border-top:1px solid #efefed} |
| #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} |
| #content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} |
| #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} |
| #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} |
| #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} |
| .audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} |
| .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} |
| table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} |
| .paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} |
| table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} |
| .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} |
| .admonitionblock>table td.icon{text-align:center;width:80px} |
| .admonitionblock>table td.icon img{max-width:none} |
| .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} |
| .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} |
| .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} |
| .exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} |
| .exampleblock>.content>:first-child{margin-top:0} |
| .exampleblock>.content>:last-child{margin-bottom:0} |
| .sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} |
| .sidebarblock>:first-child{margin-top:0} |
| .sidebarblock>:last-child{margin-bottom:0} |
| .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} |
| .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} |
| .literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} |
| .sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} |
| .literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} |
| .literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} |
| @media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} |
| @media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} |
| .literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} |
| .listingblock pre.highlightjs{padding:0} |
| .listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} |
| .listingblock pre.prettyprint{border-width:0} |
| .listingblock>.content{position:relative} |
| .listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} |
| .listingblock:hover code[data-lang]::before{display:block} |
| .listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} |
| .listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} |
| table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} |
| table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} |
| table.pyhltable td.code{padding-left:.75em;padding-right:0} |
| pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} |
| pre.pygments .lineno{display:inline-block;margin-right:.25em} |
| table.pyhltable .linenodiv{background:none!important;padding-right:0!important} |
| .quoteblock{margin:0 1em 1.25em 1.5em;display:table} |
| .quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} |
| .quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} |
| .quoteblock blockquote{margin:0;padding:0;border:0} |
| .quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} |
| .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} |
| .quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} |
| .quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} |
| .quoteblock .quoteblock blockquote{padding:0 0 0 .75em} |
| .quoteblock .quoteblock blockquote::before{display:none} |
| .verseblock{margin:0 1em 1.25em} |
| .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} |
| .verseblock pre strong{font-weight:400} |
| .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} |
| .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} |
| .quoteblock .attribution br,.verseblock .attribution br{display:none} |
| .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} |
| .quoteblock.abstract{margin:0 1em 1.25em;display:block} |
| .quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} |
| .quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6} |
| .quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none} |
| table.tableblock{max-width:100%;border-collapse:separate} |
| p.tableblock:last-child{margin-bottom:0} |
| td.tableblock>.content{margin-bottom:-1.25em} |
| table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} |
| table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} |
| table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} |
| table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} |
| table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} |
| table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} |
| table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} |
| table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} |
| table.frame-all{border-width:1px} |
| table.frame-sides{border-width:0 1px} |
| table.frame-topbot,table.frame-ends{border-width:1px 0} |
| table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} |
| table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} |
| th.halign-left,td.halign-left{text-align:left} |
| th.halign-right,td.halign-right{text-align:right} |
| th.halign-center,td.halign-center{text-align:center} |
| th.valign-top,td.valign-top{vertical-align:top} |
| th.valign-bottom,td.valign-bottom{vertical-align:bottom} |
| th.valign-middle,td.valign-middle{vertical-align:middle} |
| table thead th,table tfoot th{font-weight:bold} |
| tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} |
| tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} |
| p.tableblock>code:only-child{background:none;padding:0} |
| p.tableblock{font-size:1em} |
| td>div.verse{white-space:pre} |
| ol{margin-left:1.75em} |
| ul li ol{margin-left:1.5em} |
| dl dd{margin-left:1.125em} |
| dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} |
| ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} |
| ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} |
| ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} |
| ul.unstyled,ol.unstyled{margin-left:0} |
| ul.checklist{margin-left:.625em} |
| ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} |
| ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} |
| ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} |
| ul.inline>li{margin-left:1.25em} |
| .unstyled dl dt{font-weight:400;font-style:normal} |
| ol.arabic{list-style-type:decimal} |
| ol.decimal{list-style-type:decimal-leading-zero} |
| ol.loweralpha{list-style-type:lower-alpha} |
| ol.upperalpha{list-style-type:upper-alpha} |
| ol.lowerroman{list-style-type:lower-roman} |
| ol.upperroman{list-style-type:upper-roman} |
| ol.lowergreek{list-style-type:lower-greek} |
| .hdlist>table,.colist>table{border:0;background:none} |
| .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} |
| td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} |
| td.hdlist1{font-weight:bold;padding-bottom:1.25em} |
| .literalblock+.colist,.listingblock+.colist{margin-top:-.5em} |
| .colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} |
| .colist td:not([class]):first-child img{max-width:none} |
| .colist td:not([class]):last-child{padding:.25em 0} |
| .thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} |
| .imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} |
| .imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} |
| .imageblock>.title{margin-bottom:0} |
| .imageblock.thumb,.imageblock.th{border-width:6px} |
| .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} |
| .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} |
| .image.left{margin-right:.625em} |
| .image.right{margin-left:.625em} |
| a.image{text-decoration:none;display:inline-block} |
| a.image object{pointer-events:none} |
| sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} |
| sup.footnote a,sup.footnoteref a{text-decoration:none} |
| sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} |
| #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} |
| #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} |
| #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} |
| #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} |
| #footnotes .footnote:last-of-type{margin-bottom:0} |
| #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} |
| .gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} |
| .gist .file-data>table td.line-data{width:99%} |
| div.unbreakable{page-break-inside:avoid} |
| .big{font-size:larger} |
| .small{font-size:smaller} |
| .underline{text-decoration:underline} |
| .overline{text-decoration:overline} |
| .line-through{text-decoration:line-through} |
| .aqua{color:#00bfbf} |
| .aqua-background{background-color:#00fafa} |
| .black{color:#000} |
| .black-background{background-color:#000} |
| .blue{color:#0000bf} |
| .blue-background{background-color:#0000fa} |
| .fuchsia{color:#bf00bf} |
| .fuchsia-background{background-color:#fa00fa} |
| .gray{color:#606060} |
| .gray-background{background-color:#7d7d7d} |
| .green{color:#006000} |
| .green-background{background-color:#007d00} |
| .lime{color:#00bf00} |
| .lime-background{background-color:#00fa00} |
| .maroon{color:#600000} |
| .maroon-background{background-color:#7d0000} |
| .navy{color:#000060} |
| .navy-background{background-color:#00007d} |
| .olive{color:#606000} |
| .olive-background{background-color:#7d7d00} |
| .purple{color:#600060} |
| .purple-background{background-color:#7d007d} |
| .red{color:#bf0000} |
| .red-background{background-color:#fa0000} |
| .silver{color:#909090} |
| .silver-background{background-color:#bcbcbc} |
| .teal{color:#006060} |
| .teal-background{background-color:#007d7d} |
| .white{color:#bfbfbf} |
| .white-background{background-color:#fafafa} |
| .yellow{color:#bfbf00} |
| .yellow-background{background-color:#fafa00} |
| span.icon>.fa{cursor:default} |
| a span.icon>.fa{cursor:inherit} |
| .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} |
| .admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} |
| .admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} |
| .admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} |
| .admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} |
| .admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} |
| .conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} |
| .conum[data-value] *{color:#fff!important} |
| .conum[data-value]+b{display:none} |
| .conum[data-value]::after{content:attr(data-value)} |
| pre .conum[data-value]{position:relative;top:-.125em} |
| b.conum *{color:inherit!important} |
| .conum:not([data-value]):empty{display:none} |
| dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} |
| h1,h2,p,td.content,span.alt{letter-spacing:-.01em} |
| p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} |
| p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} |
| p{margin-bottom:1.25rem} |
| .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} |
| .exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} |
| .print-only{display:none!important} |
| @page{margin:1.25cm .75cm} |
| @media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} |
| html{font-size:80%} |
| a{color:inherit!important;text-decoration:underline!important} |
| a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} |
| a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} |
| abbr[title]::after{content:" (" attr(title) ")"} |
| pre,blockquote,tr,img,object,svg{page-break-inside:avoid} |
| thead{display:table-header-group} |
| svg{max-width:100%} |
| p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} |
| h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} |
| #toc,.sidebarblock,.exampleblock>.content{background:none!important} |
| #toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} |
| body.book #header{text-align:center} |
| body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} |
| body.book #header .details{border:0!important;display:block;padding:0!important} |
| body.book #header .details span:first-child{margin-left:0!important} |
| body.book #header .details br{display:block} |
| body.book #header .details br+span::before{content:none!important} |
| body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} |
| body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} |
| .listingblock code[data-lang]::before{display:block} |
| #footer{padding:0 .9375em} |
| .hide-on-print{display:none!important} |
| .print-only{display:block!important} |
| .hide-for-print{display:none!important} |
| .show-for-print{display:inherit!important}} |
| @media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} |
| .sect1{padding:0!important} |
| .sect1+.sect1{border:0} |
| #footer{background:none} |
| #footer-text{color:rgba(0,0,0,.6);font-size:.9em}} |
| @media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} |
| </style> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> |
| <style> |
| /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */ |
| /*pre.CodeRay {background-color:#f7f7f8;}*/ |
| .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em} |
| .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)} |
| .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)} |
| table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none} |
| table.CodeRay td{vertical-align: top;line-height:1.45} |
| table.CodeRay td.line-numbers{text-align:right} |
| table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)} |
| table.CodeRay td.code{padding:0 0 0 .5em} |
| table.CodeRay td.code>pre{padding:0} |
| .CodeRay .debug{color:#fff !important;background:#000080 !important} |
| .CodeRay .annotation{color:#007} |
| .CodeRay .attribute-name{color:#000080} |
| .CodeRay .attribute-value{color:#700} |
| .CodeRay .binary{color:#509} |
| .CodeRay .comment{color:#998;font-style:italic} |
| .CodeRay .char{color:#04d} |
| .CodeRay .char .content{color:#04d} |
| .CodeRay .char .delimiter{color:#039} |
| .CodeRay .class{color:#458;font-weight:bold} |
| .CodeRay .complex{color:#a08} |
| .CodeRay .constant,.CodeRay .predefined-constant{color:#008080} |
| .CodeRay .color{color:#099} |
| .CodeRay .class-variable{color:#369} |
| .CodeRay .decorator{color:#b0b} |
| .CodeRay .definition{color:#099} |
| .CodeRay .delimiter{color:#000} |
| .CodeRay .doc{color:#970} |
| .CodeRay .doctype{color:#34b} |
| .CodeRay .doc-string{color:#d42} |
| .CodeRay .escape{color:#666} |
| .CodeRay .entity{color:#800} |
| .CodeRay .error{color:#808} |
| .CodeRay .exception{color:inherit} |
| .CodeRay .filename{color:#099} |
| .CodeRay .function{color:#900;font-weight:bold} |
| .CodeRay .global-variable{color:#008080} |
| .CodeRay .hex{color:#058} |
| .CodeRay .integer,.CodeRay .float{color:#099} |
| .CodeRay .include{color:#555} |
| .CodeRay .inline{color:#000} |
| .CodeRay .inline .inline{background:#ccc} |
| .CodeRay .inline .inline .inline{background:#bbb} |
| .CodeRay .inline .inline-delimiter{color:#d14} |
| .CodeRay .inline-delimiter{color:#d14} |
| .CodeRay .important{color:#555;font-weight:bold} |
| .CodeRay .interpreted{color:#b2b} |
| .CodeRay .instance-variable{color:#008080} |
| .CodeRay .label{color:#970} |
| .CodeRay .local-variable{color:#963} |
| .CodeRay .octal{color:#40e} |
| .CodeRay .predefined{color:#369} |
| .CodeRay .preprocessor{color:#579} |
| .CodeRay .pseudo-class{color:#555} |
| .CodeRay .directive{font-weight:bold} |
| .CodeRay .type{font-weight:bold} |
| .CodeRay .predefined-type{color:inherit} |
| .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold} |
| .CodeRay .key{color:#808} |
| .CodeRay .key .delimiter{color:#606} |
| .CodeRay .key .char{color:#80f} |
| .CodeRay .value{color:#088} |
| .CodeRay .regexp .delimiter{color:#808} |
| .CodeRay .regexp .content{color:#808} |
| .CodeRay .regexp .modifier{color:#808} |
| .CodeRay .regexp .char{color:#d14} |
| .CodeRay .regexp .function{color:#404;font-weight:bold} |
| .CodeRay .string{color:#d20} |
| .CodeRay .string .string .string{background:#ffd0d0} |
| .CodeRay .string .content{color:#d14} |
| .CodeRay .string .char{color:#d14} |
| .CodeRay .string .delimiter{color:#d14} |
| .CodeRay .shell{color:#d14} |
| .CodeRay .shell .delimiter{color:#d14} |
| .CodeRay .symbol{color:#990073} |
| .CodeRay .symbol .content{color:#a60} |
| .CodeRay .symbol .delimiter{color:#630} |
| .CodeRay .tag{color:#008080} |
| .CodeRay .tag-special{color:#d70} |
| .CodeRay .variable{color:#036} |
| .CodeRay .insert{background:#afa} |
| .CodeRay .delete{background:#faa} |
| .CodeRay .change{color:#aaf;background:#007} |
| .CodeRay .head{color:#f8f;background:#505} |
| .CodeRay .insert .insert{color:#080} |
| .CodeRay .delete .delete{color:#800} |
| .CodeRay .change .change{color:#66f} |
| .CodeRay .head .head{color:#f4f} |
| </style> |
| <link rel="stylesheet" href="../katex/katex.min.css"> |
| <script src="../katex/katex.min.js"></script> |
| <script src="../katex/contrib/auto-render.min.js"></script> |
| <!-- Use KaTeX to render math once document is loaded, see |
| https://github.com/Khan/KaTeX/tree/master/contrib/auto-render --> |
| <script> |
| document.addEventListener("DOMContentLoaded", function () { |
| renderMathInElement( |
| document.body, |
| { |
| delimiters: [ |
| { left: "$$", right: "$$", display: true}, |
| { left: "\\[", right: "\\]", display: true}, |
| { left: "$", right: "$", display: false}, |
| { left: "\\(", right: "\\)", display: false} |
| ] |
| } |
| ); |
| }); |
| </script></head> |
| <body class="book toc2 toc-left" style="max-width: 100;"> |
| <div id="header"> |
| <h1>The OpenGL<sup>®</sup> Shading Language, Version 4.60.7</h1> |
| <div class="details"> |
| <span id="author" class="author">John Kessenich, Google (Editor and Author) ; Dave Baldwin and Randi Rost (Version 1.1 Authors)</span><br> |
| <span id="revnumber">version 4.60.7,</span> |
| <span id="revdate">Wed, 10 Jul 2019 20:42:58 +0000</span> |
| <br><span id="revremark">Git branch information not available</span> |
| </div> |
| <div id="toc" class="toc2"> |
| <div id="toctitle">Table of Contents</div> |
| <ul class="sectlevel1"> |
| <li><a href="#introduction">1. Introduction</a> |
| <ul class="sectlevel2"> |
| <li><a href="#changes">1.1. Changes</a></li> |
| <li><a href="#overview">1.2. Overview</a></li> |
| <li><a href="#error-handling">1.3. Error Handling</a></li> |
| <li><a href="#typographical-conventions">1.4. Typographical Conventions</a></li> |
| <li><a href="#deprecation">1.5. Deprecation</a></li> |
| </ul> |
| </li> |
| <li><a href="#overview-of-opengl-shading">2. Overview of Shading</a> |
| <ul class="sectlevel2"> |
| <li><a href="#vertex-processor">2.1. Vertex Processor</a></li> |
| <li><a href="#tessellation-control-processor">2.2. Tessellation Control Processor</a></li> |
| <li><a href="#tessellation-evaluation-processor">2.3. Tessellation Evaluation Processor</a></li> |
| <li><a href="#geometry-processor">2.4. Geometry Processor</a></li> |
| <li><a href="#fragment-processor">2.5. Fragment Processor</a></li> |
| <li><a href="#compute-processor">2.6. Compute Processor</a></li> |
| </ul> |
| </li> |
| <li><a href="#basics">3. Basics</a> |
| <ul class="sectlevel2"> |
| <li><a href="#character-set">3.1. Character Set and Phases of Compilation</a></li> |
| <li><a href="#source-strings">3.2. Source Strings</a></li> |
| <li><a href="#preprocessor">3.3. Preprocessor</a></li> |
| <li><a href="#comments">3.4. Comments</a></li> |
| <li><a href="#tokens">3.5. Tokens</a></li> |
| <li><a href="#keywords">3.6. Keywords</a></li> |
| <li><a href="#identifiers">3.7. Identifiers</a></li> |
| <li><a href="#definitions">3.8. Definitions</a></li> |
| </ul> |
| </li> |
| <li><a href="#variables-and-types">4. Variables and Types</a> |
| <ul class="sectlevel2"> |
| <li><a href="#basic-types">4.1. Basic Types</a></li> |
| <li><a href="#scoping">4.2. Scoping</a></li> |
| <li><a href="#storage-qualifiers">4.3. Storage Qualifiers</a></li> |
| <li><a href="#layout-qualifiers">4.4. Layout Qualifiers</a></li> |
| <li><a href="#interpolation-qualifiers">4.5. Interpolation Qualifiers</a></li> |
| <li><a href="#parameter-qualifiers">4.6. Parameter Qualifiers</a></li> |
| <li><a href="#precision-and-precision-qualifiers">4.7. Precision and Precision Qualifiers</a></li> |
| <li><a href="#variance-and-the-invariant-qualifier">4.8. Variance and the Invariant Qualifier</a></li> |
| <li><a href="#the-precise-qualifier">4.9. The Precise Qualifier</a></li> |
| <li><a href="#memory-qualifiers">4.10. Memory Qualifiers</a></li> |
| <li><a href="#specialization-constant-qualifier">4.11. Specialization-Constant Qualifier</a></li> |
| <li><a href="#order-of-qualification">4.12. Order and Repetition of Qualification</a></li> |
| <li><a href="#empty-declarations">4.13. Empty Declarations</a></li> |
| </ul> |
| </li> |
| <li><a href="#operators-and-expressions">5. Operators and Expressions</a> |
| <ul class="sectlevel2"> |
| <li><a href="#operators">5.1. Operators</a></li> |
| <li><a href="#array-operations">5.2. Array Operations</a></li> |
| <li><a href="#function-calls">5.3. Function Calls</a></li> |
| <li><a href="#constructors">5.4. Constructors</a></li> |
| <li><a href="#vector-components">5.5. Vector and Scalar Components and Length</a></li> |
| <li><a href="#matrix-components">5.6. Matrix Components</a></li> |
| <li><a href="#structure-and-array-operations">5.7. Structure and Array Operations</a></li> |
| <li><a href="#assignments">5.8. Assignments</a></li> |
| <li><a href="#expressions">5.9. Expressions</a></li> |
| <li><a href="#vector-and-matrix-operations">5.10. Vector and Matrix Operations</a></li> |
| <li><a href="#out-of-bounds-accesses">5.11. Out-of-Bounds Accesses</a></li> |
| <li><a href="#specialization-constant-operations">5.12. Specialization-Constant Operations</a></li> |
| </ul> |
| </li> |
| <li><a href="#statements-and-structure">6. Statements and Structure</a> |
| <ul class="sectlevel2"> |
| <li><a href="#function-definitions">6.1. Function Definitions</a></li> |
| <li><a href="#selection">6.2. Selection</a></li> |
| <li><a href="#iteration">6.3. Iteration</a></li> |
| <li><a href="#jumps">6.4. Jumps</a></li> |
| </ul> |
| </li> |
| <li><a href="#built-in-variables">7. Built-In Variables</a> |
| <ul class="sectlevel2"> |
| <li><a href="#built-in-language-variables">7.1. Built-In Language Variables</a></li> |
| <li><a href="#compatibility-profile-vertex-shader-built-in-inputs">7.2. Compatibility Profile Vertex Shader Built-In Inputs</a></li> |
| <li><a href="#built-in-constants">7.3. Built-In Constants</a></li> |
| <li><a href="#built-in-uniform-state">7.4. Built-In Uniform State</a></li> |
| <li><a href="#redeclaring-built-in-blocks">7.5. Redeclaring Built-In Blocks</a></li> |
| </ul> |
| </li> |
| <li><a href="#built-in-functions">8. Built-In Functions</a> |
| <ul class="sectlevel2"> |
| <li><a href="#angle-and-trigonometry-functions">8.1. Angle and Trigonometry Functions</a></li> |
| <li><a href="#exponential-functions">8.2. Exponential Functions</a></li> |
| <li><a href="#common-functions">8.3. Common Functions</a></li> |
| <li><a href="#floating-point-pack-and-unpack-functions">8.4. Floating-Point Pack and Unpack Functions</a></li> |
| <li><a href="#geometric-functions">8.5. Geometric Functions</a></li> |
| <li><a href="#matrix-functions">8.6. Matrix Functions</a></li> |
| <li><a href="#vector-relational-functions">8.7. Vector Relational Functions</a></li> |
| <li><a href="#integer-functions">8.8. Integer Functions</a></li> |
| <li><a href="#texture-functions">8.9. Texture Functions</a></li> |
| <li><a href="#atomic-counter-functions">8.10. Atomic Counter Functions</a></li> |
| <li><a href="#atomic-memory-functions">8.11. Atomic Memory Functions</a></li> |
| <li><a href="#image-functions">8.12. Image Functions</a></li> |
| <li><a href="#geometry-shader-functions">8.13. Geometry Shader Functions</a></li> |
| <li><a href="#fragment-processing-functions">8.14. Fragment Processing Functions</a></li> |
| <li><a href="#noise-functions">8.15. Noise Functions</a></li> |
| <li><a href="#shader-invocation-control-functions">8.16. Shader Invocation Control Functions</a></li> |
| <li><a href="#shader-memory-control-functions">8.17. Shader Memory Control Functions</a></li> |
| <li><a href="#_subpass_input_functions">8.18. Subpass-Input Functions</a></li> |
| <li><a href="#shader-invocation-group-functions">8.19. Shader Invocation Group Functions</a></li> |
| </ul> |
| </li> |
| <li><a href="#shading-language-grammar">9. Shading Language Grammar</a></li> |
| <li><a href="#acknowledgments">10. Acknowledgments</a></li> |
| <li><a href="#references">11. Normative References</a></li> |
| <li><a href="#_non_normative_spir_v_mappings">12. Non-Normative SPIR-V Mappings</a> |
| <ul class="sectlevel2"> |
| <li><a href="#_feature_comparisons">12.1. Feature Comparisons</a></li> |
| <li><a href="#_mapping_from_glsl_to_spir_v">12.2. Mapping from GLSL to SPIR-V</a></li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div id="content"> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div style="page-break-after: always;"></div> |
| <div class="paragraph"> |
| <p>Copyright © 2008-2018 The Khronos Group Inc. All Rights Reserved.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This specification is protected by copyright laws and contains material |
| proprietary to the Khronos Group, Inc. It or any components may not be |
| reproduced, republished, distributed, transmitted, displayed, broadcast, |
| or otherwise exploited in any manner without the express prior written |
| permission of Khronos Group. You may use this specification for |
| implementing the functionality therein, without altering or removing any |
| trademark, copyright or other notice from the specification, but the |
| receipt or possession of this specification does not convey any rights |
| to reproduce, disclose, or distribute its contents, or to manufacture, |
| use, or sell anything that it may describe, in whole or in part.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Khronos Group grants express permission to any current Promoter, |
| Contributor or Adopter member of Khronos to copy and redistribute |
| UNMODIFIED versions of this specification in any fashion, provided that |
| NO CHARGE is made for the specification and the latest available update |
| of the specification for any version of the API is used whenever |
| possible. Such distributed specification may be reformatted AS LONG AS |
| the contents of the specification are not changed in any way. The |
| specification may be incorporated into a product that is sold as long as |
| such product includes significant independent work developed by the |
| seller. A link to the current version of this specification on the |
| Khronos Group website should be included whenever possible with |
| specification distributions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Khronos Group makes no, and expressly disclaims any, representations or |
| warranties, express or implied, regarding this specification, including, |
| without limitation, any implied warranties of merchantability or fitness |
| for a particular purpose or noninfringement of any intellectual |
| property. Khronos Group makes no, and expressly disclaims any, |
| warranties, express or implied, regarding the correctness, accuracy, |
| completeness, timeliness, and reliability of the specification. Under no |
| circumstances will the Khronos Group, or any of its Promoters, |
| Contributors or Members or their respective partners, officers, |
| directors, employees, agents, or representatives be liable for any |
| damages, whether direct, indirect, special or consequential damages for |
| lost revenues, lost profits, or otherwise, arising from or in connection |
| with these materials.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Khronos, Vulkan, SYCL, SPIR, WebGL, EGL, COLLADA, StreamInput, OpenVX, |
| OpenKCam, glTF, OpenKODE, OpenVG, OpenWF, OpenSL ES, OpenMAX, OpenMAX |
| AL, OpenMAX IL and OpenMAX DL are trademarks and WebCL is a |
| certification mark of the Khronos Group Inc. OpenCL is a trademark of |
| Apple Inc. and OpenGL and OpenML are registered trademarks and the |
| OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics |
| International used under license by Khronos. All other product names, |
| trademarks, and/or company names are used solely for identification and |
| belong to their respective owners.</p> |
| </div> |
| <div style="page-break-after: always;"></div> |
| <!-- toc disabled --> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="introduction">1. Introduction</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This document specifies only version 4.60 of the OpenGL Shading Language (GLSL). |
| It requires __VERSION__ to substitute 460, and requires |
| <strong>#version</strong> to accept only |
| <code>460</code>. |
| If <strong>#version</strong> is declared with a smaller number, the language accepted is a |
| previous version of the shading language, which will be supported depending |
| on the version and type of context in the API. |
| See the <a href="#references">normative references</a> for details on what language |
| versions are supported.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Previous versions of the OpenGL Shading Language, as well as the OpenGL ES Shading Language, |
| are not strict subsets of the version specified here, particularly with |
| respect to precision, name-hiding rules, and treatment of interface |
| variables. |
| See the specification corresponding to a particular language version for |
| details specific to that version of the language.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Throughout, when generating SPIR-V for consumption by the Vulkan API |
| (see <a href="#references">normative references</a>), this will be said to be |
| <em>targeting Vulkan</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>While this specification and the OpenGL Specification are normative for OpenGL Shading Language, for |
| SPIR-V generation it is still the SPIR-V specification and the SPIR-V client |
| API specification that are normative for the generated SPIR-V. |
| See the <a href="#references">normative references</a> for further detail.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For SPIR-V generation, the SPIR-V client API specifies the commands used to |
| manipulate SPIR-V shaders.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Independent offline tool chains will compile GLSL down to the SPIR-V |
| intermediate language. |
| SPIR-V generation is not enabled with a <strong>#extension</strong>, <strong>#version</strong>, or a |
| profile. |
| Instead, use of GLSL for SPIR-V is determined by offline tool-chain use. |
| See the documentation of such tools to see how to request generation of |
| SPIR-V for its client API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>GLSL → SPIR-V compilers must be directed as to what SPIR-V <strong>Capabilities</strong> |
| are legal at run-time and give errors for GLSL feature use outside those |
| capabilities. |
| This is also true for implementation-dependent limits that can be error |
| checked by the front-end against built-in constants present in the GLSL |
| source: the front-end can be informed of such limits, and report errors when |
| they are exceeded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>SPIR-V features that are not controlled by a SPIR-V capability, but do have an |
| equivalent GLSL counterpart (stages, built-in functions, types, limits, etc.) |
| are only expected to work on OpenGL drivers that support the GLSL counterpart.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All references in this specification to the <a href="#references">OpenGL Specification</a> are to |
| the Core profile of version 4.6, unless a different profile is |
| specified.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="changes">1.1. Changes</h3> |
| <div class="sect3"> |
| <h4 id="_changes_from_revision_6_of_glsl_4_6">1.1.1. Changes from Revision 6 of GLSL 4.6</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Incorporated the GL_KHR_vulkan_glsl specification.</p> |
| </li> |
| <li> |
| <p>Add note in the introduction about presence in drivers of SPIR-V features, |
| as they relate to GLSL features.</p> |
| </li> |
| <li> |
| <p>Clarify it is same location that triggers default-uniform block matching |
| rules. |
| See <a href="#uniform-variable-layout-qualifiers">Uniform Variable Layout Qualifiers</a>.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_changes_from_revision_5_of_glsl_4_6">1.1.2. Changes from Revision 5 of GLSL 4.6</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Private GLSL issue #34: Clarify/consolidate implicit conversion rules from int → uint |
| to be the same as explicit construction.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue #24: Clarify that <strong>barrier</strong>() by itself is enough to synchronize |
| both control flow and memory accesses to <strong>shared</strong> variables and tessellation |
| control output variables. For other memory accesses an additional memory |
| barrier is still required.</p> |
| </li> |
| <li> |
| <p>Normatively reference IEEE-754 for definitions of floating-point formats.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 36: <strong>refract</strong> function on <strong>double</strong> types requires eta |
| argument to have type <strong>double</strong>.</p> |
| </li> |
| <li> |
| <p>Clarify restrictions on input variables in tessellation and geometry stages.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 15: Clarify the ordering of bindings for arrays of arrays.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 14: Uniform variables need only match at link time if they |
| are statically used.</p> |
| </li> |
| <li> |
| <p>For <strong>precise</strong> computations, the controlling expressions for |
| control flow and ternary operators (<strong>?:</strong>) are not included.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_changes_from_revision_4_of_glsl_4_6">1.1.3. Changes from Revision 4 of GLSL 4.6</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Private bug 13012: Clarified that builtin uniform variables might only |
| be available in the fragment stage.</p> |
| </li> |
| <li> |
| <p>Private bug 13837: Ternary and sequence operators may operate on <strong>void</strong> types.</p> |
| </li> |
| <li> |
| <p>Clarified that errors arising from preprocessing must be returned at compile time.</p> |
| </li> |
| <li> |
| <p>Clarified that access to any part of a variable constitutes a static use.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 19: A statement is required following any label at the end of a <strong>switch</strong>.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 26: <strong>noise</strong> is not valid when compiling for SPIR-V.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 20: <strong>length</strong>() expressions returning a constant value may not |
| contain side effects.</p> |
| </li> |
| <li> |
| <p>Public OpenGL-API issue 7: Variables can be declared as both <strong>readonly</strong> |
| and <strong>writeonly</strong>.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 16: Use of constant expressions within <strong>#line</strong> directives is undefined.</p> |
| </li> |
| <li> |
| <p>Corrected return type of <strong>imageAtomicExchange</strong> on <strong>float</strong> images.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 32: Remove <strong>length</strong>() method contradiction: |
| Non runtime-sized arrays only support <strong>length</strong>() on explicitly |
| sized arrays.</p> |
| </li> |
| <li> |
| <p>Private GLSL issue 21: Clarified the l-value restriction on <strong>interpolateAt</strong>.</p> |
| </li> |
| <li> |
| <p>Private OpenGL-API issue 53: Clarified bit-width requirements for location aliasing.</p> |
| </li> |
| <li> |
| <p>Public GLSL issue 15: <strong>gl_in</strong> can be redeclared using unsized-array syntax.</p> |
| </li> |
| <li> |
| <p>Clarification of the formats needed for DEPTH_COMPONENT and |
| STENCIL_COMPONENT for depth/stencil textures.</p> |
| </li> |
| <li> |
| <p>Added image formats to the layout-qualifier table in the |
| <a href="#layout-qualifiers">Layout Qualifiers</a> section.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_changes_from_revision_3_of_glsl_4_6">1.1.4. Changes from Revision 3 of GLSL 4.6</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Private GLSL issue 13: Fix misspelling of <strong>allInvocationsEqual</strong>(). |
| (The one in the table was incorrectly listed as <strong>anyInvocationsEqual</strong>(), |
| other spellings were correct.)</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_summary_of_changes_from_revision_7_of_glsl_version_4_50">1.1.5. Summary of Changes from Revision 7 of GLSL Version 4.50</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Incorporated the GL_ARB_shader_atomic_counter_ops extension.</p> |
| </li> |
| <li> |
| <p>Incorporated the GL_ARB_shader_draw_parameters extension.</p> |
| </li> |
| <li> |
| <p>Incorporated the GL_ARB_shader_group_vote extension.</p> |
| </li> |
| <li> |
| <p>Incorporated the GL_ARB_gl_spirv extension.</p> |
| </li> |
| <li> |
| <p>Private Bug 16070: Allow extra semi-colons at global scope.</p> |
| </li> |
| <li> |
| <p>Private GLSL Issue 5: Be explicit that “fail to link” is really |
| “compile-time or link-time error”, for some forms of error.</p> |
| </li> |
| <li> |
| <p>Private GLSL Issue 7: Change <em>gl_MaxComputeUniformComponents</em> to 1024.</p> |
| </li> |
| <li> |
| <p>Private OpenGL API Issue 35: Require location on transparent individual |
| uniform variables for SPIR-V.</p> |
| </li> |
| <li> |
| <p>Private GLSL Issue 8: Be more clear an <strong>interpolateAt</strong>() interpolant can |
| be a structure member.</p> |
| </li> |
| <li> |
| <p>Private GLSL Issue 9: Specify how <strong>xfb_buffer</strong> interacts with a block |
| array: the capturing buffer increments for each block array element.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="overview">1.2. Overview</h3> |
| <div class="paragraph"> |
| <p>This document describes <em>The OpenGL Shading Language, version 4.60</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Independent compilation units written in this language are called <em>shaders</em>. |
| A <em>program</em> is a set of shaders that are compiled and linked |
| together, |
| completely creating one or more of the programmable stages of the |
| API pipeline. |
| All the shaders for a single programmable stage must be within the same |
| program. |
| A complete set of programmable stages can be put into a single program or |
| the stages can be partitioned across multiple programs. |
| The aim of this document is to thoroughly specify the programming language. |
| The <a href="#references">normative references</a> will specify the API entry points |
| used to manipulate and communicate with programs and shaders.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="error-handling">1.3. Error Handling</h3> |
| <div class="paragraph"> |
| <p>Compilers, in general, accept programs that are ill-formed, due to the |
| impossibility of detecting all ill-formed programs. |
| Portability is only ensured for well-formed programs, which this |
| specification describes. |
| Compilers are encouraged to detect ill-formed programs and issue diagnostic |
| messages, but are not required to do so for all cases. |
| Compile-time errors must be returned for lexically or grammatically |
| incorrect shaders. |
| Other errors are reported at compile time or link time as indicated. |
| Code that is “dead” must still be error checked. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">if</span> (<span class="predefined-constant">false</span>) <span class="comment">// changing false to true cannot uncover additional errors</span> |
| statement; <span class="comment">// statement must be error checked regardless</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="typographical-conventions">1.4. Typographical Conventions</h3> |
| <div class="paragraph"> |
| <p>Italic, bold, and font choices have been used in this specification |
| primarily to improve readability. |
| Code fragments use a fixed width font. |
| Identifiers embedded in text are italicized. |
| Keywords embedded in text are bold. |
| Operators are called by their name, followed by their symbol in bold in |
| parentheses. |
| The clarifying grammar fragments in the text use bold for literals and |
| italics for non-terminals. |
| The official grammar in “<a href="#shading-language-grammar">Shading Language |
| Grammar</a>” uses all capitals for terminals and lower case for |
| non-terminals.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="deprecation">1.5. Deprecation</h3> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language has deprecated some features. |
| These are clearly called out in this specification as “deprecated”. |
| They are still present in this version of the language, but are targeted for |
| potential removal in a future version of the shading language. |
| The OpenGL API has a forward compatibility mode that will disallow use of |
| deprecated features. |
| If compiling in a mode where use of deprecated features is disallowed, their |
| use causes compile-time or link-time errors. |
| See the <a href="#references">OpenGL Specification</a> for details on what causes deprecated |
| language features to be accepted or to return an error.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="overview-of-opengl-shading">2. Overview of Shading</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language is actually several closely related languages. |
| These languages are used to create shaders for each of the programmable |
| processors contained in the API’s processing pipeline. |
| Currently, these processors are the vertex, tessellation control, |
| tessellation evaluation, geometry, fragment, and compute processors.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unless otherwise noted in this paper, a language feature applies to all |
| languages, and common usage will refer to these languages as a single |
| language. |
| The specific languages will be referred to by the name of the processor they |
| target: vertex, tessellation control, tessellation evaluation, geometry, |
| fragment, or compute.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Most API state is not tracked or made available to shaders. |
| Typically, user-defined variables will be used for communicating between |
| different stages of the API pipeline. |
| However, a small amount of state is still tracked and automatically made |
| available to shaders, and there are a few built-in variables for interfaces |
| between different stages of the API pipeline.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="vertex-processor">2.1. Vertex Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>vertex processor</em> is a programmable unit that operates on incoming |
| vertices and their associated data. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| <em>vertex shaders</em>. |
| When a set of vertex shaders are successfully compiled and linked, they |
| result in a <em>vertex shader executable</em> that runs on the vertex processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The vertex processor operates on one vertex at a time. |
| It does not replace graphics operations that require knowledge of several |
| vertices at a time.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="tessellation-control-processor">2.2. Tessellation Control Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>tessellation control processor</em> is a programmable unit that operates on |
| a patch of incoming vertices and their associated data, emitting a new |
| output patch. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| tessellation control shaders. |
| When a set of tessellation control shaders are successfully compiled and |
| linked, they result in a <em>tessellation control shader executable</em> that runs |
| on the tessellation control processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The tessellation control shader is invoked for each vertex of the output |
| patch. |
| Each invocation can read the attributes of any vertex in the input or output |
| patches, but can only write per-vertex attributes for the corresponding |
| output patch vertex. |
| The shader invocations collectively produce a set of per-patch attributes |
| for the output patch.</p> |
| </div> |
| <div class="paragraph"> |
| <p>After all tessellation control shader invocations have completed, the output |
| vertices and per-patch attributes are assembled to form a patch to be used |
| by subsequent pipeline stages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Tessellation control shader invocations run mostly independently, with |
| undefined relative execution order. |
| However, the built-in function <strong>barrier</strong>() can be used to control execution |
| order by synchronizing invocations, effectively dividing tessellation |
| control shader execution into a set of phases. |
| Tessellation control shaders will get undefined results if one invocation |
| reads from a per-vertex or per-patch attribute written by another invocation |
| at any point during the same phase, or if two invocations attempt to write |
| different values to the same per-patch output |
| 32-bit component |
| in a single phase.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="tessellation-evaluation-processor">2.3. Tessellation Evaluation Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>tessellation evaluation processor</em> is a programmable unit that |
| evaluates the position and other attributes of a vertex generated by the |
| tessellation primitive generator, using a patch of incoming vertices and |
| their associated data. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| tessellation evaluation shaders. |
| When a set of tessellation evaluation shaders are successfully compiled and |
| linked, they result in a <em>tessellation evaluation shader executable</em> that |
| runs on the tessellation evaluation processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each invocation of the tessellation evaluation executable computes the |
| position and attributes of a single vertex generated by the tessellation |
| primitive generator. |
| The executable can read the attributes of any vertex in the input patch, |
| plus the tessellation coordinate, which is the relative location of the |
| vertex in the primitive being tessellated. |
| The executable writes the position and other attributes of the vertex.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="geometry-processor">2.4. Geometry Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>geometry processor</em> is a programmable unit that operates on data for |
| incoming vertices for a primitive assembled after vertex processing and |
| outputs a sequence of vertices forming output primitives. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| <em>geometry shaders</em>. |
| When a set of geometry shaders are successfully compiled and linked, they |
| result in a <em>geometry shader executable</em> that runs on the geometry |
| processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A single invocation of the geometry shader executable on the geometry |
| processor will operate on a declared input primitive with a fixed number of |
| vertices. |
| This single invocation can emit a variable number of vertices that are |
| assembled into primitives of a declared output primitive type and passed to |
| subsequent pipeline stages.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="fragment-processor">2.5. Fragment Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>fragment processor</em> is a programmable unit that operates on fragment |
| values and their associated data. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| <em>fragment shaders</em>. |
| When a set of fragment shaders are successfully compiled and linked, they |
| result in a <em>fragment shader executable</em> that runs on the fragment |
| processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A fragment shader cannot change a fragment’s (<em>x</em>, <em>y</em>) position. |
| Access to neighboring fragments is not allowed. |
| The values computed by the fragment shader are ultimately used to update |
| framebuffer memory or texture memory, depending on the current API |
| state and the API command that caused the fragments to be generated.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="compute-processor">2.6. Compute Processor</h3> |
| <div class="paragraph"> |
| <p>The <em>compute processor</em> is a programmable unit that operates independently |
| from the other shader processors. |
| Compilation units written in the OpenGL Shading Language to run on this processor are called |
| <em>compute shaders</em>. |
| When a set of compute shaders are successfully compiled and linked, they |
| result in a <em>compute shader executable</em> that runs on the compute processor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A compute shader has access to many of the same resources as fragment and |
| other shader processors, such as textures, buffers, image variables, and |
| atomic counters. |
| It does not have fixed-function outputs. |
| It is not part of the graphics pipeline and its visible side effects are |
| through changes to images, storage buffers, and atomic counters.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A compute shader operates on a group of work items called a <em>workgroup</em>. |
| A workgroup is a collection of shader invocations that execute the same |
| code, potentially in parallel. |
| An invocation within a workgroup may share data with other members of the |
| same workgroup through shared variables and issue memory and control flow |
| barriers to synchronize with other members of the same workgroup.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="basics">3. Basics</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="character-set">3.1. Character Set and Phases of Compilation</h3> |
| <div class="paragraph"> |
| <p>The source character set used for the OpenGL Shading Language is Unicode in the UTF-8 |
| encoding scheme.</p> |
| </div> |
| <div class="paragraph"> |
| <p>After preprocessing, only the following characters are allowed in the |
| resulting stream of GLSL tokens:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The letters <strong>a-z</strong>, <strong>A-Z</strong>, and the underscore (<strong>_</strong>).</p> |
| </li> |
| <li> |
| <p>The numbers <strong>0-9</strong>.</p> |
| </li> |
| <li> |
| <p>The symbols period (<strong>.</strong>), plus (<strong>+</strong>), dash (<strong>-</strong>), slash (<strong>/</strong>), asterisk |
| (<strong>*</strong>), percent (<strong>%</strong>), angled brackets (<strong><</strong> and <strong>></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>&</strong>), tilde (<strong>~</strong>), equals (<strong>=</strong>), |
| exclamation point (<strong>!</strong>), colon (<strong>:</strong>), semicolon (<strong>;</strong>), comma (<strong>,</strong>), and |
| question mark (<strong>?</strong>).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A compile-time error will be given if any other character is used in a GLSL |
| token.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are no digraphs or trigraphs. |
| There are no escape sequences or other uses of the backslash beyond use as |
| the line-continuation character.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Lines are relevant for compiler diagnostic messages and the preprocessor. |
| They are terminated by carriage-return or line-feed. |
| If both are used together, it will count as only a single line termination. |
| For the remainder of this document, any of these combinations is simply |
| referred to as a new-line. |
| Lines may be of arbitrary length.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, the language’s use of this character set is case sensitive.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are no character or string data types, so no quoting characters are |
| included.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is no end-of-file character.</p> |
| </div> |
| <div class="paragraph"> |
| <p>More formally, compilation happens as if the following logical phases were |
| executed in order:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Source strings are concatenated to form a single input. |
| All provided new-lines are retained.</p> |
| </li> |
| <li> |
| <p>Line numbering is noted, based on all present new-lines, and does not |
| change when new-lines are later eliminated.</p> |
| </li> |
| <li> |
| <p>Wherever a backslash ('\') occurs immediately before a new-line, both |
| are eliminated. |
| (Note no white space is substituted, allowing a single token to span a |
| new-line.) Any newly formed backslash followed by a new-line is not |
| eliminated; only those pairs originally occurring after phase 1 are |
| eliminated.</p> |
| </li> |
| <li> |
| <p>All comments are replaced with a single space. |
| (Note that '//' style comments end before their terminating new-lines |
| and white space is generally relevant to preprocessing.)</p> |
| </li> |
| <li> |
| <p>Preprocessing is done, resulting in a sequence of GLSL tokens, formed |
| from the character set stated above.</p> |
| </li> |
| <li> |
| <p>GLSL processing is done on the sequence of GLSL tokens.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>Details that fully define source strings, comments, line numbering, new-line |
| elimination, and preprocessing are all discussed in upcoming sections. |
| Sections beyond those describe GLSL processing.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="source-strings">3.2. Source Strings</h3> |
| <div class="paragraph"> |
| <p>The source for a single shader is an array of strings of characters from the |
| character set. |
| A single shader is made from the concatenation of these strings. |
| Each string can contain multiple lines, separated by new-lines. |
| No new-lines need be present in a string; a single line can be formed from |
| multiple strings. |
| No new-lines or other characters are inserted by the implementation when it |
| concatenates the strings to form a single shader. |
| Multiple shaders can be linked together to form a single program.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Diagnostic messages returned from compiling a shader must identify both the |
| line number within a string and which source string the message applies to. |
| Source strings are counted sequentially with the first string being string |
| 0. |
| Line numbers are one more than the number of new-lines that have been |
| processed, including counting the new-lines that will be removed by the |
| line-continuation character (<strong>\</strong>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Lines separated by the line-continuation character preceding a new-line are |
| concatenated together before either comment processing or preprocessing. |
| This means that no white space is substituted for the line-continuation |
| character. |
| That is, a single token could be formed by the concatenation by taking the |
| characters at the end of one line concatenating them with the characters at |
| the beginning of the next line.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> f\ |
| oo; |
| <span class="comment">// forms a single line equivalent to "float foo;"</span> |
| <span class="comment">// (assuming '\' is the last character before the new-line and "oo" are</span> |
| <span class="comment">// the first two characters of the next line)</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="preprocessor">3.3. Preprocessor</h3> |
| <div class="paragraph"> |
| <p>There is a preprocessor that processes the source strings as part of the |
| compilation process. |
| Except as noted below, it behaves as the C++ standard preprocessor (see |
| “<a href="#references">Normative References</a>”).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The complete list of preprocessor directives is as follows.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>#<br> |
| #define<br> |
| #undef<br></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>#if<br> |
| #ifdef<br> |
| #ifndef<br> |
| #else<br> |
| #elif<br> |
| #endif<br></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>#error<br> |
| #pragma<br></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>#extension<br> |
| #version<br></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>#line</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The following |
| operators are |
| also available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>defined<br> |
| ##</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Each number sign (<strong>#</strong>) can be preceded in its line only by spaces or |
| horizontal tabs. |
| It may also be followed by spaces and horizontal tabs, preceding the |
| directive. |
| Each directive is terminated by a new-line. |
| Preprocessing does not change the number or relative location of new-lines |
| in a source string. |
| Preprocessing takes places after new-lines have been removed by the |
| line-continuation character.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The number sign (<strong>#</strong>) on a line by itself is ignored. |
| Any directive not listed above will cause a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>#define</strong> and <strong>#undef</strong> functionality are defined as is standard for C++ |
| preprocessors for macro definitions both with and without macro parameters.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following predefined macros are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>__LINE__<br> |
| __FILE__<br> |
| __VERSION__<br></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>__LINE__ will substitute a decimal integer constant that is one more than |
| the number of preceding new-lines in the current source string.</p> |
| </div> |
| <div class="paragraph"> |
| <p>__FILE__ will substitute a decimal integer constant that says which source |
| string number is currently being processed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>__VERSION__ will substitute a decimal integer reflecting the version |
| number of the OpenGL Shading Language. |
| The version of the shading language described in this document will have |
| __VERSION__ substitute the decimal integer 460.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By convention, all macro names containing two consecutive underscores (__) |
| are reserved for use by underlying software layers. |
| Defining |
| or undefining |
| such a name in a shader does not itself result in an error, but may |
| result in unintended behaviors that stem from having multiple definitions of |
| the same name. |
| All macro names prefixed with “GL_” (“GL” followed by a single |
| underscore) are also reserved, and defining |
| or undefining |
| such a name results in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations must support macro-name lengths of up to 1024 characters. |
| Implementations are allowed to generate an error for a macro name of length |
| greater than 1024 characters, but are also allowed to support lengths |
| greater than 1024.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>#if</strong>, <strong>#ifdef</strong>, <strong>#ifndef</strong>, <strong>#else</strong>, <strong>#elif</strong>, and <strong>#endif</strong> are defined to |
| operate as is standard for C++ preprocessors except for the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Expressions following <strong>#if</strong> and <strong>#elif</strong> are |
| further restricted to |
| expressions operating on literal integer constants, plus identifiers |
| consumed by the <strong>defined</strong> operator.</p> |
| </li> |
| <li> |
| <p>Character constants are not supported.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The operators available are as follows.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Precedence</th> |
| <th class="tableblock halign-left valign-top">Operator class</th> |
| <th class="tableblock halign-left valign-top">Operators</th> |
| <th class="tableblock halign-left valign-top">Associativity</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1 (highest)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">parenthetical grouping</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">( )</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">NA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unary</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">defined<br> |
| + - ~ !</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">multiplicative</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">* / %</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">additive</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">+ -</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise shift</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><< >></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">< > <= >=</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">&</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">&&</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">12 (lowest)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">logical inclusive or</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">||</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The <strong>defined</strong> operator can be used in either of the following ways:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">defined identifier |
| defined ( identifier )</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Two tokens in a macro can be concatenated into one token using the token |
| pasting (<strong>##</strong>) operator, as is standard for C++ preprocessors. |
| The result must be a valid single token, which will then be subject to macro |
| expansion. |
| That is, macro expansion happens only after token pasting. |
| There are no other number sign based operators (e.g. no <strong>#</strong> or <strong>#@</strong>), nor is |
| there a <strong>sizeof</strong> operator.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The semantics of applying operators to integer literals in the preprocessor |
| match those standard in the C++ preprocessor, not those in the OpenGL Shading Language.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Preprocessor expressions will be evaluated according to the behavior of the |
| host processor, not the processor targeted by the shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>#error</strong> will cause the implementation to put a compile-time diagnostic message |
| into the shader object’s information log (see section 7.12 “Shader, Program |
| and Program Pipeline Queries” of the <a href="#references">OpenGL Specification</a> for how to |
| access a shader object’s information log). |
| The message will be the tokens following the <strong>#error</strong> directive, up to the |
| first new-line. |
| The implementation must treat the presence of a <strong>#error</strong> directive as a |
| compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>#pragma</strong> allows implementation-dependent compiler control. |
| Tokens following <strong>#pragma</strong> are not subject to preprocessor macro expansion. |
| If an implementation does not recognize the tokens following <strong>#pragma</strong>, then |
| it will ignore that pragma. |
| The following pragmas are defined as part of the language.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> STDGL</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>STDGL</strong> pragma is used to reserve pragmas for use by future revisions of |
| this language. |
| No implementation may use a pragma whose first token is <strong>STDGL</strong>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> optimize(on) |
| <span class="preprocessor">#pragma</span> optimize(off)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to turn off optimizations as an aid in developing and debugging |
| shaders. |
| It can only be used outside function definitions. |
| By default, optimization is turned on for all shaders. |
| The debug pragma</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> debug(on) |
| <span class="preprocessor">#pragma</span> debug(off)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to enable compiling and annotating a shader with debug |
| information, so that it can be used with a debugger. |
| It can only be used outside function definitions. |
| By default, debug is turned off.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shaders should declare the version of the language they are written to. |
| The language version a shader is written to is specified by</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#version</span> number profile_opt</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>number</em> must be a version of the language, following the same |
| convention as __VERSION__ above. |
| The directive “<strong>#version 460</strong>” is required in any shader that |
| uses version 4.60 of the language. |
| Any <em>number</em> representing a version of the language a compiler does not |
| support will cause a compile-time error to be generated. |
| Version 1.10 of the language does not require shaders to include this |
| directive, and shaders that do not include a <strong>#version</strong> directive will be |
| treated as targeting version 1.10. |
| Shaders that specify <strong>#version</strong> 100 will be treated as targeting version |
| 1.00 of the OpenGL ES Shading Language. |
| Shaders that specify <strong>#version</strong> 300 will be treated as targeting version |
| 3.00 of the OpenGL ES Shading Language. |
| Shaders that specify <strong>#version</strong> 310 will be treated as targeting version |
| 3.10 of the OpenGL ES Shading Language.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the optional <em>profile</em> argument is provided, it must be the name of an |
| OpenGL profile. |
| Currently, there are three choices:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">core |
| compatibility |
| es</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A <em>profile</em> argument can only be used with version 150 or greater. |
| If no profile argument is provided and the version is 150 or greater, the |
| default is <strong>core</strong>. |
| If version 300 or 310 is specified, the profile argument is not optional and |
| must be <strong>es</strong>, or a compile-time error results. |
| The Language Specification for the <strong>es</strong> profile is specified in The OpenGL |
| ES Shading Language specification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shaders for the <strong>core</strong> or <strong>compatibility</strong> profiles that declare different |
| versions can be linked together. |
| However, <strong>es</strong> profile shaders cannot be linked with non-<strong>es</strong> profile shaders |
| or with <strong>es</strong> profile shaders of a different version, or a link-time error |
| will result. |
| When linking shaders of versions allowed by these rules, remaining link-time |
| errors will be given as per the linking rules in the GLSL version |
| corresponding to the version of the context the shaders are linked under. |
| Shader compile-time errors must still be given strictly based on the version |
| declared (or defaulted to) within each shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unless otherwise specified, this specification is documenting the core |
| profile, and everything specified for the core profile is also available in |
| the compatibility profile. |
| Features specified as belonging specifically to the compatibility profile |
| are not available in the core profile. |
| Compatibility-profile features are not available when generating SPIR-V.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is a built-in macro definition for each profile the implementation |
| supports. |
| All implementations provide the following macro:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_core_profile <span class="integer">1</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations providing the <strong>compatibility</strong> profile provide the following |
| macro:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_compatibility_profile <span class="integer">1</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations providing the <strong>es</strong> profile provide the following macro:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_es_profile <span class="integer">1</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>#version</strong> directive must occur in a shader before anything else, except |
| for comments and white space.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By default, compilers of this language must issue compile-time |
| lexical |
| and |
| grammatical errors for shaders that do not conform to this specification. |
| Any extended behavior must first be enabled. |
| Directives to control the behavior of the compiler with respect to |
| extensions are declared with the <strong>#extension</strong> directive</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#extension</span> extension_name : behavior |
| <span class="preprocessor">#extension</span> all : behavior</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>extension_name</em> is the name of an extension. |
| Extension names are not documented in this specification. |
| The token <strong>all</strong> means the behavior applies to all extensions supported by |
| the compiler. |
| The <em>behavior</em> can be one of the following:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Behavior</th> |
| <th class="tableblock halign-left valign-top">Effect</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>require</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>.<br> |
| Give a compile-time error on the <strong>#extension</strong> if the extension |
| <em>extension_name</em> is not supported, or if <strong>all</strong> is specified.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>enable</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>.<br> |
| Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is |
| not supported.<br> |
| Give a compile-time error on the <strong>#extension</strong> if <strong>all</strong> is |
| specified.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>warn</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Behave as specified by the extension <em>extension_name</em>, |
| except issue warnings on any detectable use of that extension, |
| unless such use is supported by other enabled or required |
| extensions.<br> |
| If <strong>all</strong> is specified, then warn on all detectable uses of any |
| extension used.<br> |
| Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is |
| not supported.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>disable</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Behave (including issuing errors and warnings) as if the |
| extension <em>extension_name</em> is not part of the language |
| definition.<br> |
| If <strong>all</strong> is specified, then behavior must revert back to that |
| of the non-extended core version of the language being |
| compiled to.<br> |
| Warn on the <strong>#extension</strong> if the extension <em>extension_name</em> is |
| not supported.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The <strong>extension</strong> directive is a simple, low-level mechanism to set the |
| behavior for each extension. |
| It does not define policies such as which combinations are appropriate, |
| those must be defined elsewhere. |
| Order of directives matters in setting the behavior for each extension: |
| Directives that occur later override those seen earlier. |
| The <strong>all</strong> variant sets the behavior for all extensions, overriding all |
| previously issued <strong>extension</strong> directives, but only for the <em>behaviors</em> |
| <strong>warn</strong> and <strong>disable</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The initial state of the compiler is as if the directive</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#extension</span> all : disable</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>was issued, telling the compiler that all error and warning reporting must |
| be done according to this specification, ignoring any extensions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each extension can define its allowed granularity of scope. |
| If nothing is said, the granularity is a shader (that is, a single |
| compilation unit), and the extension directives must occur before any |
| non-preprocessor tokens. |
| If necessary, the linker can enforce granularities larger than a single |
| compilation unit, in which case each involved shader will have to contain |
| the necessary extension directive.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Macro expansion is not done on lines containing <strong>#extension</strong> and <strong>#version</strong> |
| directives.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>#line</strong> must have, after macro substitution, one of the following forms:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#line</span> line |
| <span class="preprocessor">#line</span> line source-<span class="predefined-type">string</span>-number</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>line</em> and <em>source-string-number</em> are |
| constant integer expressions. |
| If these constant expressions are not integer literals then behavior is undefined. |
| After processing this directive (including its new-line), the implementation |
| will behave as if it is compiling at line number <em>line</em> and source string |
| number <em>source-string-number</em>. |
| Subsequent source strings will be numbered sequentially, until another |
| <strong>#line</strong> directive overrides that numbering.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| <div class="title">Note</div> |
| <div class="paragraph"> |
| <p>Some implementations have allowed constant expressions in #line directives and |
| some have not. Even where expressions are supported the grammar is ambiguous and so |
| results are implementation dependent. For example, |
| + #line +2 +2 // Line number set to 4, or file to 2 and line to 2</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>When shaders are compiled for OpenGL SPIR-V, the following predefined |
| macro is available:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_SPIRV <span class="integer">100</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan, the following predefined macro is available:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> VULKAN <span class="integer">100</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="comments">3.4. Comments</h3> |
| <div class="paragraph"> |
| <p>Comments are delimited by <strong>/*</strong> and <strong>*/</strong>, or by <strong>//</strong> and a new-line. |
| The begin comment delimiters (/* or //) are not recognized as comment |
| delimiters inside of a comment, hence comments cannot be nested. |
| A <strong>/*</strong> comment includes its terminating delimiter (*/). |
| However, a <strong>//</strong> comment does not include (or eliminate) its terminating new |
| line.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Inside comments, any byte values may be used, except a byte whose value is |
| 0. |
| No errors will be given for the content of comments and no validation on the |
| content of comments need be done.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Removal of new-lines by the line-continuation character (<strong>\</strong>) logically |
| occurs before comments are processed. |
| That is, a single-line comment ending in the line-continuation character |
| (<strong>\</strong>) includes the next line in the comment.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// a single-line comment containing the next line \ |
| a = b; // this is still in the first comment</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="tokens">3.5. Tokens</h3> |
| <div class="paragraph"> |
| <p>The language, after preprocessing, is a sequence of tokens. |
| A token can be</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>token</em> : </dt> |
| <dd> |
| <p><em>keyword</em><br> |
| <em>identifier</em><br> |
| <em>integer-constant</em><br> |
| <em>floating-constant</em><br> |
| <em>operator</em><br> |
| <strong>;</strong> <strong>{</strong> <strong>}</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="keywords">3.6. Keywords</h3> |
| <div class="paragraph"> |
| <p>The following are the keywords in the language and (after |
| preprocessing) can only be used as described in this specification, |
| or a compile-time error results:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>const</strong> <strong>uniform</strong> <strong>buffer</strong> <strong>shared</strong> |
| <strong>attribute</strong> <strong>varying</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>coherent</strong> <strong>volatile</strong> <strong>restrict</strong> <strong>readonly</strong> <strong>writeonly</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>atomic_uint</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>layout</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>centroid</strong> <strong>flat</strong> <strong>smooth</strong> |
| <strong>noperspective</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>patch</strong> <strong>sample</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>invariant</strong> <strong>precise</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>break</strong> <strong>continue</strong> <strong>do</strong> <strong>for</strong> <strong>while</strong> <strong>switch</strong> <strong>case</strong> <strong>default</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>if</strong> <strong>else</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>subroutine</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>in</strong> <strong>out</strong> <strong>inout</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>int</strong> <strong>void</strong> <strong>bool</strong> <strong>true</strong> <strong>false</strong> <strong>float</strong> |
| <strong>double</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>discard</strong> <strong>return</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>vec2</strong> <strong>vec3</strong> <strong>vec4</strong> <strong>ivec2</strong> <strong>ivec3</strong> <strong>ivec4</strong> <strong>bvec2</strong> <strong>bvec3</strong> <strong>bvec4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>uint</strong> <strong>uvec2</strong> <strong>uvec3</strong> <strong>uvec4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>dvec2</strong> <strong>dvec3</strong> <strong>dvec4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>mat2</strong> <strong>mat3</strong> <strong>mat4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>mat2x2</strong> <strong>mat2x3</strong> <strong>mat2x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>mat3x2</strong> <strong>mat3x3</strong> <strong>mat3x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>mat4x2</strong> <strong>mat4x3</strong> <strong>mat4x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>dmat2</strong> <strong>dmat3</strong> <strong>dmat4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>dmat2x2</strong> <strong>dmat2x3</strong> <strong>dmat2x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>dmat3x2</strong> <strong>dmat3x3</strong> <strong>dmat3x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>dmat4x2</strong> <strong>dmat4x3</strong> <strong>dmat4x4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>lowp</strong> <strong>mediump</strong> <strong>highp</strong> <strong>precision</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler1D</strong> <strong>sampler1DShadow</strong> <strong>sampler1DArray</strong> <strong>sampler1DArrayShadow</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>isampler1D</strong> <strong>isampler1DArray</strong> <strong>usampler1D</strong> <strong>usampler1DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler2D</strong> <strong>sampler2DShadow</strong> <strong>sampler2DArray</strong> <strong>sampler2DArrayShadow</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>isampler2D</strong> <strong>isampler2DArray</strong> <strong>usampler2D</strong> <strong>usampler2DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler2DRect</strong> <strong>sampler2DRectShadow</strong> <strong>isampler2DRect</strong> <strong>usampler2DRect</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler2DMS</strong> <strong>isampler2DMS</strong> <strong>usampler2DMS</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler2DMSArray</strong> <strong>isampler2DMSArray</strong> <strong>usampler2DMSArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler3D</strong> <strong>isampler3D</strong> <strong>usampler3D</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>samplerCube</strong> <strong>samplerCubeShadow</strong> <strong>isamplerCube</strong> <strong>usamplerCube</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>samplerCubeArray</strong> <strong>samplerCubeArrayShadow</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>isamplerCubeArray</strong> <strong>usamplerCubeArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>samplerBuffer</strong> <strong>isamplerBuffer</strong> <strong>usamplerBuffer</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image1D</strong> <strong>iimage1D</strong> <strong>uimage1D</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image1DArray</strong> <strong>iimage1DArray</strong> <strong>uimage1DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image2D</strong> <strong>iimage2D</strong> <strong>uimage2D</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image2DArray</strong> <strong>iimage2DArray</strong> <strong>uimage2DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image2DRect</strong> <strong>iimage2DRect</strong> <strong>uimage2DRect</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image2DMS</strong> <strong>iimage2DMS</strong> <strong>uimage2DMS</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image2DMSArray</strong> <strong>iimage2DMSArray</strong> <strong>uimage2DMSArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>image3D</strong> <strong>iimage3D</strong> <strong>uimage3D</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>imageCube</strong> <strong>iimageCube</strong> <strong>uimageCube</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>imageCubeArray</strong> <strong>iimageCubeArray</strong> <strong>uimageCubeArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>imageBuffer</strong> <strong>iimageBuffer</strong> <strong>uimageBuffer</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>struct</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, when targeting Vulkan, the following keywords also exist:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture1D</strong> <strong>texture1DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>itexture1D</strong> <strong>itexture1DArray</strong> <strong>utexture1D</strong> <strong>utexture1DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture2D</strong> <strong>texture2DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>itexture2D</strong> <strong>itexture2DArray</strong> <strong>utexture2D</strong> <strong>utexture2DArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture2DRect</strong> <strong>itexture2DRect</strong> <strong>utexture2DRect</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture2DMS</strong> <strong>itexture2DMS</strong> <strong>utexture2DMS</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture2DMSArray</strong> <strong>itexture2DMSArray</strong> <strong>utexture2DMSArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>texture3D</strong> <strong>itexture3D</strong> <strong>utexture3D</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>textureCube</strong> <strong>itextureCube</strong> <strong>utextureCube</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>textureCubeArray</strong> <strong>itextureCubeArray</strong> <strong>utextureCubeArray</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>textureBuffer</strong> <strong>itextureBuffer</strong> <strong>utextureBuffer</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler</strong> <strong>samplerShadow</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>subpassInput</strong> <strong>isubpassInput</strong> <strong>usubpassInput</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>subpassInputMS</strong> <strong>isubpassInputMS</strong> <strong>usubpassInputMS</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The following are the keywords reserved for future use. |
| Using them will result in a compile-time error:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>common</strong> <strong>partition</strong> <strong>active</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>asm</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>class</strong> <strong>union</strong> <strong>enum</strong> <strong>typedef</strong> <strong>template</strong> <strong>this</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>resource</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>goto</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>inline</strong> <strong>noinline</strong> <strong>public</strong> <strong>static</strong> <strong>extern</strong> <strong>external</strong> <strong>interface</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>long</strong> <strong>short</strong> <strong>half</strong> <strong>fixed</strong> <strong>unsigned</strong> <strong>superp</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>input</strong> <strong>output</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>hvec2</strong> <strong>hvec3</strong> <strong>hvec4</strong> <strong>fvec2</strong> <strong>fvec3</strong> <strong>fvec4</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>filter</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sizeof</strong> <strong>cast</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>namespace</strong> <strong>using</strong></p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><strong>sampler3DRect</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, all identifiers containing two consecutive underscores (__) |
| are reserved for use by underlying software layers. |
| Defining such a name in a shader does not itself result in an error, but may |
| result in unintended behaviors that stem from having multiple definitions of |
| the same name.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="identifiers">3.7. Identifiers</h3> |
| <div class="paragraph"> |
| <p>Identifiers are used for variable names, function names, structure names, |
| and field selectors (field selectors select components of |
| <code><a href="#vector-components">vectors</a></code> and <code><a href="#matrix-components">matrices</a></code>, |
| similarly to structure members). |
| Identifiers have the form:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>identifier</em> : </dt> |
| <dd> |
| <p><em>nondigit</em><br> |
| <em>identifier</em> <em>nondigit</em><br> |
| <em>identifier</em> <em>digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>nondigit</em> : one of </dt> |
| <dd> |
| <p><strong>_</strong> <strong>a b c d e f g h i j k l m n o p q r s t u v w x y z</strong><br> |
| <strong>A B C D E F G H I J K L M N O P Q R S T U V W X Y Z</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>digit</em> : one of </dt> |
| <dd> |
| <p><strong>0 1 2 3 4 5 6 7 8 9</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Identifiers starting with “gl_” are reserved, and |
| in general, may not be declared in a shader; |
| this results in a compile-time error. |
| However, as noted in the specification, there are some cases where |
| previously declared variables can be redeclared, and predeclared “gl_” |
| names are allowed to be redeclared in a shader only for these specific |
| purposes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Implementations must support identifier lengths of up to 1024 characters. |
| Implementations are allowed to generate an error for an identifier of length |
| greater than 1024 characters, but are also allowed to support lengths |
| greater than 1024.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="definitions">3.8. Definitions</h3> |
| <div class="paragraph"> |
| <p>Some language rules described below depend on the following definitions.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="static-use">3.8.1. Static Use</h4> |
| <div class="paragraph"> |
| <p>A shader contains a <em>static use</em> of a variable <em>x</em> if, after preprocessing, |
| the shader contains a statement that would access any part of <em>x</em>, |
| whether or not flow of control will cause that statement to be executed. |
| Such a variable is referred to as being <em>statically used</em>. If the access is a |
| write then <em>x</em> is further said to be <em>statically assigned</em>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="dynamically-uniform-expressions-and-uniform-control-flow">3.8.2. Dynamically Uniform Expressions and Uniform Control Flow</h4> |
| <div class="paragraph"> |
| <p>Some operations require an expression to be <em>dynamically uniform</em>, or that |
| it be located in <em>uniform control flow</em>. |
| These requirements are defined by the following set of definitions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An <em>invocation</em> is a single execution of <em>main()</em> for a particular stage, |
| operating only on the amount of data explicitly exposed within that stage’s |
| shaders. |
| (Any implicit operation on additional instances of data would comprise |
| additional invocations.) For example, in compute execution models, a single |
| invocation operates only on a single work item, or, in a vertex execution |
| model, a single invocation operates only on a single vertex.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An <em>invocation group</em> is the complete set of invocations collectively |
| processing a particular compute workgroup or graphical operation, where the |
| scope of a "graphical operation" is implementation-dependent, but at least |
| as large as a single triangle or patch, and at most as large as a single |
| rendering command, as defined by the client API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Within a single invocation, a single shader statement can be executed |
| multiple times, giving multiple <em>dynamic instances</em> of that instruction. |
| This can happen when the instruction is executed in a loop, or in a function |
| called from multiple call sites, or combinations of multiple of these. |
| Different loop iterations and different dynamic function-call-site chains |
| yield different dynamic instances of such an instruction. |
| Dynamic instances are distinguished by their control-flow path within an |
| invocation, not by which invocation executed it. |
| That is, different invocations of <em>main()</em> execute the same dynamic |
| instances of an instruction when they follow the same control-flow path.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An expression is <em>dynamically uniform</em> for a dynamic instance consuming it |
| when its value is the same for all invocations (in the invocation group) |
| that execute that dynamic instance.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>Uniform control flow</em> (or converged control flow) occurs when all |
| invocations in the invocation group execute the same control-flow path (and |
| hence the same sequence of dynamic instances of instructions). |
| Uniform control flow is the initial state at the entry into <em>main()</em>, and |
| lasts until a conditional branch takes different control paths for different |
| invocations (non-uniform or divergent control flow). |
| Such divergence can reconverge, with all the invocations once again |
| executing the same control-flow path, and this re-establishes the existence |
| of uniform control flow. |
| If control flow is uniform upon entry into a selection or loop, and all |
| invocations in the invocation group subsequently leave that selection or |
| loop, then control flow reconverges to be uniform.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">main() |
| { |
| <span class="predefined-type">float</span> a = ...; <span class="comment">// this is uniform control flow</span> |
| <span class="keyword">if</span> (a < b) { <span class="comment">// this expression is true for some fragments, not all</span> |
| ...; <span class="comment">// non-uniform control flow</span> |
| } <span class="keyword">else</span> { |
| ...; <span class="comment">// non-uniform control flow</span> |
| } |
| ...; <span class="comment">// uniform control flow again</span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note that constant expressions are trivially dynamically uniform. |
| It follows that typical loop counters based on these are also dynamically |
| uniform.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="variables-and-types">4. Variables and Types</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>All variables and functions must be declared before being used. |
| Variable and function names are identifiers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are no default types. |
| All variable and function declarations must have a declared type, and |
| optionally qualifiers. |
| A variable is declared by specifying its type followed by one or more names |
| separated by commas. |
| In many cases, a variable can be initialized as part of its declaration by |
| using the assignment operator (<strong>=</strong>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>User-defined types may be defined using <strong>struct</strong> to aggregate a list of |
| existing types into a single name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language is type safe. |
| There are some implicit conversions between types. |
| Exactly how and when this can occur is described in section |
| “<a href="#implicit-conversions">Implicit Conversions</a>” and as referenced by other |
| sections in this specification.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="basic-types">4.1. Basic Types</h3> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Definition</dt> |
| <dd> |
| <p>A <em>basic type</em> is a type defined by a keyword in the language.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language supports the following basic data types, grouped as follows.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>Transparent Types</strong></p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>void</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">for functions that do not return a value</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bool</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a conditional type, taking on values of true or false</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a signed integer</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uint</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">an unsigned integer</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>float</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point scalar</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>double</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point scalar</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a two-component single-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a three-component single-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a four-component single-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a two-component double-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a three-component double-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a four-component double-precision floating-point vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a two-component Boolean vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a three-component Boolean vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>bvec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a four-component Boolean vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a two-component signed integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a three-component signed integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a four-component signed integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a two-component unsigned integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a three-component unsigned integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a four-component unsigned integer vector</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 2 × 2 single-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 3 × 3 single-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 4 × 4 single-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 2 columns and 3 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 2 columns and 4 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 3 columns and 2 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 3 columns and 4 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 4 columns and 2 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a single-precision floating-point matrix with 4 columns and 3 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>mat4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 2 × 2 double-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 3 × 3 double-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a 4 × 4 double-precision floating-point matrix</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 2 columns and 3 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 2 columns and 4 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 3 columns and 2 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 3 columns and 4 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 4 columns and 2 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a double-precision floating-point matrix with 4 columns and 3 rows</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as a <strong>dmat4</strong></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Note that where the following tables say “accessing a texture”, the |
| <strong>sampler*</strong> opaque types access textures, and the <strong>image*</strong> opaque types |
| access images, of a specified type.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>Floating-Point Opaque Types</strong></p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1D</strong><br> |
| <strong>texture1D</strong><br> |
| <strong>image1D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DArray</strong><br> |
| <strong>texture1DArray</strong><br> |
| <strong>image1DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler1DArrayShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 1D array depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2D</strong><br> |
| <strong>texture2D</strong><br> |
| <strong>image2D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DArray</strong><br> |
| <strong>texture2DArray</strong><br> |
| <strong>image2DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DArrayShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D array depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DMS</strong><br> |
| <strong>texture2DMS</strong><br> |
| <strong>image2DMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D multisample texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DMSArray</strong><br> |
| <strong>texture2DMSArray</strong><br> |
| <strong>image2DMSArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 2D multisample array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DRect</strong><br> |
| <strong>texture2DRect</strong><br> |
| <strong>image2DRect</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a rectangle texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler2DRectShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a rectangle texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler3D</strong><br> |
| <strong>texture3D</strong><br> |
| <strong>image3D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a 3D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCube</strong><br> |
| <strong>textureCube</strong><br> |
| <strong>imageCube</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube mapped texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeArray</strong><br> |
| <strong>textureCubeArray</strong><br> |
| <strong>imageCubeArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerCubeArrayShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a cube map array depth texture with comparison</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerBuffer</strong><br> |
| <strong>textureBuffer</strong><br> |
| <strong>imageBuffer</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a buffer texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>subpassInput</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a floating-point subpass input</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>subpassInputMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled floating-point subpass input</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>Signed Integer Opaque Types</strong></p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler1D</strong><br> |
| <strong>itexture1D</strong><br> |
| <strong>iimage1D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 1D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler1DArray</strong><br> |
| <strong>itexture1DArray</strong><br> |
| <strong>iimage1DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 1D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2D</strong><br> |
| <strong>itexture2D</strong><br> |
| <strong>iimage2D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DArray</strong><br> |
| <strong>itexture2DArray</strong><br> |
| <strong>iimage2DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DMS</strong><br> |
| <strong>itexture2DMS</strong><br> |
| <strong>iimage2DMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D multisample texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DMSArray</strong><br> |
| <strong>itexture2DMSArray</strong><br> |
| <strong>iimage2DMSArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D multisample array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler2DRect</strong><br> |
| <strong>itexture2DRect</strong><br> |
| <strong>iimage2DRect</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 2D rectangle texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isampler3D</strong><br> |
| <strong>itexture3D</strong><br> |
| <strong>iimage3D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer 3D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerCube</strong><br> |
| <strong>itextureCube</strong><br> |
| <strong>iimageCube</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer cube mapped texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerCubeArray</strong><br> |
| <strong>itextureCubeArray</strong><br> |
| <strong>iimageCubeArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer cube map array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isamplerBuffer</strong><br> |
| <strong>itextureBuffer</strong><br> |
| <strong>iimageBuffer</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer buffer texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isubpassInput</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an integer subpass input</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>isubpassInputMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled integer subpass input</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>Unsigned Integer Opaque Types</strong></p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler1D</strong><br> |
| <strong>utexture1D</strong><br> |
| <strong>uimage1D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 1D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler1DArray</strong><br> |
| <strong>utexture1DArray</strong><br> |
| <strong>uimage1DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 1D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2D</strong><br> |
| <strong>utexture2D</strong><br> |
| <strong>uimage2D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DArray</strong><br> |
| <strong>utexture1DArray</strong><br> |
| <strong>uimage2DArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DMS</strong><br> |
| <strong>utexture2DMS</strong><br> |
| <strong>uimage2DMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D multisample texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DMSArray</strong><br> |
| <strong>utexture2DMSArray</strong><br> |
| <strong>uimage2DMSArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 2D multisample array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler2DRect</strong><br> |
| <strong>utexture2DRect</strong><br> |
| <strong>uimage2DRect</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer rectangle texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usampler3D</strong><br> |
| <strong>utexture3D</strong><br> |
| <strong>uimage3D</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer 3D texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerCube</strong><br> |
| <strong>utextureCube</strong><br> |
| <strong>uimageCube</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer cube mapped texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerCubeArray</strong><br> |
| <strong>utextureCubeArray</strong><br> |
| <strong>uimageCubeArray</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer cube map array texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usamplerBuffer</strong><br> |
| <strong>utextureBuffer</strong><br> |
| <strong>uimageBuffer</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer buffer texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>atomic_uint</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned integer atomic counter</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usubpassInput</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing an unsigned-integer subpass input</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>usubpassInputMS</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing a multi-sampled unsigned-integer subpass input</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p><strong>Sampler Opaque Types</strong></p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sampler</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing state describing how to sample a texture</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>samplerShadow</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a handle for accessing state describing how to sample a depth |
| texture with comparison</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>In addition, a shader can aggregate these basic types using arrays and |
| structures to build more complex types.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are no pointer types.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this specification, an <em>aggregate</em> will mean a structure or array. |
| (Matrices and vectors are not by themselves aggregates.) Aggregates, |
| matrices, and vectors will collectively be referred to as <em>composites</em>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="void">4.1.1. Void</h4> |
| <div class="paragraph"> |
| <p>Functions that do not return a value must be declared as <strong>void</strong>. |
| There is no default function return type. |
| The keyword <strong>void</strong> cannot be used in any other declarations (except for |
| empty formal or actual parameter lists), or a compile-time error results.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="booleans">4.1.2. Booleans</h4> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Definition</dt> |
| <dd> |
| <p>A <em>boolean type</em> is any boolean scalar or vector type (<strong>bool</strong>, <strong>bvec2</strong>, |
| <strong>bvec3</strong>, <strong>bvec4</strong>)</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>To make conditional execution of code easier to express, the type <strong>bool</strong> is |
| supported. |
| There is no expectation that hardware directly supports variables of this |
| type. |
| It is a genuine Boolean type, holding only one of two values meaning either |
| true or false. |
| Two keywords <strong>true</strong> and <strong>false</strong> can be used as literal Boolean constants. |
| Booleans are declared and optionally initialized as in the follow example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">bool</span> success; <span class="comment">// declare "success" to be a Boolean</span> |
| <span class="predefined-type">bool</span> done = <span class="predefined-constant">false</span>; <span class="comment">// declare and initialize "done"</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Expressions used for conditional jumps (<strong>if</strong>, <strong>for</strong>, <strong>?:</strong>, <strong>while</strong>, |
| <strong>do</strong>-<strong>while</strong>) must evaluate to the type <strong>bool</strong>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="integers">4.1.3. Integers</h4> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Definitions</dt> |
| <dd> |
| <p>An <em>integral type</em> is any signed or unsigned, scalar or vector integer type. |
| It excludes arrays and structures.</p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>A <em>scalar integral type</em> is a scalar signed or unsigned integer type:</p> |
| </dd> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>A <em>vector integral type</em> is a vector of signed or unsigned integers:</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Signed and unsigned integer variables are fully supported. |
| In this document, the term <em>integer</em> is meant to generally include both |
| signed and unsigned integers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For OpenGL, unsigned integers have exactly 32 bits of precision. |
| When targeting Vulkan, <strong>highp</strong> |
| unsigned integers have exactly 32 bits of precision.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For OpenGL, signed integers use 32 bits, including a sign bit, in two’s complement form. |
| When targeting Vulkan, <strong>highp</strong> |
| signed integers use 32 bits, including a sign bit, in two’s complement form.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan, <strong>mediump</strong> and <strong>lowp</strong> integers are as defined by the |
| SPIR-V <strong>RelaxedPrecision</strong> decoration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Addition, |
| subtraction and multiplication resulting in overflow or |
| underflow will result in the low-order |
| 32 |
| bits of the correct result R, where |
| R is computed with enough precision to avoid overflow or underflow. |
| Division resulting in overflow will result in an undefined value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Integers are declared and optionally initialized with integer expressions, |
| as in the following example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i, j = <span class="integer">42</span>; <span class="comment">// default integer literal type is int</span> |
| uint k = <span class="integer">3</span>u; <span class="comment">// "u" establishes the type as uint</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Literal integer constants can be expressed in decimal (base 10), octal (base |
| 8), or hexadecimal (base 16) as follows.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>integer-constant</em> : </dt> |
| <dd> |
| <p><em>decimal-constant</em> <em>integer-suffix<sub>opt</sub></em><br> |
| <em>octal-constant</em> <em>integer-suffix<sub>opt</sub></em><br> |
| <em>hexadecimal-constant</em> <em>integer-suffix<sub>opt</sub></em></p> |
| </dd> |
| <dt class="hdlist1"><em>integer-suffix</em> : one of </dt> |
| <dd> |
| <p><strong>u</strong> <strong>U</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>decimal-constant</em> : </dt> |
| <dd> |
| <p><em>nonzero-digit</em><br> |
| <em>decimal-constant</em> <em>digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>octal-constant</em> : </dt> |
| <dd> |
| <p><strong>0</strong><br> |
| <em>octal-constant</em> <em>octal-digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>hexadecimal-constant</em> : </dt> |
| <dd> |
| <p><strong>0x</strong> <em>hexadecimal-digit</em><br> |
| <strong>0X</strong> <em>hexadecimal-digit</em><br> |
| <em>hexadecimal-constant</em> <em>hexadecimal-digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>digit</em> : </dt> |
| <dd> |
| <p><strong>0</strong><br> |
| <em>nonzero-digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>nonzero-digit</em> : one of </dt> |
| <dd> |
| <p><strong>1 2 3 4 5 6 7 8 9</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>octal-digit</em> : one of </dt> |
| <dd> |
| <p><strong>0 1 2 3 4 5 6 7</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>hexadecimal-digit</em> : one of </dt> |
| <dd> |
| <p><strong>0 1 2 3 4 5 6 7 8 9<br> |
| a b c d e f<br> |
| A B C D E F</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>No white space is allowed between the digits of an integer constant, |
| including after the leading <strong>0</strong> or after the leading <strong>0x</strong> or <strong>0X</strong> of a |
| constant, or before the suffix <strong>u</strong> or <strong>U</strong>. |
| When tokenizing, the maximal token matching the above will be recognized |
| before a new token is started. |
| When the suffix <strong>u</strong> or <strong>U</strong> is present, the literal has type <strong>uint</strong>, |
| otherwise the type is <strong>int</strong>. |
| A leading unary minus sign (-) is interpreted as an arithmetic unary |
| negation, not as part of the constant. |
| Hence, literals themselves are always expressed with non-negative syntax, |
| though they could result in a negative value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to provide a literal integer whose bit pattern |
| cannot fit in 32 bits. |
| The bit pattern of the literal is always used unmodified. |
| So a signed literal whose bit pattern includes a set sign bit creates a |
| negative value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="integer">1</span> <span class="comment">// OK. Signed integer, value 1</span> |
| <span class="integer">1</span>u <span class="comment">// OK. Unsigned integer, value 1</span> |
| -<span class="integer">1</span> <span class="comment">// OK. Unary minus applied to signed integer.</span> |
| <span class="comment">// result is a signed integer, value -1</span> |
| -<span class="integer">1</span>u <span class="comment">// OK. Unary minus applies to unsigned integer.</span> |
| <span class="comment">// Result is an unsigned integer, value 0xffffffff</span> |
| <span class="hex">0xA0000000</span> <span class="comment">// OK. 32-bit signed hexadecimal</span> |
| <span class="hex">0xABcdEF00</span>u <span class="comment">// OK. 32-bit unsigned hexadecimal</span> |
| <span class="hex">0xffffffff</span> <span class="comment">// OK. Signed integer, value -1</span> |
| <span class="hex">0x80000000</span> <span class="comment">// OK. Evaluates to -2147483648</span> |
| <span class="hex">0xffffffff</span>u <span class="comment">// OK. Unsigned integer, value 0xffffffff</span> |
| <span class="hex">0xfffffffff</span> <span class="comment">// Error: needs more than 32 bits</span> |
| <span class="integer">3000000000</span> <span class="comment">// OK. A signed decimal literal taking 32 bits.</span> |
| <span class="comment">// It evaluates to -1294967296</span> |
| <span class="integer">2147483648</span> <span class="comment">// OK. Evaluates to -2147483648 (the literal set the sign bit)</span> |
| <span class="integer">5000000000</span> <span class="comment">// Error: needs more than 32 bits</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="floats">4.1.4. Floats</h4> |
| <div class="paragraph"> |
| <p>Single-precision and double-precision floating-point variables are available |
| for use in a variety of scalar calculations. |
| Generally, the term <em>floating-point</em> will refer to both single- and |
| double-precision floating-point. |
| Floating-point variables are defined as in the following examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a, b = <span class="float">1</span><span class="float">.5</span>; <span class="comment">// single-precision floating-point</span> |
| <span class="predefined-type">double</span> c, d = <span class="float">2</span><span class="float">.0</span>LF; <span class="comment">// double-precision floating-point</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>As an input value to one of the processing units, a single-precision or |
| double-precision floating-point variable is expected to match the |
| corresponding IEEE 754 floating-point definition for precision and dynamic |
| range. |
| Floating-point variables within a shader are also encoded according to the |
| IEEE 754 specification for single-precision floating-point values</p> |
| </div> |
| <div class="paragraph"> |
| <p>(logically, not necessarily physically). |
| While encodings are logically IEEE 754, operations (addition, |
| multiplication, etc.) are not necessarily performed as required by IEEE 754. |
| See “<a href="#range-and-precision">Range and Precision</a>” for more details on |
| precision and usage of NaNs (Not a Number) and Infs (positive or negative |
| infinities).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Floating-point constants are defined as follows.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>floating-constant</em> : </dt> |
| <dd> |
| <p><em>fractional-constant</em> <em>exponent-part<sub>opt</sub></em> <em>floating-suffix<sub>opt</sub></em><br> |
| <em>digit-sequence</em> <em>exponent-part</em> <em>floating-suffix<sub>opt</sub></em></p> |
| </dd> |
| <dt class="hdlist1"><em>fractional-constant</em> : </dt> |
| <dd> |
| <p><em>digit-sequence</em> <strong>.</strong> <em>digit-sequence</em><br> |
| <em>digit-sequence</em> <strong>.</strong><br> |
| <strong>.</strong> <em>digit-sequence</em></p> |
| </dd> |
| <dt class="hdlist1"><em>exponent-part</em> : </dt> |
| <dd> |
| <p><strong>e</strong> <em>sign<sub>opt</sub></em> <em>digit-sequence</em><br> |
| <strong>E</strong> <em>sign<sub>opt</sub></em> <em>digit-sequence</em></p> |
| </dd> |
| <dt class="hdlist1"><em>sign</em> : one of </dt> |
| <dd> |
| <p><strong>+</strong> <strong>-</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>digit-sequence</em> : </dt> |
| <dd> |
| <p><em>digit</em><br> |
| <em>digit-sequence</em> <em>digit</em></p> |
| </dd> |
| <dt class="hdlist1"><em>floating-suffix</em> : one of </dt> |
| <dd> |
| <p> <strong>f</strong> <strong>F</strong> |
| <strong>lf</strong> <strong>LF</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A decimal point (<strong>.</strong>) is not needed if the exponent part is present. |
| No white space may appear anywhere within a floating-point constant, |
| including before a suffix. |
| When tokenizing, the maximal token matching the above will be recognized |
| before a new token is started. |
| When the suffix "lf" or "LF" is present, the literal has type <strong>double</strong>. |
| Otherwise, the literal has type <strong>float</strong>. |
| A leading unary minus sign (<strong>-</strong>) is interpreted as a unary operator and is |
| not part of the floating-point constant.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="vectors">4.1.5. Vectors</h4> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language includes data types for generic 2-, 3-, and 4-component vectors |
| of floating-point values, integers, and Booleans. |
| Floating-point vector variables can be used to store colors, normals, |
| positions, texture coordinates, texture lookup results and the like. |
| Boolean vectors can be used for component-wise comparisons of numeric |
| vectors. |
| Some examples of vector declarations are:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec2 texcoord1, texcoord2; |
| vec3 position; |
| vec4 myRGBA; |
| ivec2 textureLookup; |
| bvec3 less;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Initialization of vectors can be done with constructors. |
| See “<a href="#vector-and-matrix-constructors">Vector and Matrix Constructors</a>”.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="matrices">4.1.6. Matrices</h4> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language has built-in types for 2 × 2, 2 × 3, 2 × 4, 3 |
| × 2, 3 × 3, 3 × 4, 4 × 2, 4 × 3, and 4 × |
| 4 matrices of floating-point numbers. |
| Matrix types beginning with "<strong>mat</strong>" have single-precision components while |
| matrix types beginning with "<strong>dmat</strong>" have double-precision components. |
| The first number in the type is the number of columns, the second is the |
| number of rows. |
| If there is only one number, the matrix is square. |
| Example matrix declarations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat2 mat2D; |
| mat3 optMatrix; |
| mat4 view, projection; |
| mat4x4 view; <span class="comment">// an alternate way of declaring a mat4</span> |
| mat3x2 m; <span class="comment">// a matrix with 3 columns and 2 rows</span> |
| dmat4 highPrecisionMVP; |
| dmat2x4 dm;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Initialization of matrix values is done with constructors (described in |
| “<a href="#vector-and-matrix-constructors">Vector and Matrix Constructors</a>”) in |
| column-major order.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="opaque-types">4.1.7. Opaque Types</h4> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Definition</dt> |
| <dd> |
| <p>An <em>opaque type</em> is a type where the internal structure of the type is |
| hidden from the language.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The opaque types, as listed in the following sections, declare variables |
| that are effectively opaque handles to other objects. |
| These objects are accessed through built-in functions, not through direct |
| reading or writing of the declared variable. |
| They can only be declared as function parameters or in <strong>uniform</strong>-qualified |
| variables (see “<a href="#uniform-variables">Uniform Variables</a>”). |
| The only opaque types that take memory qualifiers are the image types. |
| Except for array indexing, structure member selection, and parentheses, |
| opaque variables are not allowed to be operands in expressions; such use |
| results in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Opaque variables cannot be treated as l-values; hence cannot be used as |
| <strong>out</strong> or <strong>inout</strong> function parameters, nor can they be assigned into. |
| Any such use results in a compile-time error. |
| However, they can be passed as <strong>in</strong> parameters with matching types and |
| memory qualifiers. |
| They cannot be declared with an initializer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Because a single opaque type declaration effectively declares two objects, |
| the opaque handle itself and the object it is a handle to, there is room for |
| both a storage qualifier and a memory qualifier. |
| The storage qualifier will qualify the opaque handle, while the memory |
| qualifier will qualify the object it is a handle to.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="samplers">Texture-Combined Samplers</h5> |
| <div class="paragraph"> |
| <p>Texture-combined sampler types (e.g. <strong>sampler2D</strong>) are the sampler types |
| described in the Basic Types tables as handles for accessing textures. |
| (They do not include <strong>sampler</strong> and <strong>samplerShadow</strong>.) |
| There are distinct texture-combined sampler types for each texture target, |
| and for each of float, integer, and unsigned integer data types. |
| Texture accesses are done through built-in texture functions (described in |
| “<a href="#texture-functions">Texture Functions</a>”) and texture-combined samplers |
| are used to specify which texture to access and how it is to be filtered.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Texture-combined sampler types are opaque types, |
| declared and behaving as described above for opaque types. |
| When aggregated into arrays within a shader, they can only be indexed |
| with a dynamically uniform integral expression, otherwise results are |
| undefined.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="images">Images</h5> |
| <div class="paragraph"> |
| <p>Image types are opaque types, declared and behaving as described above for |
| opaque types. |
| They can be further qualified with memory qualifiers. |
| When aggregated into arrays within a shader, images can only be indexed with |
| a dynamically uniform integral expression, otherwise results are undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Image variables are handles to |
| one-, |
| two-, or three-dimensional images |
| corresponding to all or a portion of a single level of a texture image bound |
| to an image unit. |
| There are distinct image variable types for each texture target, and for |
| each of float, integer, and unsigned integer data types. |
| Image accesses should use an image type that matches the target of the |
| texture whose level is bound to the image unit, or for non-layered bindings |
| of 3D or array images should use the image type that matches the |
| dimensionality of the layer of the image (i.e., a layer of 3D, 2DArray, |
| Cube, or CubeArray should use |
| <strong>image2D</strong>, a layer of 1DArray should use <strong>image1D</strong>, and a layer of 2DMSArray |
| should use <strong>image2DMS</strong>). |
| If the image target type does not match the bound image in this manner, if |
| the data type does not match the bound image, or if the format layout |
| qualifier does not match the image unit format as described in section |
| 8.25 |
| “Texture Image Loads and Stores” of the <a href="#references">OpenGL Specification</a>, the |
| results of image accesses are undefined but cannot include program |
| termination.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Image variables are used in the image load, store, and atomic functions |
| described in “<a href="#image-functions">Image Functions</a>” 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 |
| “<a href="#atomic-counter-functions">Atomic Counter Functions</a>”. |
| They are bound to buffers as described in |
| “<a href="#atomic-counter-layout-qualifiers">Atomic Counter Layout Qualifiers</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic counters aggregated into arrays within a shader can only be indexed |
| with dynamically uniform integral expressions, otherwise results are |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Members of structures cannot be declared as atomic counter types.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic counter types are not available when targeting Vulkan.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_texture_sampler_and_samplershadow_types">Texture, <strong>sampler</strong>, and <strong>samplerShadow</strong> Types</h5> |
| <div class="paragraph"> |
| <p>Texture (e.g., <strong>texture2D</strong>), <strong>sampler</strong>, and <strong>samplerShadow</strong> types are opaque |
| types, declared and behaving as described above for opaque types. |
| These types are only available when targeting Vulkan. |
| When aggregated into arrays within a shader, these types can only be indexed |
| with a dynamically uniform expression, or texture lookup will result in |
| undefined values. |
| Texture variables are handles to one-, two-, and three-dimensional textures, |
| cube maps, etc., as enumerated in the basic types tables. |
| There are distinct texture types for each texture target, and for each of |
| float, integer, and unsigned integer data types. |
| Textures can be combined with a variable of type <strong>sampler</strong> or <strong>samplerShadow</strong> |
| to create a texture-combined sampler type (e.g., sampler2D, or sampler2DShadow). |
| This is done with a constructor, e.g., <code>sampler2D(texture2D, sampler)</code>, |
| <code>sampler2DShadow(texture2D, sampler)</code>, <code>sampler2DShadow(texture2D, samplerShadow)</code>, |
| or <code>sampler2D(texture2D, samplerShadow)</code> and is described in more detail |
| in section 5.4 "Constructors".</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="_subpass_inputs">Subpass Inputs</h5> |
| <div class="paragraph"> |
| <p>Subpass-input types are only available when targeting Vulkan.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subpass-input types (e.g., <strong>subpassInput</strong>) are opaque types, declared |
| and behaving as described above for opaque types. |
| When aggregated into arrays within a shader, they can only be indexed with a |
| dynamically uniform integral expression, otherwise results are undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subpass-input types are handles to two-dimensional single sampled or |
| multi-sampled images, with distinct types for each of float, integer, |
| and unsigned integer data types.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subpass-input types are only available in fragment shaders. It is |
| a compile-time error to use them in any other stage.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="structures">4.1.8. Structures</h4> |
| <div class="paragraph"> |
| <p>User-defined types can be created by aggregating other already defined types |
| into a structure using the <strong>struct</strong> keyword. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> light { |
| <span class="predefined-type">float</span> intensity; |
| vec3 position; |
| } lightVar;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this example, <em>light</em> becomes the name of the new type, and <em>lightVar</em> |
| becomes a variable of type <em>light</em>. |
| To declare variables of the new type, use its name (without the keyword |
| <strong>struct</strong>).</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">light lightVar2;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>More formally, structures are declared as follows. |
| However, the definitive grammar is as given in |
| “<a href="#shading-language-grammar">Shading Language Grammar</a>”.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>struct-definition</em> : </dt> |
| <dd> |
| <p><em>qualifier<sub>opt</sub></em> <strong>struct</strong> name<sub>opt</sub>_ <strong>{</strong> <em>member-list</em> <strong>}</strong> |
| <em>declarators<sub>opt</sub></em> <strong>;</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>member-list</em> : </dt> |
| <dd> |
| <p><em>member-declaration</em> <strong>;</strong><br> |
| <em>member-declaration</em> <em>member-list</em> <strong>;</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>member-declaration</em> : </dt> |
| <dd> |
| <p><em>basic-type</em> <em>declarators</em> <strong>;</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>name</em> becomes the user-defined type, and can be used to declare |
| variables to be of this new type. |
| The <em>name</em> shares the same name space as other variables, types, and |
| functions. |
| All previously visible variables, types, constructors, or functions with |
| that name are hidden. |
| The optional <em>qualifier</em> only applies to any <em>declarators</em>, and is not part |
| of the type being defined for <em>name</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Structures must have at least one member declaration. |
| Member declarators may contain precision qualifiers, but use of any other |
| qualifier results in a compile-time error. |
| Bit fields are not supported. |
| Member types must be already defined (there are no forward references). |
| A compile-time error results if a member declaration contains an |
| initializer. |
| Member declarators can contain arrays. |
| Such arrays must have a size specified, and the size must be a constant |
| integral expression that’s greater than zero (see |
| “<a href="#constant-expressions">Constant Expressions</a>”). |
| Each level of structure has its own name space for names given in member |
| declarators; such names need only be unique within that name space.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Anonymous structures are not supported. |
| Embedded structure definitions are not supported. |
| These result in compile-time errors.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> S { <span class="predefined-type">float</span> f; }; <span class="comment">// Allowed: S is defined as a structure.</span> |
| |
| <span class="keyword">struct</span> T { |
| S; <span class="comment">// Error: anonymous structures disallowed</span> |
| <span class="keyword">struct</span> { ... }; <span class="comment">// Error: embedded structures disallowed</span> |
| S s; <span class="comment">// Allowed: nested structure with a name.</span> |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Structures can be initialized at declaration time using constructors, as |
| discussed in “<a href="#structure-constructors">Structure Constructors</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Any restrictions on the usage of a type or qualifier also apply to any |
| structure that contains a member of that type or qualifier. |
| This also applies to structure members that are structures, recursively.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="arrays">4.1.9. Arrays</h4> |
| <div class="paragraph"> |
| <p>Variables of the same type can be aggregated into arrays by declaring a name |
| followed by brackets (<strong>[ ]</strong>) enclosing an optional size. |
| When an array size is specified in a declaration, it must be an integral |
| constant expression (see “<a href="#constant-expressions">Constant Expressions</a>”) |
| greater than zero. |
| Except for the last declared member of a shader storage block (see section |
| “<a href="#interface-blocks">Interface Blocks</a>”), the size of an array must be |
| declared (<em>explicitly sized</em>) before it is indexed with anything other than |
| a constant integral expression. |
| The size of any array must be declared before passing it as an argument to a |
| function. |
| Violation of any of these rules result in compile-time errors. |
| It is legal to declare an array without a size (<em>unsized</em>) and then later |
| redeclare the same name as an array of the same type and specify a size, or |
| index it only with constant integral expressions (<em>implicitly sized</em>). |
| However, unless noted otherwise, blocks cannot be redeclared; an unsized |
| array member in a user-declared block cannot be sized by a block redeclaration. |
| It is a compile-time error to declare an array with a size, and then later |
| (in the same shader) index the same array with a constant integral |
| expression greater than or equal to the declared size. |
| It is a compile-time error to redeclare an unsized array with a size equal |
| to or smaller than any index used earlier in the shader to index the array. |
| It is also a compile-time error to index an array with a negative constant |
| expression. |
| Arrays declared as formal parameters in a function declaration must specify |
| a size. |
| Undefined behavior results from indexing an array with a non-constant |
| expression that’s greater than or equal to the array’s size or less than 0. |
| Arrays only have a single dimension (a single entry within "[ ]"), however, |
| arrays of arrays can be declared. |
| All types (basic types, structures, arrays) can be formed into an array.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All arrays are inherently homogeneous; made of elements all having the same |
| type and size, with one exception. |
| The exception is a shader storage block having an unsized array as its last |
| member (<em>run-time sized</em>); an array can be formed from such a shader storage |
| block, even if the storage blocks have differing lengths for their last |
| member.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Some examples are:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> frequencies[<span class="integer">3</span>]; |
| uniform vec4 lightPosition[<span class="integer">4</span>]; |
| light lights[]; |
| <span class="directive">const</span> <span class="predefined-type">int</span> numLights = <span class="integer">2</span>; |
| light lights[numLights]; |
| |
| <span class="comment">// a shader storage block, introduced in section 4.3.7 "Buffer Variables"</span> |
| buffer b { |
| <span class="predefined-type">float</span> u[]; <span class="comment">// an error, unless u gets statically sized by link time</span> |
| vec4 v[]; <span class="comment">// okay, v will be sized dynamically, if not statically</span> |
| } name[<span class="integer">3</span>]; <span class="comment">// when the block is arrayed, all u will be the same size,</span> |
| <span class="comment">// but not necessarily all v, if sized dynamically</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>An array type can be formed by specifying non-array type followed by an |
| array specifier. |
| All dimensions of such an array specifier must include a size.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] <span class="comment">// an array of size [5] of float</span> |
| <span class="predefined-type">float</span>[<span class="integer">2</span>][<span class="integer">3</span>] <span class="comment">// an array of size [2][3] of float, not size [3] of float[2]</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This type can be used anywhere any other type can be used, including as the |
| return value from a function</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] foo() { }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>as a constructor of an array:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>as an unnamed parameter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> foo(<span class="predefined-type">float</span>[<span class="integer">5</span>])</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>and as an alternate way of declaring a variable or function parameter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span>[<span class="integer">5</span>] a;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Arrays can have initializers formed from array constructors:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[<span class="integer">5</span>](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); |
| <span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); <span class="comment">// same thing</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>An array of arrays can be declared as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>]; <span class="comment">// size-3 array of size-2 array of vec4</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>which declares a one-dimensional array of size 3 of one-dimensional arrays |
| of size 2 of <strong>vec4</strong>. |
| The following declarations do the same thing:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4[<span class="integer">2</span>] a[<span class="integer">3</span>]; <span class="comment">// size-3 array of size-2 array of vec4</span> |
| vec4[<span class="integer">3</span>][<span class="integer">2</span>] a; <span class="comment">// size-3 array of size-2 array of vec4</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When in transparent memory (like in a uniform block), the layout is that the |
| inner-most (right-most in declaration) dimensions iterate faster than the |
| outer dimensions. |
| That is, for the above, the order in memory would be:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p>Low address : a[0][0] : a[0][1] : a[1][0] : a[1][1] : a[2][0] : a[2][1] |
| : High address</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The type of <em>a</em> needed for both constructors and nameless parameters is |
| “vec4[3][2]”:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 b[<span class="integer">2</span>] = vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">0</span><span class="float">.1</span>)); |
| vec4[<span class="integer">3</span>][<span class="integer">2</span>] a = vec4[<span class="integer">3</span>][<span class="integer">2</span>](b, b, b); <span class="comment">// constructor</span> |
| <span class="directive">void</span> foo(vec4[<span class="integer">3</span>][<span class="integer">2</span>]); <span class="comment">// prototype with unnamed parameter</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively, the initializer-list syntax can be used to initialize an |
| array of arrays:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>] = { vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)), |
| vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)), |
| vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)) };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Unsized arrays can be explicitly sized by an initializer at declaration |
| time:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>]; |
| ... |
| <span class="predefined-type">float</span> b[] = a; <span class="comment">// b is explicitly size 5</span> |
| <span class="predefined-type">float</span> b[<span class="integer">5</span>] = a; <span class="comment">// means the same thing</span> |
| <span class="predefined-type">float</span> b[] = <span class="predefined-type">float</span>[](<span class="integer">1</span>,<span class="integer">2</span>,<span class="integer">3</span>,<span class="integer">4</span>,<span class="integer">5</span>); <span class="comment">// also explicitly sizes to 5</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>However, it is a compile-time error to assign to an unsized array. |
| Note, this is a rare case that initializers and assignments appear to have |
| different semantics. |
| For arrays of arrays, any unsized dimension is explicitly sized by the |
| initializer:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 a[][] = { vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)), <span class="comment">// okay, size to a[3][2]</span> |
| vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)), |
| vec4[<span class="integer">2</span>](vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.0</span>)) };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Arrays know the number of elements they contain. |
| This can be obtained by using the <strong>length</strong>() method:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">5</span>]; |
| a.length(); <span class="comment">// returns 5</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This returns a type <strong>int</strong>. |
| If an array has been explicitly sized, the value returned by the <strong>length</strong>() |
| method is a constant expression. |
| If an array has not been explicitly sized and is the last declared member of |
| a shader storage block, the value returned will not be a constant expression |
| and will be determined at runtime based on the size of the buffer object |
| providing storage for the block. |
| Such arrays are runtime sized. |
| For runtime-sized arrays, the value returned by the <strong>length</strong>() method will be |
| undefined if the array is contained in an array of shader storage blocks |
| that is indexed with a non-constant expression less than zero or greater |
| than or equal to the number of blocks in the array.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>length</strong>() method cannot be called on an array that is not runtime sized |
| and also has not yet been explicitly sized; |
| this results in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the <strong>length</strong>() method returns a compile-time constant, the expression the |
| <strong>length</strong>() method is applied to cannot contain any side effects, such as writes |
| to l-values within the expression, or function calls that themselves have side |
| effects: only the compile-time constant length itself need be computed. |
| Behavior and results, including any compile-time error reporting, |
| are undefined if the expression contains other effects.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a, b; |
| <span class="directive">const</span> <span class="predefined-type">int</span> s = <span class="predefined-type">float</span>[<span class="integer">2</span>](a=<span class="float">3</span><span class="float">.0</span>, ++b).length(); <span class="comment">// illegal side effects</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>length</strong>() method works equally well for arrays of arrays:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 a[<span class="integer">3</span>][<span class="integer">2</span>]; |
| a.length() <span class="comment">// this is 3</span> |
| a[x].length() <span class="comment">// this is 2</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When the <strong>length</strong>() method returns a compile-time constant, the expression |
| in brackets (<em>x</em> above) will be parsed and subjected to the rules required for |
| array indices, but the array will not be dereferenced. |
| Thus, behavior is well defined even if the run-time value of the expression |
| is out of bounds, as long as the expression contains no side effects.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the <strong>length</strong>() method returns a run-time value |
| (not a compile-time constant), the array will be |
| dereferenced. |
| E.g., if <em>x</em> is not a compile-time constant and is out of range, an undefined |
| value results. |
| More generally, all involved expressions are fully evaluated and executed.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// for a compile time-sized array b containing a member array a:</span> |
| b[x+<span class="integer">3</span>].a.length(); <span class="comment">// b is never dereferenced, x+3 is evaluated and checked</span> |
| b[++x].a.length(); <span class="comment">// not allowed; results are undefined</span> |
| |
| <span class="comment">// for an array s of a shader storage object (run-time sized) containing a member array a:</span> |
| s[++x].a.length(); <span class="comment">// s is dereferenced; ++x needs to be a valid index</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For implicitly-sized or run-time-sized arrays, only the outer-most dimension |
| can be lacking a size. |
| A type that includes an unknown array size cannot be formed into an array |
| until it gets an explicit size, except for shader storage blocks where the |
| only unsized array member is the last member of the block.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In a shader storage block, the last member may be declared without an |
| explicit size. |
| In this case, the effective array size is inferred at run-time from the size |
| of the data store backing the interface block. |
| Such run-time-sized arrays may be indexed with general integer expressions. |
| However, it is a compile-time error to pass them as an argument to a |
| function or index them with a negative constant expression.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="implicit-conversions">4.1.10. Implicit Conversions</h4> |
| <div class="paragraph"> |
| <p>In some situations, an expression and its type will be implicitly converted |
| to a different type. |
| The following table shows all allowed implicit conversions:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Type of expression</th> |
| <th class="tableblock halign-left valign-top">Can be implicitly converted to</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uint</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong><br> |
| <strong>uint</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>float</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>int</strong><br> |
| <strong>uint</strong><br> |
| <strong>float</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>double</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uvec4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong><br> |
| <strong>uvec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong><br> |
| <strong>uvec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong><br> |
| <strong>uvec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>vec4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec2</strong><br> |
| <strong>uvec2</strong><br> |
| <strong>vec2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec3</strong><br> |
| <strong>uvec3</strong><br> |
| <strong>vec3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>ivec4</strong><br> |
| <strong>uvec4</strong><br> |
| <strong>vec4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dvec4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x3</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat2x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat2x4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat3x4</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat3x4</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x2</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x2</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mat4x3</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>dmat4x3</strong></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>There are no implicit array or structure conversions. |
| For example, an array of <strong>int</strong> cannot be implicitly converted to an array of |
| <strong>float</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When an implicit conversion is done, it is the same conversion that would be |
| done under explicit conversion, using a constructor. |
| The explicit conversions via constructors are described in |
| <a href="#conversion-and-scalar-constructors">Conversion and Scalar Constructors</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When performing implicit conversion for binary operators, there may be |
| multiple data types to which the two operands can be converted. |
| For example, when adding an <strong>int</strong> value to a <strong>uint</strong> value, both values can |
| be implicitly converted to <strong>uint</strong>, <strong>float</strong>, and <strong>double</strong>. |
| In such cases, a floating-point type is chosen if either operand has a |
| floating-point type. |
| Otherwise, an unsigned integer type is chosen if either operand has an |
| unsigned integer type. |
| Otherwise, a signed integer type is chosen. |
| If operands can be implicitly converted to multiple data types deriving from |
| the same base data type, the type with the smallest component size is used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The conversions in the table above are done only as indicated by other |
| sections of this specification.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="initializers">4.1.11. Initializers</h4> |
| <div class="paragraph"> |
| <p>At declaration, an initial value for a variable may be provided, specified |
| as an equals (=) followed by an initializer. |
| The initializer is either an <em>assignment-expression</em> or a list of |
| initializers enclosed in curly braces. |
| The grammar for the initializer is:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>initializer</em> : </dt> |
| <dd> |
| <p><em>assignment-expression</em><br> |
| <strong>{</strong> <em>initializer-list</em> <strong>}</strong><br> |
| <strong>{</strong> <em>initializer-list</em> <strong>,</strong> <strong>}</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>initializer-list</em> : </dt> |
| <dd> |
| <p><em>initializer</em><br> |
| <em>initializer-list</em> , <em>initializer</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>assignment-expression</em> is a normal expression except that a comma (<strong>,</strong>) |
| outside parentheses is interpreted as the end of the initializer, not as the |
| sequence operator. |
| As explained in more detail below, this allows creation of nested |
| initializers: The variable type and its initializer must exactly match in |
| terms of nesting, number of components/elements/members present at each |
| level, and types of components/elements/members. |
| An <em>assignment-expression</em> at global scope can include calls to user-defined |
| functions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An <em>assignment-expression</em> in an initializer must be either the same type as |
| the object it initializes or be a type that can be converted to the object’s |
| type according to “<a href="#implicit-conversions">Implicit Conversions</a>”. |
| Since these include constructors, a composite variable can be initialized by |
| either a constructor or an initializer list; and an element in an |
| initializer list can be a constructor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If an initializer is a list of initializers enclosed in curly braces, the |
| variable being declared must be a vector, a matrix, an array, or a |
| structure.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i = { <span class="integer">1</span> }; <span class="comment">// illegal, i is not a composite</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A list of initializers enclosed in a matching set of curly braces is applied |
| to one composite. |
| This may be the variable being declared or a composite contained in the |
| variable being declared. |
| Individual initializers from the initializer list are applied to the |
| elements/members of the composite, in order.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the composite has a vector type, initializers from the list are applied |
| to the components of the vector, in order, starting with component 0. |
| The number of initializers must match the number of components.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the composite has a matrix type, initializers from the list must be |
| vector initializers and are applied to the columns of the matrix, in order, |
| starting with column 0. |
| The number of initializers must match the number of columns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the composite has a structure type, initializers from the list are |
| applied to the members of the structure, in the order declared in the |
| structure, starting with the first member. |
| The number of initializers must match the number of members.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Applying these rules, the following matrix declarations are equivalent:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat2x2 a = mat2( vec2( <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> ), vec2( <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> ) ); |
| mat2x2 b = { vec2( <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> ), vec2( <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> ) }; |
| mat2x2 c = { { <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span> }, { <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> } };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>All of the following declarations result in a compile-time error.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[<span class="integer">2</span>] = { <span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span> }; <span class="comment">// illegal</span> |
| vec2 b = { <span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span> }; <span class="comment">// illegal</span> |
| mat3x3 c = { vec3(<span class="float">0</span><span class="float">.0</span>), vec3(<span class="float">1</span><span class="float">.0</span>), vec3(<span class="float">2</span><span class="float">.0</span>), vec3(<span class="float">3</span><span class="float">.0</span>) }; <span class="comment">// illegal</span> |
| mat2x2 d = { <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span> }; <span class="comment">// illegal, can't flatten nesting</span> |
| <span class="keyword">struct</span> { |
| <span class="predefined-type">float</span> a; |
| <span class="predefined-type">int</span> b; |
| } e = { <span class="float">1</span><span class="float">.2</span>, <span class="integer">2</span>, <span class="integer">3</span> }; <span class="comment">// illegal</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In all cases, the inner-most initializer (i.e., not a list of initializers |
| enclosed in curly braces) applied to an object must have the same type as |
| the object being initialized or be a type that can be converted to the |
| object’s type according to “<a href="#implicit-conversions">Implicit |
| Conversions</a>”. |
| In the latter case, an implicit conversion will be done on the initializer |
| before the assignment is done.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> { |
| <span class="predefined-type">float</span> a; |
| <span class="predefined-type">int</span> b; |
| } e = { <span class="float">1</span><span class="float">.2</span>, <span class="integer">2</span> }; <span class="comment">// legal, all types match</span> |
| <span class="keyword">struct</span> { |
| <span class="predefined-type">float</span> a; |
| <span class="predefined-type">int</span> b; |
| } e = { <span class="integer">1</span>, <span class="integer">3</span> }; <span class="comment">// legal, first initializer is converted</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>All of the following declarations result in a compile-time error.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> a = <span class="predefined-constant">true</span>; <span class="comment">// illegal</span> |
| vec4 b[<span class="integer">2</span>] = { vec4(<span class="float">0</span><span class="float">.0</span>), <span class="float">1</span><span class="float">.0</span> }; <span class="comment">// illegal</span> |
| mat4x2 c = { vec3(<span class="float">0</span><span class="float">.0</span>), vec3(<span class="float">1</span><span class="float">.0</span>) }; <span class="comment">// illegal</span> |
| |
| <span class="keyword">struct</span> S1 { |
| vec4 a; |
| vec4 b; |
| }; |
| |
| <span class="keyword">struct</span> { |
| <span class="predefined-type">float</span> s; |
| <span class="predefined-type">float</span> t; |
| } d[] = { S1(vec4(<span class="float">0</span><span class="float">.0</span>), vec4(<span class="float">1</span><span class="float">.1</span>)) }; <span class="comment">// illegal</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If an initializer (of either form) is provided for an unsized array, the |
| size of the array is determined by the number of top-level (non-nested) |
| initializers within the initializer. |
| All of the following declarations create arrays explicitly sized with five |
| elements:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">float</span> a[] = <span class="predefined-type">float</span>[](<span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); |
| <span class="predefined-type">float</span> b[] = { <span class="float">3</span><span class="float">.4</span>, <span class="float">4</span><span class="float">.2</span>, <span class="float">5</span><span class="float">.0</span>, <span class="float">5</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span> }; |
| <span class="predefined-type">float</span> c[] = a; <span class="comment">// c is explicitly size 5</span> |
| <span class="predefined-type">float</span> d[<span class="integer">5</span>] = b; <span class="comment">// means the same thing</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to have too few or too many initializers in an |
| initializer list for the composite being initialized. |
| That is, all elements of an array, all members of a structure, all columns |
| of a matrix, and all components of a vector must have exactly one |
| initializer expression present, with no unconsumed initializers.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="scoping">4.2. Scoping</h3> |
| <div class="paragraph"> |
| <p>The scope of a variable is determined by where it is declared. |
| If it is declared outside all function definitions, it has global scope, |
| which starts from where it is declared and persists to the end of the shader |
| it is declared in. |
| If it is declared in a <strong>while</strong> test or a <strong>for</strong> statement, then it is scoped |
| to the end of the following sub-statement. |
| If it is declared in an <strong>if</strong> or <strong>else</strong> statement, it is scoped to the end of |
| that statement. |
| (See “<a href="#selection">Selection</a>” and “<a href="#iteration">Iteration</a>” for the |
| location of statements and sub-statements.) Otherwise, if it is declared as |
| a statement within a compound statement, it is scoped to the end of that |
| compound statement. |
| If it is declared as a parameter in a function definition, it is scoped |
| until the end of that function definition. |
| A function’s parameter declarations and body together form a single scope |
| nested in the global scope. |
| The <strong>if</strong> statement’s expression does not allow new variables to be declared, |
| hence does not form a new scope.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Within a declaration, the scope of a name starts immediately after the |
| initializer if present or immediately after the name being declared if not. |
| Several examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> x = <span class="integer">1</span>; |
| { |
| <span class="predefined-type">int</span> x = <span class="integer">2</span>, y = x; <span class="comment">// y is initialized to 2</span> |
| } |
| |
| <span class="keyword">struct</span> S |
| { |
| <span class="predefined-type">int</span> x; |
| }; |
| |
| { |
| S S = S(<span class="integer">0</span>); <span class="comment">// 'S' is only visible as a struct and constructor</span> |
| S; <span class="comment">// 'S' is now visible as a variable</span> |
| } |
| |
| <span class="predefined-type">int</span> x = x; <span class="comment">// Error if x has not been previously defined.</span> |
| <span class="comment">// If the previous definition of x was in this</span> |
| <span class="comment">// same scope, this causes a redeclaration error.</span> |
| |
| <span class="predefined-type">int</span> f( <span class="comment">/* nested scope begins here */</span> <span class="predefined-type">int</span> k) |
| { |
| <span class="predefined-type">int</span> k = k + <span class="integer">3</span>; <span class="comment">// redeclaration error of the name k</span> |
| ... |
| } |
| |
| <span class="predefined-type">int</span> f(<span class="predefined-type">int</span> k) |
| { |
| { |
| <span class="predefined-type">int</span> k = k + <span class="integer">3</span>; <span class="comment">// 2nd k is parameter, initializing nested first k</span> |
| <span class="predefined-type">int</span> m = k; <span class="comment">// use of new k, which is hiding the parameter</span> |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For both <strong>for</strong> and <strong>while</strong> loops, the sub-statement itself does not |
| introduce a new scope for variable names, so the following has a |
| redeclaration compile-time error:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">for</span> ( <span class="comment">/* nested scope begins here */</span> <span class="predefined-type">int</span> i = <span class="integer">0</span>; i < <span class="integer">10</span>; i++) { |
| <span class="predefined-type">int</span> i; <span class="comment">// redeclaration error</span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The body of a <strong>do</strong>-<strong>while</strong> loop introduces a new scope lasting only between |
| the <strong>do</strong> and <strong>while</strong> (not including the while test expression), whether or |
| not the body is simple or compound:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span> i = <span class="integer">17</span>; |
| <span class="keyword">do</span> |
| <span class="predefined-type">int</span> i = <span class="integer">4</span>; <span class="comment">// okay, in nested scope_</span> |
| <span class="keyword">while</span> (i == <span class="integer">0</span>); <span class="comment">// i is 17, scoped outside the do-while body</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The statement following a <strong>switch</strong> (…​) forms a nested scope.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All variable names, structure type names, and function names in a given |
| scope share the same name space. |
| Function names can be redeclared in the same scope, with the same or |
| different parameters, without error. |
| An implicitly-sized array can be redeclared in the same scope as an array of |
| the same base type. |
| Otherwise, within one compilation unit, a declared name cannot be redeclared |
| in the same scope; doing so results in a redeclaration compile-time error. |
| If a nested scope redeclares a name used in an outer scope, it hides all |
| existing uses of that name. |
| There is no way to access the hidden name or make it unhidden, without |
| exiting the scope that hid it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in functions are scoped in a scope outside the global scope that |
| users declare global variables in. |
| That is, a shader’s global scope, available for user-defined functions and |
| global variables, is nested inside the scope containing the built-in |
| functions. |
| When a function name is redeclared in a nested scope, it hides all functions |
| declared with that name in the outer scope. |
| Function declarations (prototypes) cannot occur inside of functions; they |
| must be at global scope, or for the built-in functions, outside the global |
| scope, otherwise a compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shared globals are global variables declared with the same name in |
| independently compiled units (shaders) within the same language (i.e., same |
| stage, e.g. vertex) that are linked together when making a single program. |
| (Globals forming the interface between two different shader languages are |
| discussed in other sections.) Shared globals share the same name space, and |
| must be declared with the same type. |
| They will share the same storage.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shared global arrays must have the same base type and the same explicit |
| size. |
| An array implicitly sized in one shader can be explicitly sized by another |
| shader in the same stage. |
| If no shader in a stage has an explicit size for the array, the largest |
| implicit size (one more than the largest index used) in that stage is used. |
| There is no cross-stage array sizing. |
| If there is no static access to an implicitly sized array within the stage |
| declaring it, then the array is given a size of 1, which is relevant when |
| the array is declared within an interface block that is shared with other |
| stages or the application (other unused arrays might be eliminated by the |
| optimizer).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shared global scalars must have exactly the same type name and type |
| definition. |
| Structures must have the same name, sequence of type names, and type |
| definitions, and member names to be considered the same type. |
| This rule applies recursively for nested or embedded types. |
| If a shared global has multiple initializers, the initializers must all be |
| constant expressions, and they must all have the same value. |
| Otherwise, a link-time error will result. |
| (A shared global having only one initializer does not require that |
| initializer to be a constant expression.)</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="storage-qualifiers">4.3. Storage Qualifiers</h3> |
| <div class="paragraph"> |
| <p>Variable declarations may have at most one storage qualifier specified in |
| front of the type. |
| These are summarized as</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Storage Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><none: default></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">local read/write memory, or an input parameter to a |
| function</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>const</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a variable whose value cannot be changed</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">linkage into a shader from a previous stage, variable |
| is copied in</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>out</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">linkage out of a shader to a subsequent stage, |
| variable is copied out</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>attribute</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">compatibility profile only and vertex language only; |
| same as <strong>in</strong> when in a vertex shader</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>uniform</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">value does not change across the primitive being |
| processed, uniforms form the linkage between a shader, |
| API, and the application</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>varying</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">compatibility profile only and vertex and fragment |
| languages only; same as <strong>out</strong> when in a vertex shader |
| and same as <strong>in</strong> when in a fragment shader</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>buffer</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">value is stored in a buffer object, and can be read or |
| written both by shader invocations and the API</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>shared</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">compute shader only; variable storage is shared across |
| all work items in a workgroup</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Some input and output qualified variables can be qualified with at most one |
| additional auxiliary storage qualifier:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Auxiliary Storage Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>centroid</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">centroid-based interpolation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sample</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">per-sample interpolation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>patch</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">per-tessellation-patch attributes</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Not all combinations of qualification are allowed. |
| Auxiliary storage qualifiers can only be used with the <strong>in</strong> or <strong>out</strong> storage |
| qualifiers. |
| Additional qualifier rules are defined in upcoming sections.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Local variables can only use the <strong>const</strong> storage qualifier (or use no |
| storage qualifier).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that function parameters can use <strong>const</strong>, <strong>in</strong>, and <strong>out</strong> qualifiers, |
| but as <em>parameter qualifiers</em>. |
| Parameter qualifiers are discussed in |
| “<a href="#function-calling-conventions">Function Calling Conventions</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Function return types and structure members do not use storage qualifiers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Initializers in global declarations may only be used in declarations of |
| global variables with no storage qualifier, with a <strong>const</strong> qualifier, or |
| with a <strong>uniform</strong> qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Global variables without storage qualifiers that are not initialized in |
| their declaration or by the application will not be initialized, |
| but rather will enter <em>main()</em> with undefined values.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When comparing an output from one shader stage to an input of a subsequent |
| shader stage, the input and output don’t match if their auxiliary qualifiers |
| (or lack thereof) are not the same.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="default-storage-qualifier">4.3.1. Default Storage Qualifier</h4> |
| <div class="paragraph"> |
| <p>If no qualifier is present on a global variable, then the variable has no |
| linkage to the application or shaders running on other pipeline stages. |
| For either global or local unqualified variables, the declaration will |
| appear to allocate memory associated with the processor it targets. |
| This variable will provide read/write access to this allocated memory.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="constant-qualifier">4.3.2. Constant Qualifier</h4> |
| <div class="paragraph"> |
| <p>Named compile-time constants |
| or read-only variables |
| can be declared using |
| the <strong>const</strong> qualifier. |
| The <strong>const</strong> qualifier can be used with any of the non-void transparent basic |
| data types, as well as with structures and arrays of these. |
| It is a compile-time error to write to a <strong>const</strong> variable outside of its |
| declaration, so they must be initialized when declared. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> vec3 zAxis = vec3 (<span class="float">0</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>); |
| <span class="directive">const</span> <span class="predefined-type">float</span> ceiling = a + b; <span class="comment">// a and b not necessarily constants</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Structure members may not be qualified with <strong>const</strong>. |
| Structure variables can be declared as <strong>const</strong>, and initialized with a |
| structure |
| constructor or initializer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Initializers for <strong>const</strong> declarations |
| at global scope |
| must be constant expressions, as defined in |
| “<a href="#constant-expressions">Constant Expressions</a>”.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="constant-expressions">4.3.3. Constant Expressions</h4> |
| <div class="paragraph"> |
| <p>SPIR-V specialization constants are expressed in GLSL as <strong>const</strong> with the |
| layout qualifier <strong>constant_id</strong>, as described in |
| “<a href="#specialization-constant-qualifier">Specialization-Constant |
| Qualifier.</a>”</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> = …​), 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>…​</strong>) are not included in the |
| operators that can create a constant expression. |
| Also, an array access with a specialization constant as an index does |
| not result in a constant expression.</p> |
| </li> |
| <li> |
| <p>Valid use of the <strong>length</strong>() method on an explicitly sized object, |
| whether or not the object itself is constant (implicitly sized or |
| run-time sized arrays do not return a constant expression).</p> |
| </li> |
| <li> |
| <p>A constructor whose arguments are all constant expressions.</p> |
| </li> |
| <li> |
| <p>For non-specialization constants only: The value returned by certain |
| built-in function calls whose arguments are all constant expressions, |
| including at least the list below. |
| Any other built-in function that does not access memory (not the texture |
| lookup functions, image access, atomic counter, etc.), that has a |
| non-<strong>void</strong> return type, that has no <strong>out</strong> parameter, and is not a noise |
| function might also be considered a constant. |
| When a function is called with an argument that is a specialization |
| constant, the result is not a constant expression.</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Angle and Trigonometric Functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>radians</strong></p> |
| </li> |
| <li> |
| <p><strong>degrees</strong></p> |
| </li> |
| <li> |
| <p><strong>sin</strong></p> |
| </li> |
| <li> |
| <p><strong>cos</strong></p> |
| </li> |
| <li> |
| <p><strong>asin</strong></p> |
| </li> |
| <li> |
| <p><strong>acos</strong></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>Exponential Functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>pow</strong></p> |
| </li> |
| <li> |
| <p><strong>exp</strong></p> |
| </li> |
| <li> |
| <p><strong>log</strong></p> |
| </li> |
| <li> |
| <p><strong>exp2</strong></p> |
| </li> |
| <li> |
| <p><strong>log2</strong></p> |
| </li> |
| <li> |
| <p><strong>sqrt</strong></p> |
| </li> |
| <li> |
| <p><strong>inversesqrt</strong></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>Common Functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>abs</strong></p> |
| </li> |
| <li> |
| <p><strong>sign</strong></p> |
| </li> |
| <li> |
| <p><strong>floor</strong></p> |
| </li> |
| <li> |
| <p><strong>trunc</strong></p> |
| </li> |
| <li> |
| <p><strong>round</strong></p> |
| </li> |
| <li> |
| <p><strong>ceil</strong></p> |
| </li> |
| <li> |
| <p><strong>mod</strong></p> |
| </li> |
| <li> |
| <p><strong>min</strong></p> |
| </li> |
| <li> |
| <p><strong>max</strong></p> |
| </li> |
| <li> |
| <p><strong>clamp</strong></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>Geometric Functions</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>length</strong></p> |
| </li> |
| <li> |
| <p><strong>dot</strong></p> |
| </li> |
| <li> |
| <p><strong>normalize</strong></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>Function calls to user-defined functions (non-built-in functions) cannot |
| be used to form constant expressions.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A <em>constant integral expression</em> is a constant expression that evaluates to |
| a scalar signed or unsigned integer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Constant expressions will be evaluated in an invariant way so as to create |
| the same value in multiple shaders when the same constant expressions appear |
| in those shaders. |
| See “<a href="#the-invariant-qualifier">The Invariant Qualifier</a>” for more details |
| on how to create invariant expressions and |
| “<a href="#precision-qualifiers">Precision Qualifiers</a>” 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 “<a href="#the-invariant-qualifier">The Invariant Qualifier</a>” and |
| “<a href="#the-precise-qualifier">The Precise Qualifier</a>” 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 “<a href="#default-precision-qualifiers">Default Precision Qualifiers</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Specialization-constant expressions are never evaluated by the compiler |
| front end, but instead retain the expression’s operations needed to evaluate |
| them later on the host.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="input-variables">4.3.4. Input Variables</h4> |
| <div class="paragraph"> |
| <p>Shader input variables are declared with the <strong>in</strong> storage qualifier. |
| They form the input interface between previous stages of the API |
| pipeline and the declaring shader. |
| Input variables must be declared at global scope. |
| Values from the previous pipeline stage are copied into input variables at |
| the beginning of shader execution. |
| It is a compile-time error to write to a variable declared as an input.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Only the input variables that are |
| statically |
| read need to be written by the |
| previous stage; it is allowed to have superfluous declarations of input |
| variables. |
| This is shown in the following table.</p> |
| </div> |
| <table class="tableblock frame-all grid-all fit-content"> |
| <colgroup> |
| <col> |
| <col> |
| <col> |
| <col> |
| <col> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top" colspan="2" rowspan="2"><p class="tableblock">Treatment of Mismatched Input Variables</p></td> |
| <td class="tableblock halign-left valign-top" colspan="3"><p class="tableblock">Consuming Shader (input variables)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">No Declaration</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Declared but no Static Use</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Declared and Static Use</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top" rowspan="3"><p class="tableblock">Generating Shader (output variables)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">No Declaration</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Link-Time Error</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Declared but no Static Use</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed (values are undefined)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Declared and Static Use</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Allowed (values are potentially undefined)</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Consumption errors are based on static use only. |
| Compilation may generate a warning, but not an error, for any dynamic use |
| the compiler can deduce that might cause consumption of undefined values.</p> |
| </div> |
| <div class="paragraph"> |
| <p>See “<a href="#built-in-variables">Built-In Variables</a>” for a list of the built-in |
| input names.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Vertex shader input variables (or attributes) receive per-vertex data. |
| It is a compile-time error to use auxiliary storage or interpolation qualifiers |
| on a vertex shader input. |
| The values copied in are established by the API or through the use |
| of the layout identifier <strong>location</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to declare a vertex shader input with, or that |
| contains, any of the following types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <a href="#booleans">boolean type</a></p> |
| </li> |
| <li> |
| <p>An <a href="#opaque-types">opaque type</a></p> |
| </li> |
| <li> |
| <p>A structure</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Example declarations in a vertex shader:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 position; |
| in vec3 normal; |
| in vec2 texCoord[<span class="integer">4</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is expected that graphics hardware will have a small number of fixed |
| vector locations for passing vertex inputs. |
| Therefore, the OpenGL Shading Language defines each non-matrix input variable as taking up |
| one such vector location. |
| There is an implementation-dependent limit on the number of locations that |
| can be used, and if this is exceeded it will cause a link-time error. |
| (Declared input variables that are not statically used do not count against |
| this limit.) A scalar input counts the same amount against this limit as a |
| <strong>vec4</strong>, so applications may want to consider packing groups of four |
| unrelated float inputs together into a vector to better utilize the |
| capabilities of the underlying hardware. |
| A matrix input will use up multiple locations. |
| The number of locations used will equal the number of columns in the matrix.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Tessellation control, evaluation, and geometry shader input variables get |
| the per-vertex values written out by output variables of the same names in |
| the previous active shader stage. |
| For these inputs, <strong>centroid</strong> and interpolation qualifiers are allowed, but |
| have no effect. |
| Since tessellation control, tessellation evaluation, and geometry shaders |
| operate on a set of vertices, each input variable (or input block, see |
| interface blocks below) needs to be declared as an array. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in <span class="predefined-type">float</span> foo[]; <span class="comment">// geometry shader input for vertex "out float foo"</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 “<a href="#input-layout-qualifiers">Input |
| Layout Qualifiers</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Some inputs and outputs are <em>arrayed</em>, meaning that for an interface between |
| two shader stages either the input or output declaration requires an extra |
| level of array indexing for the declarations to match. |
| For example, with the interface between a vertex shader and a geometry |
| shader, vertex shader output variables and geometry shader input variables |
| of the same name must have matching types, except that the geometry shader |
| will have one more array dimension than the vertex shader, to allow for |
| vertex indexing. |
| If such an arrayed interface variable is not declared with the necessary |
| additional input or output array dimension, a link-time error will result. |
| Geometry shader inputs, tessellation control shader inputs and outputs, and |
| tessellation evaluation inputs all have an additional level of arrayness |
| relative to other shader inputs and outputs. |
| These inputs and outputs are known as <em>per-vertex-arrayed</em> inputs and |
| outputs. |
| Component limits for arrayed interfaces (e.g. |
| <em>gl_MaxTessControlInputComponents</em>) are limits per vertex, not limits for |
| the entire interface.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For non-arrayed interfaces (meaning array dimensionally stays the same |
| between stages), it is a link-time error if the input variable is not |
| declared with the same type, including array dimensionality, as the matching |
| output variable.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The link-time type-matching rules apply to all declared input and output |
| variables, whether or not they are used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Additionally, tessellation evaluation shaders support per-patch input |
| variables declared with the <strong>patch</strong> and <strong>in</strong> qualifiers. |
| Per-patch input variables are filled with the values of per-patch output |
| variables written by the tessellation control shader. |
| Per-patch inputs may be declared as one-dimensional arrays, but are not |
| indexed by vertex number. |
| Applying the <strong>patch</strong> qualifier to inputs can only be done in tessellation |
| evaluation shaders. |
| As with other input variables, per-patch inputs must be declared using the |
| same type and qualification as per-patch outputs from the previous |
| (tessellation control) shader stage. |
| It is a compile-time error to use <strong>patch</strong> with inputs in any other stage.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to declare a tessellation control, tessellation |
| evaluation or geometry shader input with, or that contains, any of the |
| following types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <a href="#booleans">boolean type</a></p> |
| </li> |
| <li> |
| <p>An <a href="#opaque-types">opaque type</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment shader inputs get per-fragment values, typically interpolated from |
| a previous stage’s outputs. |
| The auxiliary storage qualifiers <strong>centroid</strong> and <strong>sample</strong> can also be |
| applied, as well as the interpolation qualifiers <strong>flat</strong>, <strong>noperspective</strong>, |
| and <strong>smooth.</strong></p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to declare a fragment shader input with, or that |
| contains, any of the following types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <a href="#booleans">boolean type</a></p> |
| </li> |
| <li> |
| <p>An <a href="#opaque-types">opaque type</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment shader inputs that are, or contain, integral |
| or double-precision floating-point |
| types must be |
| qualified with the interpolation qualifier <strong>flat</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment inputs are declared as in the following examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec3 normal; |
| centroid in vec2 TexCoord; |
| invariant centroid in vec4 Color; |
| noperspective in <span class="predefined-type">float</span> temperature; |
| flat in vec3 myColor; |
| noperspective centroid in vec2 myTexCoord;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The fragment shader inputs form an interface with the last active shader in |
| the vertex processing pipeline. |
| For this interface, the last active shader stage output variables and |
| fragment shader input variables of the same name must match in type and |
| qualification, with a few exceptions: The storage qualifiers must, of |
| course, differ (one is <strong>in</strong> and one is <strong>out</strong>). |
| Also, |
| interpolation qualification (e.g. <strong>flat</strong>) and |
| auxiliary qualification (e.g. <strong>centroid</strong>) may differ. |
| These mismatches are allowed between any pair of stages. |
| When |
| interpolation or |
| auxiliary qualifiers do not match, those provided in |
| the fragment shader supersede those provided in previous stages. |
| If any such qualifiers are completely missing in the fragment shaders, then |
| the default is used, rather than any qualifiers that may have been declared |
| in previous stages. |
| That is, what matters is what is declared in the fragment shaders, not what |
| is declared in shaders in previous stages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When an interface between shader stages is formed using shaders from two |
| separate program objects, it is not possible to detect mismatches between |
| inputs and outputs when the programs are linked. |
| When there are mismatches between inputs and outputs on such interfaces, |
| the values passed across the interface will be partially or completely |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Shaders can ensure matches across such interfaces either by using input and |
| output layout qualifiers (sections “<a href="#input-layout-qualifiers">Input Layout |
| Qualifiers</a>” and “<a href="#output-layout-qualifiers">Output Layout |
| Qualifiers</a>”) or by using identical input and output declarations of |
| blocks or variables. |
| Complete rules for interface matching are found in section 7.4.1 “Shader |
| Interface Matching” of the <a href="#references">OpenGL Specification</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Compute shaders do not permit user-defined input variables and do not form a |
| formal interface with any other shader stage. |
| See “<a href="#compute-shader-special-variables">Compute Shader Special |
| Variables</a>” for a description of built-in compute shader input variables. |
| All other input to a compute shader is retrieved explicitly through image |
| loads, texture fetches, loads from uniforms or uniform buffers, or other |
| user supplied code. |
| Redeclaration of built-in input variables in compute shaders is not |
| permitted.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="uniform-variables">4.3.5. Uniform Variables</h4> |
| <div class="paragraph"> |
| <p>The <strong>uniform</strong> qualifier is used to declare global variables whose values are |
| the same across the entire primitive being processed. |
| All <strong>uniform</strong> variables are read-only and are initialized externally either |
| at link time or through the API. |
| The link-time initial value is either the value of the variable’s |
| initializer, if present, or 0 if no initializer is present. |
| Opaque types cannot have initializers, or a compile-time error results. |
| When targeting Vulkan, it is a compile-time error to declare <strong>uniform</strong> |
| variables outside a block.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Example declarations are:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">uniform vec4 lightPosition; |
| uniform vec3 color = vec3(<span class="float">0</span><span class="float">.7</span>, <span class="float">0</span><span class="float">.7</span>, <span class="float">0</span><span class="float">.2</span>); <span class="comment">// value assigned at link time</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>uniform</strong> qualifier can be used with any of the basic data types, or |
| when declaring a variable whose type is a structure, or an array of any of |
| these.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is an implementation-dependent limit on the amount of storage for |
| uniforms that can be used for each type of shader and if this is exceeded it |
| will cause a compile-time or link-time error. |
| Uniform variables that are declared but not |
| used do not count against this limit. |
| The number of user-defined uniform variables and the number of built-in |
| uniform variables that are used within a shader are added together to |
| determine whether available uniform storage has been exceeded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Uniforms in shaders all share a single global name space when linked into a |
| program or separable program. |
| Hence, the types, |
| initializers, |
| and any location specifiers of all statically used uniform variables with the |
| same name must match across all shaders that are linked into a single program. |
| However it is not required to repeat the |
| initializer or |
| location specifier in all the linked shaders. |
| While this single uniform name space is cross stage, a uniform variable |
| name’s scope is per stage: If a uniform variable name is declared in one |
| stage (e.g. a vertex shader) but not in another (e.g. a fragment shader), |
| then that name is still available in the other stage for a different use.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="output-variables">4.3.6. Output Variables</h4> |
| <div class="paragraph"> |
| <p>Shader output variables are declared with the <strong>out</strong> storage qualifier. |
| They form the output interface between the declaring shader and the |
| subsequent stages of the API pipeline. |
| Output variables must be declared at global scope. |
| During shader execution they will behave as normal unqualified global |
| variables. |
| Their values are copied out to the subsequent pipeline stage on shader exit. |
| Only output variables that are read by the subsequent pipeline stage need to |
| be written; it is allowed to have superfluous declarations of output |
| variables.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is <em>not</em> an <strong>inout</strong> storage qualifier for declaring a single variable |
| name as both input and output to a shader. |
| Also, a variable cannot be declared with both the <strong>in</strong> and the <strong>out</strong> |
| qualifiers, this will result in a compile-time or link-time error. |
| Output variables must be declared with different names than input variables. |
| However, nesting an input or output inside an interface block with an |
| instance name allows the same names with one referenced through a block |
| instance name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Vertex, tessellation evaluation, and geometry output variables output |
| per-vertex data and are declared using the <strong>out</strong> storage qualifier. |
| Applying <strong>patch</strong> to an output can only be done in a tessellation control |
| shader. |
| It is a compile-time error to use <strong>patch</strong> on outputs in any other stage.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to declare a vertex, tessellation evaluation, |
| tessellation control, or geometry shader output with, or that contains, any |
| of the following types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <a href="#booleans">boolean type</a></p> |
| </li> |
| <li> |
| <p>An <a href="#opaque-types">opaque type</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Individual outputs are declared as in the following examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out vec3 normal; |
| centroid out vec2 TexCoord; |
| invariant centroid out vec4 Color; |
| flat out vec3 myColor; |
| sample out vec4 perSampleColor;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>These can also appear in interface blocks, as described in |
| “<a href="#interface-blocks">Interface Blocks</a>”. |
| 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 |
| “<a href="#input-variables">Input Variables</a>”) 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 "in float foo[]"</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 |
| “<a href="#tessellation-control-outputs">Tessellation Control Outputs</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each tessellation control shader invocation has a corresponding output patch |
| vertex, and may assign values to per-vertex outputs only if they belong to |
| that corresponding vertex. |
| If a per-vertex output variable is used as an l-value, it is a compile-time |
| or link-time error if the expression indicating the vertex index is not the |
| identifier <em>gl_InvocationID</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The order of execution of a tessellation control shader invocation relative |
| to the other invocations for the same input patch is undefined unless the |
| built-in function <strong>barrier</strong>() is used. |
| This provides some control over relative execution order. |
| When a shader invocation calls <strong>barrier</strong>(), its execution pauses until all |
| other invocations have reached the same point of execution. |
| Output variable assignments performed by any invocation executed prior to |
| calling <strong>barrier</strong>() will be visible to any other invocation after the call |
| to <strong>barrier</strong>() returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Because tessellation control shader invocations execute in undefined order |
| between barriers, the values of per-vertex or per-patch output variables |
| will sometimes be undefined. |
| Consider the beginning and end of shader execution and each call to |
| <strong>barrier</strong>() as synchronization points. |
| The value of an output variable will be undefined in any of the three |
| following cases:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>At the beginning of execution.</p> |
| </li> |
| <li> |
| <p>At each synchronization point, unless</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>the value was well-defined after the previous synchronization point and |
| was not written by any invocation since, or</p> |
| </li> |
| <li> |
| <p>the value was written by exactly one shader invocation since the previous |
| synchronization point, or</p> |
| </li> |
| <li> |
| <p>the value was written by multiple shader invocations since the previous |
| synchronization point, and the last write performed by all such |
| invocations wrote the same value.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </li> |
| <li> |
| <p>When read by a shader invocation, if</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>the value was undefined at the previous synchronization point and has not |
| been written by the same shader invocation since, or</p> |
| </li> |
| <li> |
| <p>the output variable is written to by any other shader invocation between |
| the previous and next synchronization points, even if that assignment |
| occurs in code following the read.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment outputs output per-fragment data and are declared using the <strong>out</strong> |
| storage qualifier. |
| It is a compile-time error to use auxiliary storage qualifiers or |
| interpolation qualifiers in a fragment shader output declaration. |
| It is a compile-time error to declare a fragment shader output with, or that |
| contains, any of the following types:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <a href="#booleans">boolean type</a></p> |
| </li> |
| <li> |
| <p>A double-precision scalar or vector (<strong>double</strong>, <strong>dvec2</strong>, <strong>dvec3</strong>, |
| <strong>dvec4</strong>)</p> |
| </li> |
| <li> |
| <p>An <a href="#opaque-types">opaque type</a></p> |
| </li> |
| <li> |
| <p>A matrix type</p> |
| </li> |
| <li> |
| <p>A structure</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment outputs are declared as in the following examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out vec4 FragmentColor; |
| out uint Luminosity;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Compute shaders have no built-in output variables, do not support |
| user-defined output variables and do not form a formal interface with any |
| other shader stage. |
| All outputs from a compute shader take the form of the side effects such as |
| image stores and operations on atomic counters.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="buffer-variables">4.3.7. Buffer Variables</h4> |
| <div class="paragraph"> |
| <p>The <strong>buffer</strong> qualifier is used to declare global variables whose values are |
| stored in the data store of a buffer object bound through the API. |
| Buffer variables can be read and written, with the underlying storage shared |
| among all active shader invocations. |
| Buffer variable memory reads and writes within a single shader invocation |
| are processed in order. |
| However, the order of reads and writes performed in one invocation relative |
| to those performed by another invocation is largely undefined. |
| Buffer variables may be qualified with memory qualifiers affecting how the |
| underlying memory is accessed, as described in “<a href="#memory-qualifiers">Memory |
| Qualifiers</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>buffer</strong> qualifier can be used to declare interface blocks (see |
| “<a href="#interface-blocks">Interface Blocks</a>”), which are then referred to as |
| shader storage blocks. |
| It is a compile-time error to declare buffer variables outside a block.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// use buffer to create a buffer block (shader storage block)</span> |
| buffer BufferName { <span class="comment">// externally visible name of buffer</span> |
| <span class="predefined-type">int</span> count; <span class="comment">// typed, shared memory...</span> |
| ... <span class="comment">// ...</span> |
| vec4 v[]; <span class="comment">// last member may be an array that is not sized</span> |
| <span class="comment">// until after link time (dynamically sized)</span> |
| } Name; <span class="comment">// name of block within the shader</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>There are implementation-dependent limits on the number of shader storage |
| blocks used for each type of shader, the combined number of shader storage |
| blocks used for a program, and the amount of storage required by each |
| individual shader storage block. |
| If any of these limits are exceeded, it will cause a compile-time or |
| link-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If multiple shaders are linked together, then they will share a single |
| global buffer variable name space. |
| Hence, the types of all declared buffer variables with the same name must |
| match across all shaders that are linked into a single program.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="shared-variables">4.3.8. Shared Variables</h4> |
| <div class="paragraph"> |
| <p>The <strong>shared</strong> qualifier is used to declare global variables that have storage |
| shared between all work items in a compute shader workgroup. |
| Variables declared as <strong>shared</strong> may only be used in compute shaders (see |
| “<a href="#compute-processor">Compute Processor</a>”). |
| Any other declaration of a <strong>shared</strong> variable is a compile-time error. |
| Shared variables are implicitly coherent (see |
| “<a href="#memory-qualifiers">Memory Qualifiers</a>”).</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 “<a href="#shader-invocation-control-functions">Shader Invocation Control |
| Functions</a>”).</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is a limit to the total size of all variables declared as <strong>shared</strong> in a |
| single program. |
| This limit, expressed in units of basic machine units may be determined by |
| using the OpenGL API to query the value of |
| MAX_COMPUTE_SHARED_MEMORY_SIZE.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="interface-blocks">4.3.9. Interface Blocks</h4> |
| <div class="paragraph"> |
| <p>Input, output, uniform, and buffer variable declarations can be grouped into |
| named interface blocks to provide coarser granularity backing than is |
| achievable with individual declarations. |
| They can have an optional instance name, used in the shader to reference |
| their members. |
| An output block of one programmable stage is backed by a corresponding input |
| block in the subsequent programmable stage. |
| A <em>uniform block</em> is backed by the application with a buffer object. |
| A block of buffer variables, called a <em>shader storage block</em>, is also backed |
| by the application with a buffer object. |
| It is a compile-time error to have an input block in a vertex shader or an |
| output block in a fragment shader. |
| These uses are reserved for future use.</p> |
| </div> |
| <div class="paragraph"> |
| <p>An interface block is started by an <strong>in</strong>, <strong>out</strong>, <strong>uniform</strong>, or <strong>buffer</strong> |
| keyword, followed by a block name, followed by an open curly brace (<strong>{</strong>) as |
| follows:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>interface-block</em> : </dt> |
| <dd> |
| <p><em>layout-qualifier<sub>opt</sub></em> <em>interface-qualifier</em> <em>block-name</em> <strong>{</strong> |
| <em>member-list</em> <strong>}</strong> <em>instance-name<sub>opt</sub></em> <strong>;</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>interface-qualifier</em> : </dt> |
| <dd> |
| <p><strong>in</strong><br> |
| <strong>out</strong><br> |
| <strong>patch</strong> <strong>in</strong> // Note: Qualifiers can be in any order.<br> |
| <strong>patch</strong> <strong>out</strong><br> |
| <strong>uniform</strong><br> |
| <strong>buffer</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>member-list</em> : </dt> |
| <dd> |
| <p><em>member-declaration</em><br> |
| <em>member-declaration</em> <em>member-list</em></p> |
| </dd> |
| <dt class="hdlist1"><em>member-declaration</em> : </dt> |
| <dd> |
| <p><em>layout-qualifier<sub>opt</sub></em> <em>qualifiers<sub>opt</sub></em> <em>type</em> <em>declarators</em> <strong>;</strong></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>instance-name</em> : </dt> |
| <dd> |
| <p><em>identifier</em><br> |
| <em>identifier</em> <strong>[</strong> <strong>]</strong><br> |
| <em>identifier</em> <strong>[</strong> <em>constant-integral-expression</em> <strong>]</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Each of the above elements is discussed below, with the exception of layout |
| qualifiers (<em>layout-qualifier</em>), which are defined in the next section.</p> |
| </div> |
| <div class="paragraph"> |
| <p>First, an example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">uniform Transform { |
| mat4 ModelViewMatrix; |
| mat4 ModelViewProjectionMatrix; |
| uniform mat3 NormalMatrix; <span class="comment">// allowed restatement of qualifier</span> |
| <span class="predefined-type">float</span> Deformation; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The above establishes a uniform block named “Transform” with four uniforms |
| grouped inside it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Types and declarators are the same as for other input, output, uniform, and |
| buffer variable declarations outside blocks, with these exceptions:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Initializers are not allowed</p> |
| </li> |
| <li> |
| <p>Opaque types are not allowed</p> |
| </li> |
| <li> |
| <p>Structure definitions cannot be nested inside a block</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Any of these would result in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If no optional qualifier is used in a member-declaration, the qualification |
| of the member includes all <strong>in</strong>, <strong>out</strong>, <strong>patch</strong>, <strong>uniform</strong>, or <strong>buffer</strong> as |
| determined by <em>interface-qualifier</em>. |
| If optional qualifiers are used, they can include interpolation qualifiers, |
| auxiliary storage qualifiers, |
| and storage qualifiers and they must declare |
| an input, output, or uniform member consistent with the interface qualifier |
| of the block: Input variables, output variables, uniform variables, and |
| <strong>buffer</strong> members can only be in <strong>in</strong> blocks, <strong>out</strong> blocks, <strong>uniform</strong> blocks, |
| and shader storage blocks, respectively.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Repeating the <strong>in</strong>, <strong>out</strong>, <strong>patch</strong>, <strong>uniform</strong>, or <strong>buffer</strong> interface |
| qualifier for a member’s storage qualifier is optional. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in Material { |
| smooth in vec4 Color1; <span class="comment">// legal, input inside in block</span> |
| smooth vec4 Color2; <span class="comment">// legal, 'in' inherited from 'in Material'</span> |
| vec2 TexCoord; <span class="comment">// legal, TexCoord is an input</span> |
| uniform <span class="predefined-type">float</span> Atten; <span class="comment">// illegal, mismatched storage qualifier</span> |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A <em>shader interface</em> is defined to be one of these:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>All the uniform variables and uniform blocks declared in a program. |
| This spans all compilation units linked together within one program.</p> |
| </li> |
| <li> |
| <p>All the <strong>buffer</strong> blocks declared in a program.</p> |
| </li> |
| <li> |
| <p>The boundary between adjacent programmable pipeline stages: This spans |
| all the outputs declared in all compilation units of the first stage and |
| all the inputs declared in all compilation units of the second stage. |
| Note that for the purposes of this definition, the fragment shader and |
| the preceding shader are considered to have a shared boundary even |
| though in practice, all values passed to the fragment shader first pass |
| through the rasterizer and interpolator.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The block name (<em>block-name</em>) is used to match within shader interfaces: an |
| output block of one pipeline stage will be matched to an input block with |
| the same name in the subsequent pipeline stage. |
| For uniform or shader storage blocks, the application uses the block name to |
| identify the block. |
| Block names have no other use within a shader beyond interface matching; it |
| is a compile-time error |
| to use a block name at global scope for anything other than as a |
| block name (e.g. use of a block name for a global variable name or function |
| name is currently reserved). |
| It is a compile-time error to use the same block name for more than one |
| block declaration in the same shader interface (as defined above) within one |
| shader, even if the block contents are identical.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Matched block names within a shader interface (as defined above) must match |
| in terms of having the same number of declarations with the same sequence of |
| types and the same sequence of member names, as well as having matching |
| member-wise layout qualification |
| (see next section). |
| Matched uniform or shader storage block names (but not input or output block |
| names) must also either all be lacking an instance name or all having an |
| instance name, putting their members at the same scoping level. |
| When instance names are present on matched block names, it is allowed for |
| the instance names to differ; they need not match for the blocks to match. |
| Furthermore, if a matching block is declared as an array, then the array |
| sizes must also match (or follow array matching rules for the shader |
| interface between consecutive shader stages). |
| Any mismatch will generate a link-time error. |
| A block name is allowed to have different definitions in different shader |
| interfaces within the same shader, allowing, for example, an input block and |
| output block to have the same name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If an instance name (<em>instance-name</em>) is not used, the names declared inside |
| the block are scoped at the global level and accessed as if they were |
| declared outside the block. |
| If an instance name (<em>instance-name</em>) is used, then it puts all the members |
| inside a scope within its own name space, accessed with the field selector |
| (<strong>.</strong>) operator (analogously to structures). |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in Light { |
| vec4 LightPos; |
| vec3 LightColor; |
| }; |
| in ColoredTexture { |
| vec4 Color; |
| vec2 TexCoord; |
| } Material; <span class="comment">// instance name</span> |
| vec3 Color; <span class="comment">// different Color than Material.Color</span> |
| vec4 LightPos; <span class="comment">// illegal, already defined</span> |
| ... |
| ... = LightPos; <span class="comment">// accessing LightPos</span> |
| ... = Material.Color; <span class="comment">// accessing Color in ColoredTexture block</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Outside the shading language (i.e., in the API), members are similarly |
| identified except the block name is always used in place of the instance |
| name (API accesses are to shader interfaces, not to shaders). |
| If there is no instance name, then the API does not use the block name to |
| access a member, just the member name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Within a shader interface, all declarations of the same global name must be |
| for the same object and must match in type and in whether they declare a |
| variable or member of a block with no instance name. |
| The API also needs this name to uniquely identify an object in the shader |
| interface. |
| It is a link-time error if any particular shader interface contains</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>two different blocks, each having no instance name, and each having a |
| member of the same name, or</p> |
| </li> |
| <li> |
| <p>a variable outside a block, and a block with no instance name, where the |
| variable has the same name as a member in the block.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out Vertex { |
| vec4 Position; <span class="comment">// API transform/feedback will use "Vertex.Position"</span> |
| vec2 Texture; |
| } Coords; <span class="comment">// shader will use "Coords.Position"</span> |
| out Vertex2 { |
| vec4 Color; <span class="comment">// API will use "Color"</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 "Transform[2]" to refer to instance 2</span> |
| mat4 ModelViewMatrix; |
| mat4 ModelViewProjectionMatrix; |
| vec4 a[]; <span class="comment">// array will get implicitly sized</span> |
| <span class="predefined-type">float</span> Deformation; |
| } transforms[<span class="integer">4</span>]; |
| ... |
| ... = transforms[<span class="integer">2</span>].ModelViewMatrix; <span class="comment">// shader access of instance 2</span> |
| <span class="comment">// API uses "Transform.ModelViewMatrix" to query an offset or other query</span> |
| transforms[x].a.length(); <span class="comment">// same length for 'a' for all x</span> |
| Transform[x]; <span class="comment">// illegal, must use 'transforms'</span> |
| Transform.a.length(); <span class="comment">// illegal, must use 'transforms'</span> |
| ...transforms[<span class="integer">2</span>].a[<span class="integer">3</span>]... <span class="comment">// if these are the only two dereferences of 'a',</span> |
| ...transforms[<span class="integer">3</span>].a[<span class="integer">7</span>]... <span class="comment">// then 'a' must be size 8, for all</span> |
| transforms[x]</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For uniform or shader storage blocks declared as an array, each individual |
| array element corresponds to a separate buffer object bind range, backing |
| one instance of the block. |
| As the array size indicates the number of buffer objects needed, uniform and |
| shader storage block array declarations must specify an array size. |
| A uniform or shader storage block array can only be indexed with a |
| dynamically uniform integral expression, otherwise results are undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When using OpenGL API entry points to identify the name of an individual |
| block in an array of blocks, the name string may include an array index |
| (e.g. <em>Transform[2]</em>). |
| When using OpenGL API entry points to refer to offsets or other |
| characteristics of a block member, an array index must not be specified |
| (e.g. <em>Transform.ModelViewMatrix</em>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Tessellation control, tessellation evaluation and geometry shader input |
| blocks must be declared as arrays and follow the array declaration and |
| linking rules for all shader inputs for the respective stages. |
| All other input and output block arrays must specify an array size.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are implementation-dependent limits on the number of uniform blocks |
| and the number of shader storage blocks that can be used per stage. |
| If either limit is exceeded, it will cause a link-time error.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="layout-qualifiers">4.4. Layout Qualifiers</h3> |
| <div class="paragraph"> |
| <p>Layout qualifiers can appear in several forms of declaration. |
| They can appear as part of an interface block definition or block member, as |
| shown in the grammar in the previous section. |
| They can also appear with just an <em>interface-qualifier</em> to establish layouts |
| of other declarations made with that qualifier:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p><em>layout-qualifier</em> <em>interface-qualifier</em> <strong>;</strong></p> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Or, they can appear with an individual variable declared with an interface |
| qualifier:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p><em>layout-qualifier</em> <em>interface-qualifier</em> <em>declaration</em> <strong>;</strong></p> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Declarations of layouts can only be made at global scope or block members, |
| and only where indicated in the following subsections; their details are |
| specific to what the interface qualifier is, and are discussed individually.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>layout-qualifier</em> expands to:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier</em> : </dt> |
| <dd> |
| <p><strong>layout</strong> <strong>(</strong> <em>layout-qualifier-id-list</em> <strong>)</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>layout-qualifier-id-list</em> : </dt> |
| <dd> |
| <p><em>layout-qualifier-id</em><br> |
| <em>layout-qualifier-id</em> <strong>,</strong> <em>layout-qualifier-id-list</em></p> |
| </dd> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><em>layout-qualifier-name</em><br> |
| <em>layout-qualifier-name</em> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>shared</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-value</em> : </dt> |
| <dd> |
| <p><em>integer-constant-expression</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The tokens used for <em>layout-qualifier-name</em> are identifiers, not keywords, |
| however, the <strong>shared</strong> keyword is allowed as a <em>layout-qualifier-id</em>. |
| Generally, they can be listed in any order. |
| Order-dependent meanings exist only if explicitly called out below. |
| Similarly, these identifiers are not case sensitive, unless explicitly noted |
| otherwise.</p> |
| </div> |
| <div class="paragraph"> |
| <p>More than one layout qualifier may appear in a single declaration. |
| Additionally, the same <em>layout-qualifier-name</em> can occur multiple times |
| within a layout qualifier or across multiple layout qualifiers in the same |
| declaration. |
| When the same <em>layout-qualifier-name</em> occurs multiple times, in a single |
| declaration, the last occurrence overrides the former occurrence(s). |
| Further, if such a <em>layout-qualifier-name</em> will affect subsequent |
| declarations or other observable behavior, it is only the last occurrence |
| that will have any effect, behaving as if the earlier occurrence(s) within |
| the declaration are not present. |
| This is also true for overriding <em>layout-qualifier-name</em>, where one |
| overrides the other (e.g. <strong>row_major</strong> vs. |
| <strong>column_major</strong>); only the last occurrence has any effect.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>integer-constant-expression</em> is defined in |
| “<a href="#constant-expressions">Constant Expressions</a>” as <em>constant integral |
| expression</em>, with it being a compile-time error for |
| <em>integer-constant-expression</em> to be a specialization constant.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following table summarizes the use of layout qualifiers. |
| It shows for each one what kinds of declarations it may be applied to. |
| These are all discussed in detail in the following sections.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 16.6666%;"> |
| <col style="width: 16.6666%;"> |
| <col style="width: 16.6666%;"> |
| <col style="width: 16.6666%;"> |
| <col style="width: 16.6666%;"> |
| <col style="width: 16.667%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-middle">Layout Qualifier</th> |
| <th class="tableblock halign-center valign-middle">Qualifier Only</th> |
| <th class="tableblock halign-center valign-middle">Individual Variable</th> |
| <th class="tableblock halign-center valign-middle">Block</th> |
| <th class="tableblock halign-center valign-middle">Block Member</th> |
| <th class="tableblock halign-left valign-middle">Allowed Interfaces</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shared</strong><br> |
| <strong>packed</strong><br> |
| <strong>std140</strong><br> |
| <strong>std430</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle" rowspan="5"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>row_major</strong><br> |
| <strong>column_major</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>binding</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">opaque types only</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>offset</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">atomic counters only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>align</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>set</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">opaque types only</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong> (Vulkan only)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>push_constant</strong></p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> (Vulkan only)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>input_attachment_index</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">subpass types only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> (Vulkan only)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>location</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong> / <strong>buffer</strong> and subroutine variables</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>location</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">all <strong>in</strong> / <strong>out</strong>, except for compute</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>component</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>index</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">fragment <strong>out</strong> and subroutine functions</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>triangles</strong><br> |
| <strong>quads</strong><br> |
| <strong>isolines</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>equal_spacing</strong><br> |
| <strong>fractional_even_spacing</strong><br> |
| <strong>fractional_odd_spacing</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>cw</strong><br> |
| <strong>ccw</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>point_mode</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation evaluation <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>points</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong>/<strong>out</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">[ <strong>points</strong> ]<br> |
| <strong>lines</strong><br> |
| <strong>lines_adjacency</strong><br> |
| <strong>triangles</strong><br> |
| <strong>triangles_adjacency</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>invocations</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">geometry <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>origin_upper_left</strong><br> |
| <strong>pixel_center_integer</strong></p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock"><em>gl_FragCoord</em> only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">fragment <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>early_fragment_tests</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>local_size_x</strong> =<br> |
| <strong>local_size_y</strong> =<br> |
| <strong>local_size_z</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">compute <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>local_size_x_id</strong> =<br> |
| <strong>local_size_y_id</strong> =<br> |
| <strong>local_size_z_id</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">compute <strong>in</strong> (SPIR-V only)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>xfb_buffer</strong> =<br> |
| <strong>xfb_stride</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-left valign-middle" rowspan="2"><p class="tableblock">vertex, tessellation, and geometry <strong>out</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>xfb_offset</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>vertices</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">tessellation control <strong>out</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">[ <strong>points</strong> ]<br> |
| <strong>line_strip</strong><br> |
| <strong>triangle_strip</strong></p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle" rowspan="3"><p class="tableblock">geometry <strong>out</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>max_vertices</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>stream</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>depth_any</strong><br> |
| <strong>depth_greater</strong><br> |
| <strong>depth_less</strong><br> |
| <strong>depth_unchanged</strong></p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock"><em>gl_FragDepth</em> only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock">fragment <strong>out</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>constant_id</strong> =</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">scalar only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>const</strong> (SPIR-V only)</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>rgba32f</strong><br> |
| <strong>rgba16f</strong><br> |
| <strong>rg32f</strong><br> |
| <strong>rg16f</strong><br> |
| <strong>r11f_g11f_b10f</strong><br> |
| <strong>r32f</strong><br> |
| <strong>r16f</strong><br> |
| <strong>rgba16</strong><br> |
| <strong>rgb10_a2</strong><br> |
| <strong>rgba8</strong><br> |
| <strong>rg16</strong><br> |
| <strong>rg8</strong><br> |
| <strong>r16</strong><br> |
| <strong>r8</strong><br> |
| <strong>rgba16_snorm</strong><br> |
| <strong>rgba8_snorm</strong><br> |
| <strong>rg16_snorm</strong><br> |
| <strong>rg8_snorm</strong><br> |
| <strong>r16_snorm</strong><br> |
| <strong>r8_snorm</strong><br> |
| <strong>rgba32i</strong><br> |
| <strong>rgba16i</strong><br> |
| <strong>rgba8i</strong><br> |
| <strong>rg32i</strong><br> |
| <strong>rg16i</strong><br> |
| <strong>rg8i</strong><br> |
| <strong>r32i</strong><br> |
| <strong>r16i</strong><br> |
| <strong>r8i</strong><br> |
| <strong>rgba32ui</strong><br> |
| <strong>rgba16ui</strong><br> |
| <strong>rgb10_a2ui</strong><br> |
| <strong>rgba8ui</strong><br> |
| <strong>rg32ui</strong><br> |
| <strong>rg16ui</strong><br> |
| <strong>rg8ui</strong><br> |
| <strong>r32ui</strong><br> |
| <strong>r16ui</strong><br> |
| <strong>r8ui</strong></p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"><p class="tableblock">image types only</p></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-center valign-middle"></td> |
| <td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniform</strong></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect3"> |
| <h4 id="input-layout-qualifiers">4.4.1. Input Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Layout qualifiers specific to a particular shader language are discussed in |
| separate sections below.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All shaders except compute shaders allow <strong>location</strong> layout qualifiers on |
| input variable declarations, input block declarations, and input block |
| member declarations. |
| Of these, variables and block members (but not blocks) additionally allow |
| the <strong>component</strong> layout qualifier.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>component</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) in vec4 normal; |
| <span class="directive">const</span> <span class="predefined-type">int</span> start = <span class="integer">6</span>; |
| layout(location = start + <span class="integer">2</span>) <span class="predefined-type">int</span> vec4 v;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the shader input <em>normal</em> is assigned to vector location |
| number |
| 3 and <em>v</em> is assigned location number 8. |
| For vertex shader inputs, the location specifies the number of the |
| vertex attribute from which input values are taken. |
| For inputs of all other shader types, the location specifies a vector number |
| that can be used to match against outputs from a previous shader stage, even |
| if that shader is in a different program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following language describes how many locations are consumed by a given |
| type. |
| However, geometry shader inputs, tessellation control shader inputs and |
| outputs, and tessellation evaluation inputs all have an additional level of |
| arrayness relative to other shader inputs and outputs. |
| This outer array level is removed from the type before considering how many |
| locations the type consumes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Except when targeting Vulkan, |
| if a vertex shader input is any scalar or vector type, it will consume a |
| single location. |
| If a non-vertex shader input, or any stage input when targeting Vulkan, |
| is a scalar or vector type other than <strong>dvec3</strong> |
| or <strong>dvec4</strong>, it will consume a single location, while types <strong>dvec3</strong> or |
| <strong>dvec4</strong> will consume two consecutive locations. |
| Inputs of type <strong>double</strong> and <strong>dvec2</strong> will consume only a single location, in |
| all stages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared input (after potentially removing an outer array level as |
| just described above) is an array of size <em>n</em> and each of the elements takes |
| <em>m</em> locations, it will be assigned <em>m</em> * <em>n</em> consecutive locations starting |
| with the location specified. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">6</span>) in vec4 colors[<span class="integer">3</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the shader input <em>colors</em> is assigned to vector location |
| numbers 6, 7, and 8.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared input is an <em>n</em> × <em>m</em> |
| matrix, it will be assigned multiple locations starting with the location |
| specified. |
| The number of locations assigned for each matrix will be the same as for an |
| <em>n</em>-element array of <em>m</em>-component vectors. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">9</span>) in mat4 transforms[<span class="integer">2</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that shader input <em>transforms</em> is assigned to vector |
| locations 9-16, with <em>transforms[0]</em> being assigned to locations 9-12, and |
| <em>transforms[1]</em> being assigned to locations 13-16.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared input is a structure or block, its members will be assigned |
| consecutive locations in their order of declaration, with the first member |
| assigned the location provided in the layout qualifier. |
| For a structure, this process applies to the entire structure. |
| It is a compile-time error to use a <strong>location</strong> qualifier on a member of a |
| structure. |
| For a block, this process applies to the entire block, or until the first |
| member is reached that has a <strong>location</strong> layout qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When a block member is declared with a <strong>location</strong> qualifier, its location |
| comes from that qualifier; the member’s <strong>location</strong> qualifier overrides the |
| block-level declaration. |
| Subsequent members are again assigned consecutive locations, based on the |
| newest location, until the next member declared with a <strong>location</strong> qualifier. |
| The values used for locations do not have to be declared in increasing |
| order.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a block has no block-level <strong>location</strong> layout qualifier, it is required |
| that either all or none of its members have a <strong>location</strong> layout qualifier, |
| or a compile-time error results. |
| For some blocks declared as arrays, the <strong>location</strong> can only be applied at |
| the block level: When a block is declared as an array where additional |
| locations are needed for each member for each block array element, it is a |
| compile-time error to specify locations on the block members. |
| That is, when locations would be under specified by applying them on block |
| members, they are not allowed on block members. |
| For <em>arrayed</em> interfaces (those generally having an extra level of arrayness |
| due to interface expansion), the outer array is stripped before applying |
| this rule.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When generating SPIR-V, all <strong>in</strong> and <strong>out</strong> qualified user-declared (non |
| built-in) variables and blocks (or all their members) must have a |
| shader-specified <strong>location</strong>. |
| Otherwise, a compile-time error is generated.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The locations consumed by block and structure members are determined by |
| applying the rules above recursively as though the structure member were |
| declared as an input variable of the same type. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) in <span class="keyword">struct</span> S |
| { |
| vec3 a; <span class="comment">// gets location 3</span> |
| mat2 b; <span class="comment">// gets locations 4 and 5</span> |
| vec4 c[<span class="integer">2</span>]; <span class="comment">// gets locations 6 and 7</span> |
| layout(location = <span class="integer">8</span>) vec2 A; <span class="comment">// ERROR, can't use on struct member</span> |
| } s; |
| layout(location = <span class="integer">4</span>) in block |
| { |
| vec4 d; <span class="comment">// gets location 4</span> |
| vec4 e; <span class="comment">// gets location 5</span> |
| layout(location = <span class="integer">7</span>) vec4 f; <span class="comment">// gets location 7</span> |
| vec4 g; <span class="comment">// gets location 8</span> |
| layout(location = <span class="integer">1</span>) vec4 h; <span class="comment">// gets location 1</span> |
| vec4 i; <span class="comment">// gets location 2</span> |
| vec4 j; <span class="comment">// gets location 3</span> |
| vec4 k; <span class="comment">// ERROR, location 4 already used</span> |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The number of input locations available to a shader is limited. |
| For vertex shaders, the limit is the advertised number of vertex attributes. |
| For all other shaders, the limit is implementation-dependent and must be no |
| less than one fourth of the advertised maximum input component count.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A program will fail to link if any attached shader uses a location greater |
| than or equal to the number of supported locations, unless device-dependent |
| optimizations are able to make the program fit within available hardware |
| resources.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A program will fail to link if explicit location assignments leave the |
| linker unable to find space for other variables without explicit |
| assignments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the purposes of determining if a non-vertex input matches an output from |
| a previous shader stage, the <strong>location</strong> layout qualifier (if any) must |
| match.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a vertex shader input variable with no location assigned in the shader |
| text has a location specified through the OpenGL API, the API-assigned |
| location will be used. |
| Otherwise, such variables will be assigned a location by the linker. |
| See section 11.1.1 “Vertex Attributes” of the <a href="#references">OpenGL Specification</a> for |
| more details. |
| A link-time error will occur if an input variable is declared in multiple |
| shaders of the same language with conflicting locations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>component</strong> qualifier allows the location to be more finely specified |
| for scalars and vectors, down to the individual components within a location |
| that are consumed. |
| It is a compile-time error to use <strong>component</strong> without also specifying the |
| <strong>location</strong> qualifier (order does not matter). |
| The components within a location are 0, 1, 2, and 3. |
| A variable or block member starting at component <em>N</em> will consume components |
| <em>N</em>, <em>N+1</em>, <em>N+2</em>, …​ |
| up through its size. |
| It is a compile-time error if this sequence of components gets larger than |
| 3. |
| A scalar <strong>double</strong> will consume two of these components, and a <strong>dvec2</strong> will |
| consume all four components available within a location. |
| A <strong>dvec3</strong> or <strong>dvec4</strong> can only be declared without specifying a <strong>component</strong>. |
| A <strong>dvec3</strong> will consume all four components of the first location and |
| components 0 and 1 of the second location. |
| This leaves components 2 and 3 available for other component-qualified |
| declarations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// a consumes components 2 and 3 of location 4</span> |
| layout(location = <span class="integer">4</span>, component = <span class="integer">2</span>) in vec2 a; |
| |
| <span class="comment">// b consumes component 1 of location 4</span> |
| layout(location = <span class="integer">4</span>, component = <span class="integer">1</span>) in <span class="predefined-type">float</span> b; |
| |
| <span class="comment">// ERROR: c overflows component 3</span> |
| layout(location = <span class="integer">3</span>, component = <span class="integer">2</span>) in vec3 c; |
| |
| <span class="comment">// d consumes components 2 and 3 of location 5</span> |
| layout(location = <span class="integer">5</span>, component = <span class="integer">2</span>) in <span class="predefined-type">double</span> d; |
| |
| <span class="comment">// ERROR: e overflows component 3 of location 6</span> |
| layout(location = <span class="integer">6</span>, component = <span class="integer">2</span>) in dvec2 e; |
| |
| <span class="comment">// ERROR: f overlaps with g</span> |
| layout(location = <span class="integer">7</span>, component = <span class="integer">0</span>) <span class="predefined-type">double</span> f; |
| layout(location = <span class="integer">7</span>, component = <span class="integer">1</span>) <span class="predefined-type">float</span> g; |
| |
| layout(location = <span class="integer">8</span>) in dvec3 h; <span class="comment">// components 0,1,2 and 3 of location 8</span> |
| <span class="comment">// and components 0 and 1 of location 9</span> |
| layout(location = <span class="integer">9</span>, component = <span class="integer">2</span>) in <span class="predefined-type">float</span> i; <span class="comment">// okay, compts 2 and 3</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If the variable is an array, each element of the array, in order, is |
| assigned to consecutive locations, but all at the same specified component |
| within each location. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// component 3 in 6 locations are consumed</span> |
| layout(location = <span class="integer">2</span>, component = <span class="integer">3</span>) in <span class="predefined-type">float</span> d[<span class="integer">6</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>That is, location 2 component 3 will hold <em>d[0]</em>, location 3 component 3 |
| will hold <em>d[1]</em>, …​, up through location 7 component 3 holding <em>d[5]</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This allows packing of two arrays into the same set of locations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// e consumes beginning (components 0, 1 and 2) of each of 6 slots</span> |
| layout(location = <span class="integer">0</span>, component = <span class="integer">0</span>) in vec3 e[<span class="integer">6</span>]; |
| |
| <span class="comment">// f consumes last component of the same 6 slots</span> |
| layout(location = <span class="integer">0</span>, component = <span class="integer">3</span>) in <span class="predefined-type">float</span> f[<span class="integer">6</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If applying this to an array of arrays, all levels of arrayness are removed |
| to get to the elements that are assigned per location to the specified |
| component. |
| These non-arrayed elements will fill the locations in the order specified |
| for arrays of arrays in “<a href="#arrays">Arrays</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to apply the <strong>component</strong> qualifier to a matrix, a |
| structure, a block, or an array containing any of these. |
| It is a compile-time error to use <strong>component</strong> 1 or 3 as the beginning of a |
| <strong>double</strong> or <strong>dvec2</strong>. |
| It is a link-time error to specify different components for the same |
| variable within a program.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>Location aliasing</em> is causing two variables or block members to have the |
| same location number. |
| <em>Component aliasing</em> is assigning the same (or overlapping) component |
| numbers for two location aliases. |
| (Recall if <strong>component</strong> is not used, components are assigned starting with |
| 0.) |
| With one exception, location aliasing is allowed only if it does not |
| cause component aliasing; it is a compile-time or link-time error to cause |
| component aliasing. |
| Further, when location aliasing, the aliases sharing the location must have |
| the same underlying numerical type and bit width (floating-point or integer, |
| 32-bit versus 64-bit, etc.) and the same |
| auxiliary storage and interpolation qualification. |
| The one exception where component aliasing is permitted is |
| when targeting OpenGL for two input |
| variables (not block members) to a vertex shader, which are allowed to have |
| component aliasing. |
| This vertex-variable component aliasing is intended only to support vertex |
| shaders where each execution path accesses at most one input per each |
| aliased component. |
| Implementations are permitted, but not required, to generate link-time |
| errors if they detect that every path through the vertex shader executable |
| accesses multiple inputs aliased to any single component.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-evaluation-inputs">Tessellation Evaluation Inputs</h5> |
| <div class="paragraph"> |
| <p>Additional input layout qualifier identifiers allowed for tessellation |
| evaluation shaders are described below.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><em>primitive_mode</em><br> |
| <em>vertex_spacing</em><br> |
| <em>ordering</em><br> |
| <em>point_mode</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>primitive-mode</strong> is used to specify a tessellation primitive mode to be |
| used by the tessellation primitive generator.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>primitive-mode</em>: </dt> |
| <dd> |
| <p><strong>triangles</strong><br> |
| <strong>quads</strong><br> |
| <strong>isolines</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If present, the <em>primitive-mode</em> specifies that the tessellation primitive |
| generator should subdivide a triangle into smaller triangles, a quad into |
| triangles, or a quad into a collection of lines, respectively.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A second group of layout identifiers, <em>vertex spacing</em>, is used to specify |
| the spacing used by the tessellation primitive generator when subdividing an |
| edge.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>vertex-spacing</em>: </dt> |
| <dd> |
| <p><strong>equal_spacing</strong><br> |
| <strong>fractional_even_spacing</strong><br> |
| <strong>fractional_odd_spacing</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><strong>equal_spacing</strong> specifies that edges should be divided into a collection of |
| equal-sized segments;</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>fractional_even_spacing</strong> specifies that edges should be divided into an |
| even number of equal-length segments plus two additional shorter |
| “fractional” 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 “fractional” |
| segments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A third group of layout identifiers, <em>ordering</em>, specifies whether the |
| tessellation primitive generator produces triangles in clockwise or |
| counter-clockwise order, according to the coordinate system depicted in the |
| <a href="#references">OpenGL Specification</a>.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>ordering</em>: </dt> |
| <dd> |
| <p><strong>cw</strong><br> |
| <strong>ccw</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The identifiers <strong>cw</strong> and <strong>ccw</strong> indicate clockwise and counter-clockwise |
| triangles, respectively. |
| If the tessellation primitive generator does not produce triangles, the |
| order is ignored.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Finally, <em>point mode</em> indicates that the tessellation primitive generator |
| should produce one point for each distinct vertex in the subdivided |
| primitive, rather than generating lines or triangles.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>point-mode</em>: </dt> |
| <dd> |
| <p><strong>point_mode</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Any or all of these identifiers may be specified one or more times in a |
| single input layout declaration. |
| If primitive mode, vertex spacing, or ordering is declared more than once in |
| the tessellation evaluation shaders of a program, all such declarations must |
| use the same identifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>At least one tessellation evaluation shader (compilation unit) in a program |
| must declare a primitive mode in its input layout. |
| Declaring vertex spacing, ordering, or point mode identifiers is optional. |
| It is not required that all tessellation evaluation shaders in a program |
| declare a primitive mode. |
| If spacing or vertex ordering declarations are omitted, the tessellation |
| primitive generator will use equal spacing or counter-clockwise vertex |
| ordering, respectively. |
| If a point mode declaration is omitted, the tessellation primitive generator |
| will produce lines or triangles according to the primitive mode.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="geometry-shader-inputs">Geometry Shader Inputs</h5> |
| <div class="paragraph"> |
| <p>Additional layout qualifier identifiers for geometry shader inputs include |
| <em>primitive</em> identifiers and an <em>invocation count</em> identifier:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>points</strong><br> |
| <strong>lines</strong><br> |
| <strong>lines_adjacency</strong><br> |
| <strong>triangles</strong><br> |
| <strong>triangles_adjacency</strong><br> |
| <strong>invocations</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The identifiers <strong>points</strong>, <strong>lines</strong>, <strong>lines_adjacency</strong>, <strong>triangles</strong>, and |
| <strong>triangles_adjacency</strong> are used to specify the type of input primitive |
| accepted by the geometry shader, and only one of these is accepted. |
| At least one geometry shader (compilation unit) in a program must declare |
| this input primitive layout, and all geometry shader input layout |
| declarations in a program must declare the same layout. |
| It is not required that all geometry shaders in a program declare an input |
| primitive layout.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The identifier <strong>invocations</strong> is used to specify the number of times the |
| geometry shader executable is invoked for each input primitive received. |
| Invocation count declarations are optional. |
| If no invocation count is declared in any geometry shader in a program, the |
| geometry shader will be run once for each input primitive. |
| If an invocation count is declared, all such declarations must specify the |
| same count. |
| If a shader specifies an invocation count greater than the |
| implementation-dependent maximum, or less than or equal to zero, |
| a compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(triangles, invocations = <span class="integer">6</span>) in;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that all inputs to the geometry shader are triangles and that |
| the geometry shader executable is run six times for each triangle processed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All geometry shader input unsized array declarations will be sized by an |
| earlier input primitive layout qualifier, when present, as per the following |
| table.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Layout</th> |
| <th class="tableblock halign-left valign-top">Size of Input Arrays</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>points</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lines</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lines_adjacency</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>triangles</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>triangles_adjacency</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The intrinsically declared input array <em>gl_in[]</em> will also be sized by any |
| input primitive-layout declaration. |
| Hence, the expression</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_in.length()</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will return the value from the table above.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For inputs declared without an array size, including intrinsically declared |
| inputs (i.e., <em>gl_in</em>), a layout must be declared before any use of the |
| method <strong>length</strong>() or other any array use that requires the array size to be |
| known.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error if a layout declaration’s array size (from the |
| table above) does not match all the explicit array sizes specified in |
| declarations of an input variables in the same shader. |
| The following includes examples of compile-time errors:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// code sequence within one shader...</span> |
| in vec4 Color1[]; <span class="comment">// legal, size still unknown</span> |
| in vec4 Color2[<span class="integer">2</span>]; <span class="comment">// legal, size is 2</span> |
| in vec4 Color3[<span class="integer">3</span>]; <span class="comment">// illegal, input sizes are inconsistent</span> |
| layout(lines) in; <span class="comment">// legal for Color2, input size is 2, matching Color2</span> |
| in vec4 Color4[<span class="integer">3</span>]; <span class="comment">// illegal, contradicts layout of lines</span> |
| layout(lines) in; <span class="comment">// legal, matches other layout() declaration</span> |
| layout(triangles) in; <span class="comment">// illegal, does not match earlier layout() declaration</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is a link-time error if not all provided sizes (sized input arrays and |
| layout size) match across all geometry shaders in a program.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="fragment-shader-inputs">Fragment Shader Inputs</h5> |
| <div class="paragraph"> |
| <p>Additional fragment layout qualifier identifiers include the following for |
| <em>gl_FragCoord</em> :</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>origin_upper_left</strong><br> |
| <strong>pixel_center_integer</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>By default, <em>gl_FragCoord</em> in OpenGL assumes a lower-left origin for window |
| coordinates and assumes pixel centers are located at half-pixel coordinates. |
| For example, the (<em>x, y</em>) location (0.5, 0.5) is returned for the |
| lower-left-most pixel in a window. |
| The origin can be changed by redeclaring <em>gl_FragCoord</em> with the |
| <strong>origin_upper_left</strong> qualifier, moving the origin of <em>gl_FragCoord</em> to the |
| upper left of the window, with <em>y</em> increasing in value toward the bottom of |
| the window. |
| The values returned can also be shifted by half a pixel in both <em>x</em> and <em>y</em> |
| by <strong>pixel_center_integer</strong> so it appears the pixels are centered at whole |
| number pixel offsets. |
| This moves the (<em>x</em>, <em>y</em>) value returned by <em>gl_FragCoord</em> of (0.5, 0.5) by |
| default, to (0.0, 0.0) with <strong>pixel_center_integer</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Targeting Vulkan will assume and require an upper-left origin for <em>gl_FragCoord</em> |
| with pixel centers located at half-pixel coordinates. |
| This origin can be explicitly set by redeclaring <em>gl_FragCoord</em> with the |
| <strong>origin_upper_left</strong> identifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Redeclarations are done as follows</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_FragCoord; <span class="comment">// redeclaration that changes nothing is allowed</span> |
| |
| <span class="comment">// All the following are allowed redeclaration that change behavior</span> |
| layout(origin_upper_left) in vec4 gl_FragCoord; |
| layout(pixel_center_integer) in vec4 gl_FragCoord; |
| layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>gl_FragCoord</em> is redeclared in any fragment shader in a program, it must |
| be redeclared in all the fragment shaders in that program that have a static |
| use <em>gl_FragCoord</em>. |
| All redeclarations of <em>gl_FragCoord in all fragment shaders in a single |
| program must have the same set of qualifiers. |
| Within any shader, the first redeclarations of _glFragCoord</em> must appear |
| before any use of <em>gl_FragCoord</em>. |
| The built-in <em>gl_FragCoord</em> is only predeclared in fragment shaders, so |
| redeclaring it in any other shader language results in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Redeclaring <em>glFragCoord</em> with <strong>origin_upper_left</strong> and/or |
| <strong>pixel_center_integer</strong> qualifiers only affects <em>gl_FragCoord.x</em> and |
| <em>gl_FragCoord.y</em>. |
| It has no effect on rasterization, transformation, or any other part of the |
| API pipeline or language features.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment shaders allow the following layout qualifier on <strong>in</strong> only (not with |
| variable declarations):</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>early_fragment_tests</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>to request that fragment tests be performed before fragment shader |
| execution, as described in section 15.2.4 “Early Fragment Tests” of the |
| <a href="#references">OpenGL Specification</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(early_fragment_tests) in;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Specifying this will make per-fragment tests be performed before fragment |
| shader execution. |
| If this is not declared, per-fragment tests will be performed after fragment |
| shader execution. |
| Only one fragment shader (compilation unit) need declare this, though more |
| than one can. |
| If at least one declares this, then it is enabled.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="compute-shader-inputs">Compute Shader Inputs</h5> |
| <div class="paragraph"> |
| <p>There are no layout location qualifiers for compute shader inputs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Layout qualifier identifiers for compute shader inputs are the workgroup |
| size qualifiers:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>local_size_x</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>local_size_y</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>local_size_z</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong> qualifiers are used |
| to declare a fixed workgroup size by the compute shader in the first, |
| second, and third dimension, respectively. |
| If a shader does not specify a size for one of the dimensions, that |
| dimension will have a size of 1.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, the following declaration in a compute shader</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">32</span>, local_size_y = <span class="integer">32</span>) in;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is used to declare a two-dimensional compute shader with a workgroup size of 32 |
| X 32 elements, which is equivalent to a three-dimensional compute shader |
| where the third dimension has size one.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As another example, the declaration</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">8</span>) in;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>effectively specifies that a one-dimensional compute shader is being |
| compiled, and its size is 8 elements.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the fixed workgroup size of the shader in any dimension is less than |
| or equal to zero or greater than the maximum size supported by the |
| implementation for that dimension, a compile-time error results. |
| Also, if such a layout qualifier is declared more than once in the same |
| shader, all those declarations must set the same set of workgroup |
| sizes and set them to the same values; otherwise a compile-time error |
| results. |
| If multiple compute shaders attached to a single program object declare a |
| fixed workgroup size, the declarations must be identical; otherwise a |
| link-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Furthermore, if a program object contains any compute shaders, at least one |
| must contain an input layout qualifier specifying a fixed workgroup size |
| for the program, or a link-time error will occur.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="output-layout-qualifiers">4.4.2. Output Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Some output layout qualifiers apply to all shader stages and some apply only |
| to specific stages. |
| The latter are discussed in separate sections below.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As with input layout qualifiers, all shaders except compute shaders allow |
| <strong>location</strong> layout qualifiers on output variable declarations, output block |
| declarations, and output block member declarations. |
| Of these, variables and block members (but not blocks) additionally allow |
| the <strong>component</strong> layout qualifier.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>component</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The usage and rules for applying the <strong>location</strong> qualifier |
| and the <strong>component</strong> qualifier |
| to blocks and structures are exactly as described in |
| “<a href="#input-layout-qualifiers">Input Layout Qualifiers</a>”. |
| Additionally, for fragment shader outputs, if two variables are placed |
| within the same location, they must have the same underlying type |
| (floating-point or integer). |
| No component aliasing of output variables or members is allowed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment shaders allow an additional <strong>index</strong> output layout qualifier:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>index</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Each of these qualifiers may appear at most once. |
| If <strong>index</strong> is specified, <strong>location</strong> must also be specified. |
| If <strong>index</strong> is not specified, the value 0 is used. |
| For example, in a fragment shader,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>) out vec4 color;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the fragment shader output <em>color</em> is assigned to |
| fragment color 3 as the first (index zero) input to the blend equation. |
| And,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">3</span>, index = <span class="integer">1</span>) out vec4 factor;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the fragment shader output <em>factor</em> is assigned to |
| fragment color 3 as the second (index one) input to the blend equation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For fragment shader outputs, the location |
| and index specify |
| the color output number |
| and index |
| receiving the values of the output. |
| For outputs of all other shader stages, the location specifies a vector |
| number that can be used to match against inputs in a subsequent shader |
| stage, even if that shader is in a different program object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a declared output is a scalar or vector type other than <strong>dvec3</strong> or |
| <strong>dvec4</strong>, it will consume a single location. |
| Outputs of type <strong>dvec3</strong> or <strong>dvec4</strong> will consume two consecutive locations. |
| Outputs of type <strong>double</strong> and <strong>dvec2</strong> will consume only a single location, in |
| all stages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared output is an array, it will be assigned consecutive |
| locations starting with the location specified. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(location = <span class="integer">2</span>) out vec4 colors[<span class="integer">3</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that <em>colors</em> is assigned to vector location numbers 2, 3, |
| and 4.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared output is an <em>n</em> × <em>m</em> |
| matrix, it will be assigned multiple locations starting with the location |
| specified. |
| The number of locations assigned will be the same as for an <em>n</em>-element |
| array of <em>m</em>-component vectors.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the declared output is a structure, its members will be assigned |
| consecutive locations in the order of declaration, with the first member |
| assigned the location specified for the structure. |
| The number of locations consumed by a structure member is determined by |
| applying the rules above recursively as though the structure member were |
| declared as an output variable of the same type.</p> |
| </div> |
| <div class="paragraph"> |
| <p><strong>location</strong> layout qualifiers may be used on output variables declared as |
| structures. |
| However, it is a compile-time error to use a <strong>location</strong> qualifier on a |
| structure member. |
| Location layout qualifiers may be used on output blocks and output block |
| members.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The number of output locations available to a shader is limited. |
| For fragment shaders, the limit is the advertised number of draw buffers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For all other shaders, the limit is implementation-dependent and must be no |
| less than one fourth of the advertised maximum output component count |
| (compute shaders have no outputs). |
| A program will fail to link if any attached shader uses a location greater |
| than or equal to the number of supported locations, unless device-dependent |
| optimizations are able to make the program fit within available hardware |
| resources.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Compile-time errors may also be given if at compile time it is known the |
| link will fail. |
| A negative output location will result in a compile-time error. |
| It is also a compile-time error if a fragment shader sets a layout index to |
| less than 0 or greater than 1.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time or link-time error if any of the following occur:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>any two fragment shader output variables are assigned to the same |
| location and index.</p> |
| </li> |
| <li> |
| <p>if any two output variables from the same vertex, tessellation or |
| geometry shader stage are assigned to the same location.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For fragment shader outputs, locations can be assigned using either a |
| <strong>layout</strong> qualifier or via the OpenGL API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For all shader types, a program will fail to link if explicit location |
| assignments leave the linker unable to find space for other variables |
| without explicit assignments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If an output variable with no location or index assigned in the shader text |
| has a location specified through the OpenGL API, the API-assigned |
| location will be used. |
| Otherwise, such variables will be assigned a location by the linker. |
| All such assignments will have a color index of zero. |
| See section 15.2 “Shader Execution” of the <a href="#references">OpenGL Specification</a> for |
| more details. |
| A link-time error will occur if an output variable is declared in multiple |
| shaders of the same language with conflicting location or index values.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the purposes of determining if a non-fragment output matches an input |
| from a subsequent shader stage, the <strong>location</strong> layout qualifier (if any) |
| must match.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="transform-feedback-layout-qualifiers">Transform Feedback Layout Qualifiers</h5> |
| <div class="paragraph"> |
| <p>The vertex, tessellation, and geometry stages allow shaders to control |
| transform feedback. |
| When doing this, shaders will dictate which transform feedback buffers are |
| in use, which output variables will be written to which buffers, and how |
| each buffer is laid out. |
| To accomplish this, shaders allow the following layout qualifier identifiers |
| on output declarations:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>xfb_buffer</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>xfb_offset</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>xfb_stride</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Any shader making any static use (after preprocessing) of any of these |
| <strong>xfb_</strong> qualifiers will cause the shader to be in a transform feedback |
| capturing mode and hence responsible for describing the transform feedback |
| setup. |
| This mode will capture any output selected by <strong>xfb_offset</strong>, directly or |
| indirectly, to a transform feedback buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>xfb_buffer</strong> qualifier specifies which transform feedback buffer will |
| capture outputs selected with <strong>xfb_offset</strong>. |
| The <strong>xfb_buffer</strong> qualifier can be applied to the qualifier <strong>out</strong>, to output |
| variables, to output blocks, and to output block members. |
| Shaders in the transform feedback capturing mode have an initial global |
| default of</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(xfb_buffer = <span class="integer">0</span>) out;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This default can be changed by declaring a different buffer with |
| <strong>xfb_buffer</strong> on the interface qualifier <strong>out</strong>. |
| This is the only way the global default can be changed. |
| When a variable or output block is declared without an <strong>xfb_buffer</strong> |
| qualifier, it inherits the global default buffer. |
| When a variable or output block is declared with an <strong>xfb_buffer</strong> qualifier, |
| it has that declared buffer. |
| All members of a block inherit the block’s buffer. |
| A member is allowed to declare an <strong>xfb_buffer</strong>, but it must match the buffer |
| inherited from its block, or a compile-time error results.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(xfb_buffer=<span class="integer">2</span>, xfb_offset=<span class="integer">0</span>) out block { <span class="comment">// block's buffer is 2</span> |
| layout(xfb_buffer = <span class="integer">2</span>) vec4 v; <span class="comment">// okay, matches the inherited 2</span> |
| layout(xfb_buffer = <span class="integer">3</span>) vec4 u; <span class="comment">// ERROR, mismatched buffer</span> |
| vec4 w; <span class="comment">// inherited</span> |
| }; |
| layout(xfb_offset=<span class="integer">16</span>) out vec4 t; <span class="comment">// initial default is buffer 0</span> |
| layout(xfb_buffer=<span class="integer">1</span>) out; <span class="comment">// new global default of 1</span> |
| out block { <span class="comment">// block has buffer 1</span> |
| vec4 x; <span class="comment">// x has buffer 1 (not captured)</span> |
| layout(xfb_buffer = <span class="integer">1</span>) vec4 y; <span class="comment">// okay (not captured)</span> |
| layout(xfb_buffer = <span class="integer">0</span>) vec4 z; <span class="comment">// ERROR, mismatched buffer</span> |
| }; |
| layout(xfb_offset=<span class="integer">0</span>) out vec4 g; <span class="comment">// g has buffer 1</span> |
| layout(xfb_buffer=<span class="integer">2</span>) out vec4 h; <span class="comment">// does not change global default</span> |
| layout(xfb_offset=<span class="integer">16</span>) out vec4 j; <span class="comment">// j has buffer 1</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note this means all members of a block that go to a transform feedback |
| buffer will go to the same buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When a block is declared as an array, all members of block array-element 0 |
| are captured, as previously described, by the declared or inherited |
| <strong>xfb_buffer</strong>. |
| Generally, an array of size <em>N</em> of blocks is captured by <em>N</em> consecutive |
| buffers, with all members of block array-element <em>E</em> captured by buffer <em>B</em>, |
| where <em>B</em> equals the declared or inherited <strong>xfb_buffer</strong> plus <em>E</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time or link-time error to specify an <strong>xfb_buffer</strong>, |
| including any additional buffers needed to capture an arrays of blocks, that |
| is less than zero or greater than or equal to the implementation-dependent |
| constant <em>gl_MaxTransformFeedbackBuffers</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>xfb_offset</strong> qualifier assigns a byte offset within a transform feedback |
| buffer. |
| Only variables, block members, or blocks can be qualified with <strong>xfb_offset</strong>. |
| If a block is qualified with <strong>xfb_offset</strong>, all its members are assigned |
| transform feedback buffer offsets. |
| If a block is not qualified with <strong>xfb_offset</strong>, any members of that block not |
| qualified with an <strong>xfb_offset</strong> will not be assigned transform feedback |
| buffer offsets. |
| Only variables and block members that are assigned offsets will be captured |
| (thus, a proper subset of a block can be captured). |
| Each time such a variable or block member is written in a shader, the |
| written value is captured at the assigned offset. |
| If such a block member or variable is not written during a shader |
| invocation, the buffer contents at the assigned offset will be undefined. |
| Even if there are no static writes to a variable or member that is assigned |
| a transform feedback offset, the space is still allocated in the buffer and |
| still affects the stride.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Variables and block members qualified with <strong>xfb_offset</strong> can be scalars, |
| vectors, matrices, structures, and (sized) arrays of these. |
| The offset must be a multiple of the size of the first component of the |
| first qualified variable or block member, or a compile-time error results. |
| Further, if applied to an aggregate containing a <strong>double</strong>, the offset must |
| also be a multiple of 8, and the space taken in the buffer will be a |
| multiple of 8. |
| The given offset applies to the first component of the first member of the |
| qualified entity. |
| Then, within the qualified entity, subsequent components are each assigned, |
| in order, to the next available offset aligned to a multiple of that |
| component’s size. |
| Aggregate types are flattened down to the component level to get this |
| sequence of components. |
| It is a compile-time error to apply <strong>xfb_offset</strong> to the declaration of an |
| unsized array.</p> |
| </div> |
| <div class="paragraph"> |
| <p>No aliasing in output buffers is allowed: It is a compile-time or link-time |
| error to specify variables with overlapping transform feedback offsets.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>xfb_stride</strong> qualifier specifies how many bytes are consumed by each |
| captured vertex. |
| It applies to the transform feedback buffer for that declaration, whether it |
| is inherited or explicitly declared. |
| It can be applied to variables, blocks, block members, or just the qualifier |
| <strong>out</strong>. |
| If the buffer is capturing any outputs with double-precision components, the |
| stride must be a multiple of 8, otherwise it must be a multiple of 4, or a |
| compile-time or link-time error results. |
| It is a compile-time or link-time error to have any <strong>xfb_offset</strong> that |
| overflows <strong>xfb_stride</strong>, whether stated on declarations before or after the |
| <strong>xfb_stride</strong>, or in different compilation units. |
| While <strong>xfb_stride</strong> can be declared multiple times for the same buffer, it is |
| a compile-time or link-time error to have different values specified for the |
| stride for the same buffer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// buffer 1 has 32-byte stride</span> |
| layout(xfb_buffer = <span class="integer">1</span>, xfb_stride = <span class="integer">32</span>) out; |
| |
| <span class="comment">// same as previous example; order within layout does not matter</span> |
| layout(xfb_stride = <span class="integer">32</span>, xfb_buffer = <span class="integer">1</span>) out; |
| |
| <span class="comment">// everything in this block goes to buffer 0</span> |
| layout(xfb_buffer = <span class="integer">0</span>, xfb_stride = <span class="integer">32</span>) out block1 { |
| layout(xfb_offset = <span class="integer">0</span>) vec4 a; <span class="comment">// a goes to byte offset 0 of buffer 0</span> |
| layout(xfb_offset = <span class="integer">16</span>) vec4 b; <span class="comment">// b goes to offset 16 of buffer 0</span> |
| }; |
| |
| layout(xfb_buffer = <span class="integer">3</span>, xfb_offset = <span class="integer">12</span>) out block2 { |
| vec4 v; <span class="comment">// v will be written to byte offsets 12 through 27 of buffer</span> |
| <span class="predefined-type">float</span> u; <span class="comment">// u will be written to offset 28</span> |
| layout(xfb_offset = <span class="integer">40</span>) vec4 w; |
| vec4 x; <span class="comment">// x will be written to offset 56, the next available offset</span> |
| }; |
| |
| layout(xfb_buffer = <span class="integer">2</span>, xfb_stride = <span class="integer">32</span>) out block3 { |
| layout(xfb_offset = <span class="integer">12</span>) vec3 c; |
| layout(xfb_offset = <span class="integer">24</span>) vec3 d; <span class="comment">// ERROR, requires stride of 36</span> |
| layout(xfb_offset = <span class="integer">0</span>) vec3 g; <span class="comment">// okay, increasing order not required</span> |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When no <strong>xfb_stride</strong> is specified for a buffer, the stride of the buffer |
| will be the smallest needed to hold the variable placed at the highest |
| offset, including any required padding. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// if there no other declarations for buffer 3, it has stride 32</span> |
| layout(xfb_buffer = <span class="integer">3</span>) out block4 { |
| layout(xfb_offset = <span class="integer">0</span>) vec4 e; |
| layout(xfb_offset = <span class="integer">16</span>) vec4 f; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The resulting stride (implicit or explicit), when divided by 4, must be less |
| than or equal to the implementation-dependent constant |
| <em>gl_MaxTransformFeedbackInterleavedComponents</em>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-control-outputs">Tessellation Control Outputs</h5> |
| <div class="paragraph"> |
| <p>Other than for the transform feedback layout qualifiers, tessellation |
| control shaders allow output layout qualifiers only on the interface |
| qualifier <strong>out</strong>, not on an output block, block member, or variable |
| declaration. |
| The output layout qualifier identifiers allowed for tessellation control |
| shaders are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>vertices</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The identifier <strong>vertices</strong> specifies the number of vertices in the output |
| patch produced by the tessellation control shader, which also specifies the |
| number of times the tessellation control shader is invoked. |
| It is a compile- or link-time error for the output vertex count to be less |
| than or equal to zero, or greater than the implementation-dependent maximum |
| patch size.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The intrinsically declared tessellation control output array <em>gl_out[]</em> will |
| also be sized by any output layout declaration. |
| Hence, the expression</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_out.length()</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will return the output patch vertex count specified in a previous output |
| layout qualifier. |
| For outputs declared without an array size, including intrinsically declared |
| outputs (i.e., <em>gl_out</em>), a layout must be declared before any use of the |
| method <strong>length</strong>() or other array use that requires its size to be known.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error if the output patch vertex count specified in an |
| output layout qualifier does not match the array size specified in any |
| output variable declaration in the same shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All tessellation control shader layout declarations in a program must |
| specify the same output patch vertex count. |
| There must be at least one layout qualifier specifying an output patch |
| vertex count in any program containing tessellation control shaders; |
| however, such a declaration is not required in all tessellation control |
| shaders.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="geometry-outputs">Geometry Outputs</h5> |
| <div class="paragraph"> |
| <p>Geometry shaders can have three additional types of output layout |
| identifiers: an output <em>primitive type</em>, a maximum output <em>vertex count</em>, |
| and per-output <em>stream</em> numbers. |
| The primitive type and vertex count identifiers are allowed only on the |
| interface qualifier <strong>out</strong>, not on an output block, block member, or variable |
| declaration. |
| The stream identifier is allowed on the interface qualifier <strong>out</strong>, on output |
| blocks, and on variable declarations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The layout qualifier identifiers for geometry shader outputs are</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>points</strong><br> |
| <strong>line_strip</strong><br> |
| <strong>triangle_strip</strong><br> |
| <strong>max_vertices</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>stream</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The primitive type identifiers <strong>points</strong>, <strong>line_strip</strong>, and <strong>triangle_strip</strong> |
| are used to specify the type of output primitive produced by the geometry |
| shader, and only one of these is accepted. |
| At least one geometry shader (compilation unit) in a program must declare an |
| output primitive type, and all geometry shader output primitive type |
| declarations in a program must declare the same primitive type. |
| It is not required that all geometry shaders in a program declare an output |
| primitive type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The vertex count identifier <strong>max_vertices</strong> is used to specify the maximum |
| number of vertices the shader will ever emit in a single invocation. |
| At least one geometry shader (compilation unit) in a program must declare a |
| maximum output vertex count, and all geometry shader output vertex count |
| declarations in a program must declare the same count. |
| It is not required that all geometry shaders in a program declare a count.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(triangle_strip, max_vertices = <span class="integer">60</span>) out; <span class="comment">// order does not matter</span> |
| layout(max_vertices = <span class="integer">60</span>) out; <span class="comment">// redeclaration okay</span> |
| layout(triangle_strip) out; <span class="comment">// redeclaration okay</span> |
| layout(points) out; <span class="comment">// error, contradicts triangle_strip</span> |
| layout(max_vertices = <span class="integer">30</span>) out; <span class="comment">// error, contradicts 60</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>all outputs from the geometry shader are triangles and at most 60 vertices |
| will be emitted by the shader. |
| It is an error for the maximum number of vertices to be greater than |
| <em>gl_MaxGeometryOutputVertices</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The identifier <strong>stream</strong> is used to specify that a geometry shader output |
| variable or block is associated with a particular vertex stream (numbered |
| beginning with zero). |
| A default stream number may be declared at global scope by qualifying |
| interface qualifier <strong>out</strong> as in this example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(stream = <span class="integer">1</span>) out;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The stream number specified in such a declaration replaces any previous |
| default and applies to all subsequent block and variable declarations until |
| a new default is established. |
| The initial default stream number is zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each output block or non-block output variable is associated with a vertex |
| stream. |
| If the block or variable is declared with the stream identifier, it is |
| associated with the specified stream; otherwise, it is associated with the |
| current default stream. |
| A block member may be declared with a stream identifier, but the specified |
| stream must match the stream associated with the containing block. |
| One example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(stream=<span class="integer">1</span>) out; <span class="comment">// default is now stream 1</span> |
| out vec4 var1; <span class="comment">// var1 gets default stream (1)</span> |
| layout(stream=<span class="integer">2</span>) out Block1 { <span class="comment">// "Block1" belongs to stream 2</span> |
| layout(stream=<span class="integer">2</span>) vec4 var2; <span class="comment">// redundant block member stream decl</span> |
| layout(stream=<span class="integer">3</span>) vec2 var3; <span class="comment">// ILLEGAL (must match block stream)</span> |
| vec3 var4; <span class="comment">// belongs to stream 2</span> |
| }; |
| layout(stream=<span class="integer">0</span>) out; <span class="comment">// default is now stream 0</span> |
| out vec4 var5; <span class="comment">// var5 gets default stream (0)</span> |
| out Block2 { <span class="comment">// "Block2" gets default stream (0)</span> |
| vec4 var6; |
| }; |
| layout(stream=<span class="integer">3</span>) out vec4 var7; <span class="comment">// var7 belongs to stream 3</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Each vertex emitted by the geometry shader is assigned to a specific stream, |
| and the attributes of the emitted vertex are taken from the set of output |
| blocks and variables assigned to the targeted stream. |
| After each vertex is emitted, the values of all output variables become |
| undefined. |
| Additionally, the output variables associated with each vertex stream may |
| share storage. |
| Writing to an output variable associated with one stream may overwrite |
| output variables associated with any other stream. |
| When emitting each vertex, a geometry shader should write to all outputs |
| associated with the stream to which the vertex will be emitted and to no |
| outputs associated with any other stream.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a geometry shader output block or variable is declared more than once, |
| all such declarations must associate the variable with the same vertex |
| stream. |
| If any stream declaration specifies a non-existent stream number, the shader |
| will fail to compile.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Built-in geometry shader outputs are always associated with vertex stream |
| zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All geometry shader output layout declarations in a program must declare the |
| same layout and same value for <strong>max_vertices</strong>. |
| If geometry shaders are in a program, there must be at least one geometry |
| output layout declaration somewhere in that |
| program, but not all geometry |
| shaders (compilation units) are required to declare it.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="fragment-outputs">Fragment Outputs</h5> |
| <div class="paragraph"> |
| <p>The built-in fragment shader variable <em>gl_FragDepth</em> may be redeclared using |
| one of the following layout qualifiers.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>depth_any</strong><br> |
| <strong>depth_greater</strong><br> |
| <strong>depth_less</strong><br> |
| <strong>depth_unchanged</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The layout qualifier for <em>gl_FragDepth</em> constrains intentions of the final |
| value of <em>gl_FragDepth</em> written by any shader invocation. |
| GL implementations are allowed to perform optimizations assuming that the |
| depth test fails (or passes) for a given fragment if all values of |
| <em>gl_FragDepth</em> consistent with the layout qualifier would fail (or pass). |
| This potentially includes skipping shader execution if the fragment is |
| discarded because it is occluded and the shader has no side effects. |
| If the final value of <em>gl_FragDepth</em> is inconsistent with its layout |
| qualifier, the result of the depth test for the corresponding fragment is |
| undefined. |
| However, no error will be generated in this case. |
| If the depth test passes and depth writes are enabled, the value written to |
| the depth buffer is always the value of <em>gl_FragDepth</em>, whether or not it is |
| consistent with the layout qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By default, <em>gl_FragDepth</em> is qualified as <em>depth_any</em>. |
| When the layout qualifier for <em>gl_FragDepth</em> is <em>depth_any</em>, the shader |
| compiler will note any assignment to <em>gl_FragDepth</em> modifying it in an |
| unknown way, and depth testing will always be performed after the shader has |
| executed. |
| When the layout qualifier is <em>depth_greater</em>, the GL can assume that the |
| final value of <em>gl_FragDepth</em> is greater than or equal to the fragment’s |
| interpolated depth value, as given by the <em>z</em> component of <em>gl_FragCoord</em>. |
| When the layout qualifier is <em>depth_less</em>, the GL can assume that any |
| modification of <em>gl_FragDepth</em> will only decrease its value. |
| When the layout qualifier is <em>depth_unchanged</em>, the shader compiler will |
| honor any modification to <em>gl_FragDepth</em>, but the rest of the GL can assume |
| that <em>gl_FragDepth</em> is not assigned a new value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Redeclarations of <em>gl_FragDepth</em> are performed as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// redeclaration that changes nothing is allowed +</span> |
| out <span class="predefined-type">float</span> gl_FragDepth; |
| |
| <span class="comment">// assume it may be modified in any way</span> |
| layout(depth_any) out <span class="predefined-type">float</span> gl_FragDepth; |
| |
| <span class="comment">// assume it may be modified such that its value will only increase</span> |
| layout(depth_greater) out <span class="predefined-type">float</span> gl_FragDepth; |
| |
| <span class="comment">// assume it may be modified such that its value will only decrease</span> |
| layout(depth_less) out <span class="predefined-type">float</span> gl_FragDepth; |
| |
| <span class="comment">// assume it will not be modified</span> |
| layout(depth_unchanged) out <span class="predefined-type">float</span> gl_FragDepth;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>gl_FragDepth</em> is redeclared in any fragment shader in a program, it must |
| be redeclared in all fragment shaders in that program that have static |
| assignments to <em>gl_FragDepth</em>. |
| All redeclarations of <em>gl_FragDepth</em> in all fragment shaders in a single |
| program must have the same set of qualifiers. |
| Within any shader, the first redeclarations of <em>gl_FragDepth</em> must appear |
| before any use of <em>gl_FragDepth</em>. |
| The built-in <em>gl_FragDepth</em> is only predeclared in fragment shaders, so |
| redeclaring it in any other shader language results in a compile-time error.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="uniform-variable-layout-qualifiers">4.4.3. Uniform Variable Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Layout qualifiers can be used for uniform variables and subroutine uniforms. |
| The layout qualifier identifiers for uniform variables and subroutine |
| uniforms are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>location</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The location identifier can be used with default-block uniform variables and |
| subroutine uniforms. |
| The location specifies the location by which the API can reference |
| the uniform and update its value. |
| Individual elements of a uniform array are assigned consecutive locations |
| with the first element taking location <strong>location</strong>. |
| Default-block uniform variable declarations sharing the same location |
| linked in the program have to match by name, type, qualifiers and arrayness. |
| For arrays their array dimensionality and array sizes must match. |
| For structs this rule applies recursively to all members. |
| No two subroutine uniform variables can have the same location in the same |
| shader stage, otherwise a compile-time or link-time error will be generated. |
| Valid locations for default-block uniform variable locations are in the |
| range of 0 to the implementation-defined maximum number of uniform locations |
| minus one. |
| Valid locations for subroutine uniforms are in the range of 0 to the |
| implementation-defined per-stage maximum number of subroutine uniform |
| locations minus one.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Locations can be assigned to default-block uniform arrays and structures. |
| The first inner-most scalar, vector or matrix member or element takes the |
| specified <strong>location</strong> and the compiler assigns the next inner-most member or |
| element the next incremental location value. |
| Each subsequent inner-most member or element gets incremental locations for |
| the entire structure or array. |
| This rule applies to nested structures and arrays and gives each inner-most |
| scalar, vector, or matrix member a unique location. |
| For arrays without an explicit size, the size is calculated based on its |
| static usage. |
| When the linker generates locations for uniforms without an explicit |
| location, it assumes for all uniforms with an explicit location all their |
| array elements and structure members are used and the linker will not |
| generate a conflicting location, even if that element or member is deemed |
| unused.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When generating SPIR-V for API’s that accept individual (default block) |
| non-opaque uniform variables, it is a compile-time error to not |
| include a location when declaring them.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan, the <strong>push_constant</strong> qualifier is used to |
| declare an entire block, and represents a set of <em>push constants</em>, as defined |
| by the Vulkan API. |
| It is a compile-time error to apply this to anything other than a uniform block |
| declaration, or when not targeting Vulkan. |
| The values in the block will be initialized as per the Vulkan API specification. |
| A block declared with <code>layout(push_constant)</code> may optionally include an |
| <em>instance-name</em>. |
| There can be only one <strong>push_constant</strong> block per stage, or a compile-time or |
| link-time error will result. |
| A push-constant array can only be indexed with dynamically uniform indices. |
| Uniform blocks declared with <strong>push_constant</strong> use different resources |
| than those without; and are accounted for separately.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="subroutine-function-layout-qualifiers">4.4.4. Subroutine Function Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Layout qualifiers can be used for subroutine functions. |
| The layout qualifier identifiers for subroutine functions are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>index</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Each subroutine with an index qualifier in the shader must be given a unique |
| index, otherwise a compile- or link-time error will be generated. |
| The indices must be in the range of 0 to the implementation defined maximum |
| number of subroutines minus one. |
| It is recommended, but not required, that the shader assigns a range of |
| tightly packed <em>index</em> values starting from zero so that the OpenGL |
| subroutine function enumeration API returns a non-empty name for all active |
| indices.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="uniform-and-shader-storage-block-layout-qualifiers">4.4.5. Uniform and Shader Storage Block Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Layout qualifiers can be used for uniform and shader storage blocks, but not |
| for non-block uniform declarations. |
| The layout qualifier identifiers (and <strong>shared</strong> keyword) for uniform and |
| shader storage blocks are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>shared</strong><br> |
| <strong>packed</strong><br> |
| <strong>std140</strong><br> |
| <strong>std430</strong><br> |
| <strong>row_major</strong><br> |
| <strong>column_major</strong><br> |
| <strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>offset</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>align</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>None of these have any semantic effect at all on the usage of the variables |
| being declared; they only describe how data is laid out in memory. |
| For example, matrix semantics are always column-based, as described in the |
| rest of this specification, no matter what layout qualifiers are being used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Uniform and shader storage block layout qualifiers can be declared for |
| global scope, on a single uniform or shader storage block, or on a single |
| block member declaration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Default layouts are established at global scope for uniform blocks as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(layout-qualifier-id-list) uniform;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>and for shader storage blocks as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(layout-qualifier-id-list) buffer;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When this is done, the previous default qualification is first inherited and |
| then overridden as per the override rules listed below for each qualifier |
| listed in the declaration. |
| The result becomes the new default qualification scoped to subsequent |
| uniform or shader storage block definitions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The initial state of compilation when generating SPIR-V is as if the |
| following were declared:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(std140, column_major) uniform; |
| layout(std430, column_major) buffer;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>However, when <strong>push_constant</strong> is declared, the default layout of the |
| buffer will be <strong>std430</strong>. There is no method to globally set this default.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The initial state of compilation when not generating SPIR-V is as if the |
| following were declared:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(shared, column_major) uniform; |
| layout(shared, column_major) buffer;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Uniform and shader storage blocks can be declared with optional layout |
| qualifiers, and so can their individual member declarations. |
| Such block layout qualification is scoped only to the content of the block. |
| As with global layout declarations, block layout qualification first |
| inherits from the current default qualification and then overrides it. |
| Similarly, individual member layout qualification is scoped just to the |
| member declaration, and inherits from and overrides the block’s |
| qualification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>shared</strong> qualifier overrides only the <strong>std140</strong>, <strong>std430</strong>, and <strong>packed</strong> |
| qualifiers; other qualifiers are inherited. |
| The compiler/linker will ensure that multiple programs and programmable |
| stages containing this definition will share the same memory layout for this |
| block, as long as all arrays are declared with explicit sizes and all |
| matrices have matching <strong>row_major</strong> and/or <strong>column_major</strong> qualifications |
| (which may come from a declaration outside the block definition). |
| This allows use of the same buffer to back the same block definition across |
| different programs. |
| It is a compile-time error to use the <strong>shared</strong> qualifier when generating |
| SPIR-V.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>packed</strong> qualifier overrides only <strong>std140</strong>, <strong>std430</strong>, and <strong>shared</strong>; |
| other qualifiers are inherited. |
| When <strong>packed</strong> is used, no shareable layout is guaranteed. |
| The compiler and linker can optimize memory use based on what variables |
| actively get used and on other criteria. |
| Offsets must be queried, as there is no other way of guaranteeing where (and |
| which) variables reside within the block.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a link-time error to access the same packed uniform or shader storage |
| block in multiple stages within a program. |
| Attempts to access the same packed uniform or shader storage block across |
| programs can result in conflicting member offsets and in undefined values |
| being read. |
| However, implementations may aid application management of packed blocks by |
| using canonical layouts for packed blocks. |
| It is a compile-time error to use the <strong>packed</strong> qualifier when generating |
| SPIR-V.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>std140</strong> and <strong>std430</strong> qualifiers override only the <strong>packed</strong>, <strong>shared</strong>, |
| <strong>std140</strong>, and <strong>std430</strong> qualifiers; other qualifiers are inherited. |
| The <strong>std430</strong> qualifier is supported only for shader storage blocks; a shader |
| using the <strong>std430</strong> qualifier on a uniform block will result in |
| a compile-time error, unless it is also declared with <strong>push_constant</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The layout is explicitly determined by this, as described in section 7.6.2.2 |
| “Standard Uniform Block Layout” of the <a href="#references">OpenGL Specification</a>. |
| Hence, as in <strong>shared</strong> above, the resulting layout is shareable across |
| programs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Layout qualifiers on member declarations cannot use the <strong>shared</strong>, <strong>packed</strong>, |
| <strong>std140</strong>, or <strong>std430</strong> qualifiers. |
| These can only be used at global scope (without an object) or on a block |
| declaration, or a compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>row_major</strong> and <strong>column_major</strong> qualifiers only affect the layout of |
| matrices, including all matrices contained in structures and arrays they are |
| applied to, to all depths of nesting. |
| These qualifiers can be applied to other types, but will have no effect.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>row_major</strong> qualifier overrides only the <strong>column_major</strong> qualifier; other |
| qualifiers are inherited. |
| Elements within a matrix row will be contiguous in memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>column_major</strong> qualifier overrides only the <strong>row_major</strong> qualifier; other |
| qualifiers are inherited. |
| Elements within a matrix column will be contiguous in memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>binding</strong> qualifier specifies the uniform buffer binding point |
| corresponding to the uniform or shader storage block, which will be used to |
| obtain the values of the member variables of the block. |
| It is a compile-time error to specify the <strong>binding</strong> qualifier for the global |
| scope or for block member declarations. |
| Any uniform or shader storage block declared without a <strong>binding</strong> qualifier |
| is initially assigned to block binding point zero. |
| After a program is linked, the binding points used for uniform |
| and shader storage blocks |
| declared with or without a <strong>binding</strong> qualifier can be updated |
| by the API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When used with OpenGL, |
| if the <strong>binding</strong> qualifier is used with a uniform block or shader storage |
| block instanced as an array, the first element of the array takes the |
| specified block binding and each subsequent element takes the next |
| consecutive binding point. |
| For an array of arrays, each element (e.g. 6 elements for a[2][3]) gets a |
| binding point, and they are ordered per the array of array ordering |
| described in “<a href="#arrays">Arrays.</a>”</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 “<a href="#arrays">Arrays.</a>”</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the binding point for any uniform or shader storage block instance is |
| less than zero, or greater than or equal to the corresponding |
| implementation-dependent maximum number of buffer bindings, a compile-time |
| error will occur. |
| When the <strong>binding</strong> qualifier is used with a uniform or shader storage block |
| instanced as an array of size <em>N</em>, all elements of the array from <strong>binding</strong> |
| through <em>binding + N - 1</em> must be within this range. |
| It is a compile-time or link-time error to use the same binding number for |
| more than one uniform block or for more than one buffer block.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>set</strong> qualifier is only available when targeting Vulkan. |
| It specifies the descriptor set this object belongs to. |
| It is a compile-time error to apply <strong>set</strong> to a standalone qualifier, to |
| a member of a block, or when not targeting an API that supports descriptor sets. |
| It is a compile-time error to apply <strong>set</strong> to a block qualified as <strong>push_constant</strong>. |
| By default, any non-push-constant uniform or shader storage block declared |
| without a <strong>set</strong> identifier is assigned to descriptor set 0. |
| Similarly, any sampler, texture, or subpass-input type declared as a uniform |
| without a <strong>set</strong> identifier is also assigned to descriptor set 0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If applied to an object declared as an array, all elements of the array |
| belong to the specified <strong>set</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When generating SPIR-V, it is a compile-time error for either the <strong>set</strong> or |
| <strong>binding</strong> value to exceed a front-end-configuration supplied maximum value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When multiple arguments are listed in a <strong>layout</strong> declaration, the effect |
| will be the same as if they were declared one at a time, in order from left |
| to right, each in turn inheriting from and overriding the result from the |
| previous qualification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(row_major, column_major)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>results in the qualification being <strong>column_major</strong>. |
| Other examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(shared, row_major) uniform; <span class="comment">// default is now shared and row_major</span> |
| |
| layout(std140) uniform Transform { <span class="comment">// layout of this block is std140</span> |
| mat4 M1; <span class="comment">// row major</span> |
| layout(column_major) mat4 M2; <span class="comment">// column major</span> |
| mat3 N1; <span class="comment">// row major</span> |
| }; |
| |
| uniform T2 { <span class="comment">// layout of this block is shared</span> |
| ... |
| }; |
| |
| layout(column_major) uniform T3 { <span class="comment">// shared and column major</span> |
| mat4 M3; <span class="comment">// column major</span> |
| layout(row_major) mat4 m4; <span class="comment">// row major</span> |
| mat3 N2; <span class="comment">// column major</span> |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan, the <strong>offset</strong> and <strong>align</strong> qualifiers for blocks and |
| block members can only be used with <strong>uniform</strong> and <strong>buffer</strong> blocks. |
| When not targeting Vulkan, they can only be used with blocks declared with |
| <strong>std140</strong> or <strong>std430</strong> layouts.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>offset</strong> qualifier can only be used on block members. |
| The <strong>offset</strong> qualifier forces the qualified member to start at or after the |
| specified <em>layout-qualifier-value</em>, which will be its byte offset from |
| the beginning of the buffer. |
| It is a compile-time error to have any offset, explicit or assigned, that |
| lies within another member of the block. |
| When not generating SPIR-V, it is a compile-time error to specify an offset |
| that is smaller than the offset of the previous member in the block. |
| Two blocks linked together in the same program with the same block name must |
| have the exact same set of members qualified with <strong>offset</strong> and their |
| <em>layout-qualifier-value</em> values must be the same, or a link-time error |
| results. |
| The specified offset must be a multiple of the base alignment of the type of |
| the block member it qualifies, or a compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>align</strong> qualifier makes the start of each block member have a minimum |
| byte alignment. |
| It does not affect the internal layout within each member, which will still |
| follow the <strong>std140</strong> or <strong>std430</strong> rules. |
| The specified alignment must be greater than 0 and a power of 2, or a |
| compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>actual alignment</em> of a member will be the greater of the specified |
| <strong>align</strong> alignment and the standard (e.g. <strong>std140</strong>) base alignment for the |
| member’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’s internal stride. |
| Both an <strong>offset</strong> and an <strong>align</strong> qualifier can be specified on a declaration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>align</strong> qualifier, when used on a block, has the same effect as |
| qualifying each member with the same <strong>align</strong> value as declared on the block, |
| and gets the same compile-time results and errors as if this had been done. |
| As described in general earlier, an individual member can specify its own |
| <strong>align</strong>, which overrides the block-level <strong>align</strong>, but just for that member.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Examples:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(std140) uniform block { |
| vec4 a; <span class="comment">// a takes offsets 0-15</span> |
| layout(offset = <span class="integer">32</span>) vec3 b; <span class="comment">// b takes offsets 32-43</span> |
| layout(offset = <span class="integer">40</span>) vec2 c; <span class="comment">// ERROR, lies within previous member</span> |
| layout(offset = <span class="integer">48</span>) vec2 d; <span class="comment">// d takes offsets 48-55</span> |
| layout(align = <span class="integer">16</span>) <span class="predefined-type">float</span> e; <span class="comment">// e takes offsets 64-67</span> |
| layout(align = <span class="integer">2</span>) <span class="predefined-type">double</span> f; <span class="comment">// f takes offsets 72-79</span> |
| layout(align = <span class="integer">6</span>) <span class="predefined-type">double</span> g; <span class="comment">// ERROR, 6 is not a power of 2</span> |
| layout(offset = <span class="integer">80</span>) <span class="predefined-type">float</span> h; <span class="comment">// h takes offsets 80-83</span> |
| layout(align = <span class="integer">64</span>) dvec3 i; <span class="comment">// i takes offsets 128-151</span> |
| layout(offset = <span class="integer">164</span>, align = <span class="integer">8</span>) |
| <span class="predefined-type">float</span> j; <span class="comment">// j takes offsets 168-171</span> |
| };</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="opaque-uniform-layout-qualifiers">4.4.6. Opaque Uniform Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Opaque uniform variables can take the uniform layout qualifier for binding:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>binding</strong> qualifier specifies the point where the variable will be bound. |
| Any opaque variable declared without a binding qualifier has a default binding |
| of zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When used with OpenGL, |
| if the <strong>binding</strong> qualifier is used with an array, the first element of the |
| array takes the specified binding point and each subsequent element takes the |
| next consecutive binding point. |
| For an array of arrays, each element (e.g. 6 elements for a[2][3]) gets a |
| binding point, and they are ordered per the array of array ordering |
| described in “<a href="#arrays">Arrays.</a>”</p> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan, |
| if the <strong>binding</strong> qualifier is used with an array, the entire array |
| takes only the provided binding number. The next consecutive binding |
| number is available for a different object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the <strong>binding</strong> is less than zero, or greater than or equal to the |
| implementation-dependent maximum supported number of binding points, |
| a compile-time error will occur. |
| When the <strong>binding</strong> qualifier is used with an array of size <em>N</em>, all elements |
| of the array from <strong>binding</strong> through <em>binding + N - 1</em> must be within this |
| range. |
| It is a compile-time or link-time error to use the same <strong>binding</strong> number for |
| more than one atomic counter, unless the <em>offset</em> for the atomic counters |
| sharing the same binding are all different.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A link-time error will result if two shaders in a program specify different |
| <em>layout-qualifier-value</em> bindings for the same opaque-uniform name. |
| However, it is not an error to specify a binding on some but not all |
| declarations for the same name, as shown in the examples below.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// in one shader...</span> |
| layout(binding=<span class="integer">3</span>) uniform sampler2D s; <span class="comment">// s bound to point 3</span> |
| |
| <span class="comment">// in another shader...</span> |
| uniform sampler2D s; <span class="comment">// okay, s still bound at 3</span> |
| |
| <span class="comment">// in another shader...</span> |
| layout(binding=<span class="integer">4</span>) uniform sampler2D s; <span class="comment">// ERROR: contradictory bindings</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="atomic-counter-layout-qualifiers">4.4.7. Atomic Counter Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Atomic counters are not available when targeting Vulkan.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic counter layout qualifiers can be used on atomic counter declarations. |
| The atomic counter qualifiers are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em><br> |
| <strong>offset</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>, offset = <span class="integer">4</span>) uniform atomic_uint a;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the opaque handle to the atomic counter <em>a</em> will be |
| bound to atomic counter buffer binding point 2 at an offset of 4 basic |
| machine units into that buffer. |
| The default <em>offset</em> for binding point 2 will be post incremented by 4 (the |
| size of an atomic counter).</p> |
| </div> |
| <div class="paragraph"> |
| <p>A subsequent atomic counter declaration will inherit the previous (post |
| incremented) offset. |
| For example, a subsequent declaration of</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>) uniform atomic_uint bar;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will establish that the atomic counter <em>bar</em> has a binding to buffer binding |
| point 2 at an offset of 8 basic machine units into that buffer. |
| The offset for binding point 2 will again be post-incremented by 4 (the size |
| of an atomic counter).</p> |
| </div> |
| <div class="paragraph"> |
| <p>When multiple variables are listed in a layout declaration, the effect will |
| be the same as if they were declared one at a time, in order from left to |
| right.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Binding points are not inherited, only offsets. |
| Each binding point tracks its own current default <em>offset</em> for inheritance |
| of subsequent variables using the same <strong>binding</strong>. |
| The initial state of compilation is that all <strong>binding</strong> points have an |
| <em>offset</em> of 0. |
| The <em>offset</em> can be set per binding point at global scope (without declaring |
| a variable). |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>, offset = <span class="integer">4</span>) uniform atomic_uint;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Establishes that the next <strong>atomic_uint</strong> declaration for binding point 2 will |
| inherit <em>offset</em> 4 (but does not establish a default <strong>binding</strong>):</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(binding = <span class="integer">2</span>) uniform atomic_uint bar; <span class="comment">// offset is 4</span> |
| layout(offset = <span class="integer">8</span>) uniform atomic_uint bar; <span class="comment">// error, no default binding</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Atomic counters may share the same binding point, but if a binding is |
| shared, their offsets must be either explicitly or implicitly (from |
| inheritance) unique and non overlapping.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Example valid uniform declarations, assuming top of shader:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(binding=<span class="integer">3</span>, offset=<span class="integer">4</span>) uniform atomic_uint a; <span class="comment">// offset = 4</span> |
| layout(binding=<span class="integer">2</span>) uniform atomic_uint b; <span class="comment">// offset = 0</span> |
| layout(binding=<span class="integer">3</span>) uniform atomic_uint c; <span class="comment">// offset = 8</span> |
| layout(binding=<span class="integer">2</span>) uniform atomic_uint d; <span class="comment">// offset = 4</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Example of an invalid uniform declaration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(offset=<span class="integer">4</span>) ... <span class="comment">// error, must include binding</span> |
| layout(binding=<span class="integer">1</span>, offset=<span class="integer">0</span>) ... a; <span class="comment">// okay</span> |
| layout(binding=<span class="integer">2</span>, offset=<span class="integer">0</span>) ... b; <span class="comment">// okay</span> |
| layout(binding=<span class="integer">1</span>, offset=<span class="integer">0</span>) ... c; <span class="comment">// error, offsets must not be shared</span> |
| <span class="comment">// between a and c</span> |
| layout(binding=<span class="integer">1</span>, offset=<span class="integer">2</span>) ... d; <span class="comment">// error, overlaps offset 0 of a</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to bind an atomic counter with a binding value |
| greater than or equal to <em>gl_MaxAtomicCounterBindings</em>. |
| It is a compile-time error to declare an unsized array of <strong>atomic_uint</strong>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="format-layout-qualifiers">4.4.8. Format Layout Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Format layout qualifiers can be used on image variable declarations (those |
| declared with a basic type having “<strong>image</strong>” in its keyword). |
| The format layout qualifier identifiers for image variable declarations are:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>layout-qualifier-id</em> : </dt> |
| <dd> |
| <p><em>float-image-format-qualifier</em><br> |
| <em>int-image-format-qualifier</em><br> |
| <em>uint-image-format-qualifier</em><br> |
| <strong>binding</strong> <strong>=</strong> <em>layout-qualifier-value</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>float-image-format-qualifier</em> : </dt> |
| <dd> |
| <p><strong>rgba32f</strong><br> |
| <strong>rgba16f</strong><br> |
| <strong>rg32f</strong><br> |
| <strong>rg16f</strong><br> |
| <strong>r11f_g11f_b10f</strong><br> |
| <strong>r32f</strong><br> |
| <strong>r16f</strong><br> |
| <strong>rgba16</strong><br> |
| <strong>rgb10_a2</strong><br> |
| <strong>rgba8</strong><br> |
| <strong>rg16</strong><br> |
| <strong>rg8</strong><br> |
| <strong>r16</strong><br> |
| <strong>r8</strong><br> |
| <strong>rgba16_snorm</strong><br> |
| <strong>rgba8_snorm</strong><br> |
| <strong>rg16_snorm</strong><br> |
| <strong>rg8_snorm</strong><br> |
| <strong>r16_snorm</strong><br> |
| <strong>r8_snorm</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>int-image-format-qualifier</em> : </dt> |
| <dd> |
| <p><strong>rgba32i</strong><br> |
| <strong>rgba16i</strong><br> |
| <strong>rgba8i</strong><br> |
| <strong>rg32i</strong><br> |
| <strong>rg16i</strong><br> |
| <strong>rg8i</strong><br> |
| <strong>r32i</strong><br> |
| <strong>r16i</strong><br> |
| <strong>r8i</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>uint-image-format-qualifier</em> : </dt> |
| <dd> |
| <p><strong>rgba32ui</strong><br> |
| <strong>rgba16ui</strong><br> |
| <strong>rgb10_a2ui</strong><br> |
| <strong>rgba8ui</strong><br> |
| <strong>rg32ui</strong><br> |
| <strong>rg16ui</strong><br> |
| <strong>rg8ui</strong><br> |
| <strong>r32ui</strong><br> |
| <strong>r16ui</strong><br> |
| <strong>r8ui</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A format layout qualifier specifies the image format associated with a |
| declared image variable. |
| Only one format qualifier may be specified for any image variable |
| declaration. |
| For image variables with floating-point component types (keywords starting |
| with “<strong>image</strong>”), signed integer component types (keywords starting with |
| “<strong>iimage</strong>”), or unsigned integer component types (keywords starting with |
| “<strong>uimage</strong>”), the format qualifier used must match the |
| <em>float-image-format-qualifier</em>, <em>int-image-format-qualifier</em>, or |
| <em>uint-image-format-qualifier</em> grammar rules, respectively. |
| It is a compile-time error to declare an image variable where the format |
| qualifier does not match the image variable type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Any image variable used for image loads or atomic operations must specify a |
| format layout qualifier; it is a compile-time error to pass an image uniform |
| variable or function parameter declared without a format layout qualifier to |
| an image load or atomic function.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Uniforms not qualified with <strong>writeonly</strong> must have a format layout qualifier. |
| Note that an image variable passed to a function for read access cannot be |
| declared as <strong>writeonly</strong> and hence must have been declared with a format |
| layout qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>binding</strong> qualifier was described in |
| “<a href="#opaque-uniform-layout-qualifiers">Opaque Uniform Layout Qualifiers</a>”.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_subpass_input_qualifier">4.4.9. Subpass Input Qualifier</h4> |
| <div class="paragraph"> |
| <p>Subpass inputs are only available when targeting Vulkan.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subpass inputs are declared with the basic <strong>subpassInput</strong> types. |
| They must be declared with the layout qualifier |
| <strong>input_attachment_index</strong>, or a compile-time error results. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(input_attachment_index = <span class="integer">2</span>) uniform subpassInput t;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This selects which subpass input is being read from. The value assigned |
| to <strong>input_attachment_index</strong>, say <em>i</em> (<code>input_attachment_index = i</code>), selects |
| that entry (<em>i</em> th entry) in the input list for the pass. See the API |
| documentation for more detail about passes and the input list.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If an array of size <em>N</em> is declared, it consumes <em>N</em> consecutive |
| <strong>input_attachment_index</strong> values, starting with the one provided.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time or link-time error to have different variables |
| declared with the same <strong>input_attachment_index</strong>. |
| This includes any overlap in the implicit <strong>input_attachment_index</strong> consumed by |
| array declarations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error if the value assigned to an <strong>input_attachment_index</strong> |
| is greater than or equal to <em>gl_MaxInputAttachments</em>.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="interpolation-qualifiers">4.5. Interpolation Qualifiers</h3> |
| <div class="paragraph"> |
| <p>Inputs and outputs that could be interpolated can be further qualified by at |
| most one of the following interpolation qualifiers:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>smooth</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">perspective correct interpolation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>flat</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no interpolation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>noperspective</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">linear interpolation</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The presence of and type of interpolation is controlled by the above |
| interpolation qualifiers as well as the auxiliary storage qualifiers |
| <strong>centroid</strong> and <strong>sample</strong>. |
| When no interpolation qualifier is present, smooth interpolation is used. |
| It is a compile-time error to use more than one interpolation qualifier. |
| The auxiliary storage qualifier <strong>patch</strong> is not used for interpolation; it is |
| a compile-time error to use interpolation qualifiers with <strong>patch</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A variable qualified as <strong>flat</strong> will not be interpolated. |
| Instead, it will have the same value for every fragment within a primitive. |
| This value will come from a single provoking vertex, as described by the |
| <a href="#references">API</a>. |
| A variable qualified as <strong>flat</strong> may also be qualified as <strong>centroid</strong> or |
| <strong>sample</strong>, which will mean the same thing as qualifying it only as <strong>flat</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A variable qualified as <strong>smooth</strong> will be interpolated in a |
| perspective-correct manner over the primitive being rendered. |
| Interpolation in a perspective correct manner is specified in equation 14.7 |
| of the <a href="#references">OpenGL Specification</a>, section 14.5 “Line Segments”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A variable qualified as <strong>noperspective</strong> must be interpolated linearly in |
| screen space, as described in equation 3.7 of the <a href="#references">OpenGL Specification</a>, |
| section 3.5 “Line Segments”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When multisample rasterization is disabled, or for fragment shader input |
| variables qualified with neither <strong>centroid</strong> nor <strong>sample</strong>, the value of the |
| assigned variable may be interpolated anywhere within the pixel and a single |
| value may be assigned to each sample within the pixel, to the extent |
| permitted by the <a href="#references">OpenGL Specification</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When multisample rasterization is enabled, <strong>centroid</strong> and <strong>sample</strong> may be |
| used to control the location and frequency of the sampling of the qualified |
| fragment shader input. |
| If a fragment shader input is qualified with <strong>centroid</strong>, a single value may |
| be assigned to that variable for all samples in the pixel, but that value |
| must be interpolated at a location that lies in both the pixel and in the |
| primitive being rendered, including any of the pixel’s samples covered by |
| the primitive. |
| Because the location at which the variable is interpolated may be different |
| in neighboring pixels, and derivatives may be computed by computing |
| differences between neighboring pixels, derivatives of centroid-sampled |
| inputs may be less accurate than those for non-centroid interpolated |
| variables. |
| If a fragment shader input is qualified with <strong>sample</strong>, a separate value must |
| be assigned to that variable for each covered sample in the pixel, and that |
| value must be sampled at the location of the individual sample.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a link-time error if, within the same stage, the interpolation |
| qualifiers of variables of the same name do not match.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="redeclaring-built-in-interpolation-variables-in-the-compatibility-profile">4.5.1. Redeclaring Built-In Interpolation Variables in the Compatibility Profile</h4> |
| <div class="paragraph"> |
| <p>The following predeclared variables can be redeclared with an interpolation |
| qualifier when using the compatibility profile:</p> |
| </div> |
| <div class="paragraph"> |
| <p>Vertex, tessellation control, tessellation evaluation, and geometry |
| languages:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_FrontColor |
| gl_BackColor |
| gl_FrontSecondaryColor |
| gl_BackSecondaryColor</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment language:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_Color |
| gl_SecondaryColor</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_Color; <span class="comment">// predeclared by the fragment language</span> |
| flat in vec4 gl_Color; <span class="comment">// redeclared by user to be flat</span> |
| flat in vec4 gl_FrontColor; <span class="comment">// input to geometry shader, no "gl_in[]"</span> |
| flat out vec4 gl_FrontColor; <span class="comment">// output from geometry shader</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Ideally, these are redeclared as part of the redeclaration of an interface |
| block, as described in |
| “<a href="#compatibility-profile-built-in-language-variables">Compatibility Profile |
| Built-In Language Variables</a>”. |
| However, for the above purpose, they can be redeclared as individual |
| variables at global scope, outside an interface block. |
| Such redeclarations also allow adding the transform-feedback qualifiers |
| <strong>xfb_buffer</strong>, <strong>xfb_stride</strong>, and <strong>xfb_offset</strong> to output variables. |
| (Using <strong>xfb_buffer</strong> on a variable does not change the global default |
| buffer.) A compile-time error will result if a shader has both an interface |
| block redeclaration and a separate redeclaration of a member of that |
| interface block outside the interface block redeclaration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If <em>gl_Color</em> is redeclared with an interpolation qualifier, then |
| <em>gl_FrontColor</em> and <em>gl_BackColor</em> (if they are written to) must also be |
| redeclared with the same interpolation qualifier, and vice versa. |
| If <em>gl_SecondaryColor</em> is redeclared with an interpolation qualifier, then |
| <em>gl_FrontSecondaryColor</em> and _gl_BackSecondaryColor _(if they are written |
| to) must also be redeclared with the same interpolation qualifier, and vice |
| versa. |
| This qualifier matching on predeclared variables is only required for |
| variables that are statically used within the shaders in a program.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="parameter-qualifiers">4.6. Parameter Qualifiers</h3> |
| <div class="paragraph"> |
| <p>In addition to precision qualifiers and memory qualifiers, parameters can |
| have these parameter qualifiers.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><none: default></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">same as <strong>in</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>const</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters that cannot be written to</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>in</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed into a function</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>out</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed back out of a function, |
| but not initialized for use when passed in</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>inout</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">for function parameters passed both into and out of a |
| function</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Parameter qualifiers are discussed in more detail in |
| “<a href="#function-calling-conventions">Function Calling Conventions</a>”.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="precision-and-precision-qualifiers">4.7. Precision and Precision Qualifiers</h3> |
| <div class="paragraph"> |
| <p>When not targeting Vulkan: |
| Precision qualifiers are added for code portability with OpenGL ES, not for |
| functionality. |
| They have the same syntax as in OpenGL ES, as described below, but they have |
| no semantic meaning, which includes no effect on the precision used to store |
| or operate on variables. |
| If an extension adds in the same semantics and functionality in the OpenGL |
| ES 2.0 specification for precision qualifiers, then the extension is allowed |
| to reuse the keywords below for that purpose.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When targeting Vulkan: |
| For interface matching, uniform variables and uniform and buffer block |
| members must have the same precision qualification. |
| Global variables declared in different compilation units linked into the |
| same shader stage must be declared with the same precision qualification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the purposes of determining if an output from one shader stage matches |
| an input of the next stage, the precision qualifier need not match.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="range-and-precision">4.7.1. Range and Precision</h4> |
| <div class="paragraph"> |
| <p>The precision of <strong>highp</strong> |
| single- and double-precision |
| floating-point variables is defined by the IEEE 754 standard for |
| 32-bit |
| and 64-bit |
| floating-point numbers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This includes support for NaNs (Not a Number) and Infs (positive or negative |
| infinities) and positive and negative zeros.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following rules apply to <strong>highp</strong> |
| for both single and double-precision |
| operations: |
| Signed infinities and zeros are generated as dictated by IEEE, but subject |
| to the precisions allowed in the following table. |
| Any subnormal (denormalized) value input into a shader or potentially |
| generated by any operation in a shader can be flushed to 0. |
| The rounding mode cannot be set and is undefined but must not affect the |
| result by more than 1 ULP. |
| NaNs are not required to be generated. |
| Support for signaling NaNs is not required and exceptions are never raised. |
| Operations including built-in functions that operate on a NaN are not |
| required to return a NaN as the result. |
| However if NaNs are generated, <strong>isnan</strong>() must return the correct value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Precisions are expressed in terms of maximum relative error in units of ULP |
| (units in the last place), unless otherwise noted.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For single precision operations, precisions are required as follows:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Operation</th> |
| <th class="tableblock halign-left valign-top">Precision</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><em>a</em> + <em>b</em>, <em>a</em> - <em>b</em>, <em>a</em> * <em>b</em></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><, <=, ==, >, >=</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 < 2<sup>-21</sup> inside the range |
| <span class="eq">[0.5,2.0]</span>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>sqrt</strong>()</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Inherited from 1.0 / <strong>inversesqrt</strong>().</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>inversesqrt</strong>()</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2 ULP.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">implicit and explicit |
| conversions between types</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Correctly rounded.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Built-in functions defined in the specification with an equation built from |
| the above operations inherit the above errors. |
| These include, for example, the geometric functions, the common functions, |
| and many of the matrix functions. |
| Built-in functions not listed above and not defined as equations of the |
| above have undefined precision. |
| These include, for example, the trigonometric functions and determinant.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The precision of double-precision operations is at least that of single |
| precision.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="precision-qualifiers">4.7.2. Precision Qualifiers</h4> |
| <div class="paragraph"> |
| <p>Any |
| single-precision |
| floating-point, integer, or opaque-type declaration can have the type |
| preceded by one of these precision qualifiers:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>highp</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">32-bit two’s complement for integers, |
| 32-bit IEEE 754 floating-point for <strong>float</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>mediump</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">SPIR-V <strong>RelaxedPrecision</strong> when targeting Vulkan, otherwise none.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>lowp</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">SPIR-V <strong>RelaxedPrecision</strong> when targeting Vulkan, otherwise none.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">lowp <span class="predefined-type">float</span> color; |
| out mediump vec2 P; |
| lowp ivec2 foo(lowp mat3); |
| highp mat4 m;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Literal constants do not have precision qualifiers. |
| Neither do Boolean variables. |
| Neither do constructors.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For this paragraph, “operation” includes operators, built-in functions, |
| and constructors, and “operand” 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 “<a href="#function-calling-conventions">Function Calling |
| Conventions</a>”, function input and output is done through copies, and |
| therefore qualifiers do not have to match.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The precision of a variable is determined when the variable is declared and |
| cannot be subsequently changed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Where the precision of a constant integral or constant floating-point |
| expression is not specified, evaluation is performed at <strong>highp</strong>. |
| This rule does not affect the precision qualification of the expression.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The evaluation of constant expressions must be invariant and will usually be |
| performed at compile time.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="default-precision-qualifiers">4.7.3. Default Precision Qualifiers</h4> |
| <div class="paragraph"> |
| <p>The precision statement</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">precision precision-qualifier type;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>can be used to establish a default precision qualifier. |
| The <em>type</em> field can be either <strong>int</strong>, <strong>float</strong>, or any of the opaque types, |
| and the <em>precision-qualifier</em> can be <strong>lowp</strong>, <strong>mediump</strong>, or <strong>highp</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Any other types or qualifiers will result in a compile-time error. |
| If <em>type</em> is <strong>float</strong>, the directive applies to non-precision-qualified |
| single-precision |
| floating-point type (scalar, vector, and matrix) declarations. |
| If <em>type</em> is <strong>int</strong>, the directive applies to all non-precision-qualified |
| integer type (scalar, vector, signed, and unsigned) declarations. |
| This includes global variable declarations, function return declarations, |
| function parameter declarations, and local variable declarations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Non-precision qualified declarations will use the precision qualifier |
| specified in the most recent <strong>precision</strong> statement that is still in scope. |
| The <strong>precision</strong> statement has the same scoping rules as variable |
| declarations. |
| If it is declared inside a compound statement, its effect stops at the end |
| of the inner-most statement it was declared in. |
| Precision statements in nested scopes override precision statements in outer |
| scopes. |
| Multiple precision statements for the same basic type can appear inside the |
| same scope, with later statements overriding earlier statements within that |
| scope.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For any type that accepts a precision qualifier, |
| the default precision qualification will be <strong>highp</strong>. |
| Because all types requiring a precision qualifier have a default precision, |
| there are no errors for omission of a precision qualifier.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="available-precision-qualifiers">4.7.4. Available Precision Qualifiers</h4> |
| <div class="paragraph"> |
| <p>The built-in macro GL_FRAGMENT_PRECISION_HIGH is defined to one:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#define</span> GL_FRAGMENT_PRECISION_HIGH <span class="integer">1</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This macro is available in all languages except compute.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="variance-and-the-invariant-qualifier">4.8. Variance and the Invariant Qualifier</h3> |
| <div class="paragraph"> |
| <p>In this section, <em>variance</em> refers to the possibility of getting different |
| values from the same expression in different programs. |
| For example, consider the situation where two vertex shaders, in different |
| programs, each set <em>gl_Position</em> with the same expression, and the input |
| values into that expression are the same when both shaders run. |
| It is possible, due to independent compilation of the two shaders, that the |
| values assigned to <em>gl_Position</em> are not exactly the same when the two |
| shaders run. |
| In this example, this can cause problems with alignment of geometry in a |
| multi-pass algorithm.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, such variance between shaders is allowed. |
| When such variance does not exist for a particular output variable, that |
| variable is said to be <em>invariant</em>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="the-invariant-qualifier">4.8.1. The Invariant Qualifier</h4> |
| <div class="paragraph"> |
| <p>To ensure that a particular output variable is invariant, it is necessary to |
| use the <strong>invariant</strong> qualifier. |
| It can either be used to qualify a previously declared variable as being |
| invariant:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">invariant gl_Position; <span class="comment">// make existing gl_Position be invariant</span> |
| out vec3 Color; |
| invariant Color; <span class="comment">// make existing Color be invariant</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>or as part of a declaration when a variable is declared:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">invariant centroid out vec3 Color;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Only variables output from a shader can be candidates for invariance. |
| This includes user-defined output variables and the built-in output |
| variables. |
| As only outputs can be declared as invariant, an output from one shader |
| stage will still match an input of a subsequent stage without the input |
| being declared as invariant.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Input or output instance names on blocks are not used when redeclaring |
| built-in variables.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>invariant</strong> keyword can be followed by a comma separated list of |
| previously declared identifiers. |
| All uses of <strong>invariant</strong> must be at global scope or on block |
| members, and before any use of the variables being declared as invariant.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To guarantee invariance of a particular output variable across two programs, |
| the following must also be true:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The output variable is declared as invariant in both programs.</p> |
| </li> |
| <li> |
| <p>The same values must be input to all shader input variables consumed by |
| expressions and control flow contributing to the value assigned to the |
| output variable.</p> |
| </li> |
| <li> |
| <p>The texture formats, texel values, and texture filtering are set the |
| same way for any texture function calls contributing to the value of the |
| output variable.</p> |
| </li> |
| <li> |
| <p>All input values are all operated on in the same way. |
| All operations in the consuming expressions and any intermediate |
| expressions must be the same, with the same order of operands and same |
| associativity, to give the same order of evaluation. |
| Intermediate variables and functions must be declared as the same type |
| with the same explicit or implicit precision |
| qualifiers. |
| Any control flow affecting the output value must be the same, and any |
| expressions consumed to determine this control flow must also follow |
| these invariance rules.</p> |
| </li> |
| <li> |
| <p>All the data flow and control flow leading to setting the invariant |
| output variable reside in a single compilation unit.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Essentially, all the data flow and control flow leading to an invariant |
| output must match.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Initially, by default, all output variables are allowed to be variant. |
| To force all output variables to be invariant, use the pragma</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="preprocessor">#pragma</span> STDGL invariant(all)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>before all declarations in a shader. |
| If this pragma is used after the declaration of any variables or functions, |
| then the set of outputs that behave as invariant is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Generally, invariance is ensured at the cost of flexibility in optimization, |
| so performance can be degraded by use of invariance. |
| Hence, use of this pragma is intended as a debug aid, to avoid individually |
| declaring all output variables as invariant.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="invariance-of-constant-expressions">4.8.2. Invariance of Constant Expressions</h4> |
| <div class="paragraph"> |
| <p>Invariance must be guaranteed for constant expressions. |
| A particular constant expression must evaluate to the same result if it |
| appears again in the same shader or a different shader. |
| This includes the same expression appearing in two shaders of the same |
| language or shaders of two different languages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Constant expressions must evaluate to the same result when operated on as |
| already described above for invariant variables.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="the-precise-qualifier">4.9. The Precise Qualifier</h3> |
| <div class="paragraph"> |
| <p>Some algorithms require floating-point computations to exactly follow the |
| order of operations specified in the source code and to treat all operations |
| consistently, even if the implementation supports optimizations that could |
| produce nearly equivalent results with higher performance. |
| For example, many GL implementations support a “multiply-add” instruction |
| that can compute a floating-point expression such as</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">result = (a * b) + (c * d);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>in two operations instead of three operations; one multiply and one |
| multiply-add instead of two multiplies and one add. |
| The result of a floating-point multiply-add might not always be identical to |
| first doing a multiply yielding a floating-point result and then doing a |
| floating-point add. |
| Hence, in this example, the two multiply operations would not be treated |
| consistently; the two multiplies could effectively appear to have differing |
| precisions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The key computation that needs to be made consistent appears when |
| tessellating, where intermediate points for subdivision are synthesized in |
| different directions, yet need to yield the same result, as shown in the |
| diagram below.</p> |
| </div> |
| <div id="img-precise" class="imageblock"> |
| <div class="content"> |
| <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KCjxzdmcgdmVyc2lvbj0iMS4yIiBiYXNlUHJvZmlsZT0idGlueSIgd2lkdGg9IjIxMG1tIiBoZWlnaHQ9IjI5N21tIiB2aWV3Qm94PSIwIDAgMjEwMDAgMjk3MDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcGF0aD0idXJsKCNwcmVzZW50YXRpb25fY2xpcF9wYXRoKSIgc3Ryb2tlLXdpZHRoPSIyOC4yMjIiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6b29vPSJodHRwOi8veG1sLm9wZW5vZmZpY2Uub3JnL3N2Zy9leHBvcnQiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KIDxkZWZzIGNsYXNzPSJDbGlwUGF0aEdyb3VwIj4KICA8Y2xpcFBhdGggaWQ9InByZXNlbnRhdGlvbl9jbGlwX3BhdGgiIGNsaXBQYXRoVW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KICAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIxMDAwIiBoZWlnaHQ9IjI5NzAwIi8+CiAgPC9jbGlwUGF0aD4KIDwvZGVmcz4KIDxkZWZzPgogIDxmb250IGlkPSJFbWJlZGRlZEZvbnRfMSIgaG9yaXotYWR2LXg9IjIwNDgiPgogICA8Zm9udC1mYWNlIGZvbnQtZmFtaWx5PSJMaWJlcmF0aW9uIFNhbnMgZW1iZWRkZWQiIHVuaXRzLXBlci1lbT0iMjA0OCIgZm9udC13ZWlnaHQ9Im5vcm1hbCIgZm9udC1zdHlsZT0ibm9ybWFsIiBhc2NlbnQ9IjE4NTIiIGRlc2NlbnQ9IjQyMyIvPgogICA8bWlzc2luZy1nbHlwaCBob3Jpei1hZHYteD0iMjA0OCIgZD0iTSAwLDAgTCAyMDQ3LDAgMjA0NywyMDQ3IDAsMjA0NyAwLDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0idyIgaG9yaXotYWR2LXg9IjE1MDkiIGQ9Ik0gMTE3NCwwIEwgOTY1LDAgNzkyLDY5OCBDIDc4Nyw3MTYgNzgxLDczOCA3NzYsNzY1IDc3MCw3OTIgNzY0LDgxOCA3NTksODQzIDc1Miw4NzIgNzQ2LDkwMyA3NDAsOTM0IDczNCw5MDQgNzI4LDg3NCA3MjEsODQ1IDcxNiw4MjAgNzEwLDc5MyA3MDQsNzY2IDY5Nyw3MzkgNjkxLDcxNSA2ODYsNjk0IEwgNTA4LDAgMzAwLDAgLTMsMTA4MiAxNzUsMTA4MiAzNTgsMzQ3IEMgMzYzLDMzMiAzNjcsMzEzIDM3MiwyOTEgMzc3LDI2OCAzODEsMjQ2IDM4NiwyMjUgMzkxLDIwMCAzOTYsMTc1IDQwMSwxNDkgNDA2LDE3NCA0MTIsMTk5IDQxOCwyMjMgNDIzLDI0NCA0MjksMjY1IDQzNCwyODYgNDM5LDMwNyA0NDQsMzI1IDQ0OCwzMzkgTCA2NDQsMTA4MiA4MzcsMTA4MiAxMDI2LDMzOSBDIDEwMzEsMzIyIDEwMzYsMzAyIDEwNDEsMjgwIDEwNDYsMjU4IDEwNTEsMjM3IDEwNTYsMjE4IDEwNjEsMTk1IDEwNjcsMTcyIDEwNzIsMTQ5IDEwNzcsMTc0IDEwODMsMTk5IDEwODgsMjIzIDEwOTMsMjQ0IDEwOTgsMjY1IDExMDMsMjg4IDExMDgsMzEwIDExMTIsMzMwIDExMTcsMzQ3IEwgMTMwOCwxMDgyIDE0ODQsMTA4MiAxMTc0LDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0idiIgaG9yaXotYWR2LXg9IjEwMzMiIGQ9Ik0gNjEzLDAgTCA0MDAsMCA3LDEwODIgMTk5LDEwODIgNDM3LDM3OCBDIDQ0MiwzNjMgNDQ3LDM0NiA0NTQsMzI1IDQ2MCwzMDQgNDY2LDI4MiA0NzMsMjU5IDQ4MCwyMzYgNDg2LDIxNSA0OTIsMTk0IDQ5NywxNzMgNTAyLDE1NSA1MDYsMTQxIDUxMCwxNTUgNTE1LDE3MyA1MjIsMTk0IDUyOCwyMTUgNTM0LDIzNiA1NDEsMjU4IDU0OCwyODAgNTU1LDMwMiA1NjIsMzIzIDU2OSwzNDQgNTc1LDM2MSA1ODAsMzc2IEwgODI2LDEwODIgMTAxNywxMDgyIDYxMywwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InUiIGhvcml6LWFkdi14PSI4NzQiIGQ9Ik0gMzE0LDEwODIgTCAzMTQsMzk2IEMgMzE0LDM0MyAzMTgsMjk5IDMyNiwyNjQgMzMzLDIyOSAzNDYsMjAwIDM2MywxNzkgMzgwLDE1NyA0MDMsMTQyIDQzMiwxMzMgNDYwLDEyNCA0OTUsMTE5IDUzNywxMTkgNTgwLDExOSA2MTgsMTI3IDY1MywxNDIgNjg3LDE1NyA3MTYsMTc4IDc0MSwyMDcgNzY1LDIzNSA3ODQsMjcwIDc5NywzMTIgODEwLDM1MyA4MTcsNDAxIDgxNyw0NTUgTCA4MTcsMTA4MiA5OTcsMTA4MiA5OTcsMjMxIEMgOTk3LDIwOCA5OTcsMTg1IDk5OCwxNjAgOTk4LDEzNSA5OTgsMTExIDk5OSw4OSAxMDAwLDY2IDEwMDAsNDcgMTAwMSwzMSAxMDAyLDE1IDEwMDIsNSAxMDAzLDAgTCA4MzMsMCBDIDgzMiwzIDgzMiwxMiA4MzEsMjcgODMwLDQyIDgzMCw1OSA4MjksNzggODI4LDk3IDgyNywxMTYgODI2LDEzNiA4MjUsMTU1IDgyNSwxNzIgODI1LDE4NSBMIDgyMiwxODUgQyA4MDUsMTU0IDc4NiwxMjUgNzY1LDEwMCA3NDQsNzUgNzIwLDUzIDY5MywzNiA2NjYsMTggNjM0LDQgNTk5LC02IDU2NCwtMTUgNTIzLC0yMCA0NzYsLTIwIDQxNiwtMjAgMzY0LC0xMyAzMjEsMiAyNzgsMTcgMjQyLDM5IDIxNCw3MCAxODYsMTAxIDE2NiwxNDAgMTUzLDE4OCAxNDAsMjM2IDEzMywyOTQgMTMzLDM2MSBMIDEzMywxMDgyIDMxNCwxMDgyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InQiIGhvcml6LWFkdi14PSI1MzEiIGQ9Ik0gNTU0LDggQyA1MjcsMSA0OTksLTUgNDcxLC0xMCA0NDIsLTE0IDQwOSwtMTYgMzcyLC0xNiAyMjgsLTE2IDE1Niw2NiAxNTYsMjI5IEwgMTU2LDk1MSAzMSw5NTEgMzEsMTA4MiAxNjMsMTA4MiAyMTYsMTMyNCAzMzYsMTMyNCAzMzYsMTA4MiA1MzYsMTA4MiA1MzYsOTUxIDMzNiw5NTEgMzM2LDI2OCBDIDMzNiwyMTYgMzQ1LDE4MCAzNjIsMTU5IDM3OSwxMzggNDA4LDEyNyA0NTAsMTI3IDQ2NywxMjcgNDg0LDEyOCA1MDEsMTMxIDUxNywxMzQgNTM1LDEzNyA1NTQsMTQxIEwgNTU0LDggWiIvPgogICA8Z2x5cGggdW5pY29kZT0icyIgaG9yaXotYWR2LXg9IjkwMSIgZD0iTSA5NTAsMjk5IEMgOTUwLDI0OCA5NDAsMjAzIDkyMSwxNjQgOTAxLDEyNCA4NzIsOTEgODM1LDY0IDc5OCwzNyA3NTIsMTYgNjk4LDIgNjQzLC0xMyA1ODEsLTIwIDUxMSwtMjAgNDQ4LC0yMCAzOTIsLTE1IDM0MiwtNiAyOTEsNCAyNDcsMjAgMjA5LDQxIDE3MSw2MiAxMzksOTEgMTE0LDEyNiA4OCwxNjEgNjksMjAzIDU3LDI1NCBMIDIxNiwyODUgQyAyMzEsMjI3IDI2MywxODUgMzExLDE1OCAzNTksMTMxIDQyNiwxMTcgNTExLDExNyA1NTAsMTE3IDU4NSwxMjAgNjE4LDEyNSA2NTAsMTMwIDY3OCwxNDAgNzAxLDE1MyA3MjQsMTY2IDc0MywxODMgNzU2LDIwNSA3NjksMjI2IDc3NSwyNTMgNzc1LDI4NSA3NzUsMzE4IDc2NywzNDUgNzUyLDM2NiA3MzcsMzg3IDcxNSw0MDQgNjg4LDQxOCA2NjEsNDMyIDYyOCw0NDQgNTg5LDQ1NSA1NTAsNDY1IDUwNyw0NzYgNDYwLDQ4OSA0MTcsNTAwIDM3NCw1MTMgMzMxLDUyNyAyODgsNTQxIDI1MCw1NjAgMjE2LDU4MyAxODEsNjA2IDE1Myw2MzQgMTMyLDY2OCAxMTEsNzAyIDEwMCw3NDUgMTAwLDc5NiAxMDAsODk1IDEzNSw5NzAgMjA2LDEwMjIgMjc2LDEwNzMgMzc4LDEwOTkgNTEzLDEwOTkgNjMyLDEwOTkgNzI3LDEwNzggNzk4LDEwMzYgODY4LDk5NCA5MTIsOTI3IDkzMSw4MzQgTCA3NjksODE0IEMgNzYzLDg0MiA3NTIsODY2IDczNiw4ODUgNzIwLDkwNCA3MDEsOTE5IDY3OCw5MzEgNjU1LDk0MiA2MzAsOTUxIDYwMiw5NTYgNTczLDk2MSA1NDQsOTYzIDUxMyw5NjMgNDMyLDk2MyAzNzIsOTUxIDMzMyw5MjYgMjk0LDkwMSAyNzUsODY0IDI3NSw4MTQgMjc1LDc4NSAyODIsNzYxIDI5Nyw3NDIgMzExLDcyMyAzMzEsNzA3IDM1Nyw2OTQgMzgyLDY4MSA0MTMsNjY5IDQ0OSw2NjAgNDg1LDY1MCA1MjUsNjQwIDU2OCw2MjkgNTk3LDYyMiA2MjYsNjE0IDY1Niw2MDYgNjg2LDU5NyA3MTUsNTg3IDc0NCw1NzYgNzcyLDU2NCA3OTksNTUwIDgyNCw1MzUgODQ5LDUxOSA4NzAsNTAwIDg4OSw0NzggOTA4LDQ1NiA5MjMsNDMwIDkzNCw0MDEgOTQ1LDM3MiA5NTAsMzM4IDk1MCwyOTkgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iciIgaG9yaXotYWR2LXg9IjUzMCIgZD0iTSAxNDIsMCBMIDE0Miw4MzAgQyAxNDIsODUzIDE0Miw4NzYgMTQyLDkwMCAxNDEsOTIzIDE0MSw5NDYgMTQwLDk2OCAxMzksOTkwIDEzOSwxMDExIDEzOCwxMDMwIDEzNywxMDQ5IDEzNywxMDY3IDEzNiwxMDgyIEwgMzA2LDEwODIgQyAzMDcsMTA2NyAzMDgsMTA0OSAzMDksMTAzMCAzMTAsMTAxMCAzMTEsOTkwIDMxMiw5NjkgMzEzLDk0OCAzMTMsOTI5IDMxNCw5MTAgMzE0LDg5MSAzMTQsODc0IDMxNCw4NjEgTCAzMTgsODYxIEMgMzMxLDkwMiAzNDQsOTM4IDM1OSw5NjkgMzczLDk5OSAzOTAsMTAyNCA0MDksMTA0NCA0MjgsMTA2MyA0NTEsMTA3OCA0NzgsMTA4OCA1MDUsMTA5NyA1MzcsMTEwMiA1NzUsMTEwMiA1OTAsMTEwMiA2MDQsMTEwMSA2MTcsMTA5OSA2MzAsMTA5NiA2NDEsMTA5NCA2NDgsMTA5MiBMIDY0OCw5MjcgQyA2MzYsOTMwIDYyMiw5MzMgNjA2LDkzNSA1OTAsOTM2IDU3Miw5MzcgNTUyLDkzNyA1MTEsOTM3IDQ3Niw5MjggNDQ3LDkwOSA0MTgsODkwIDM5NCw4NjUgMzc2LDgzMiAzNTcsNzk5IDM0NCw3NTkgMzM1LDcxNCAzMjYsNjY4IDMyMiw2MTggMzIyLDU2NCBMIDMyMiwwIDE0MiwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9InAiIGhvcml6LWFkdi14PSI5NTMiIGQ9Ik0gMTA1Myw1NDYgQyAxMDUzLDQ2NCAxMDQ2LDM4OCAxMDMzLDMxOSAxMDIwLDI1MCA5OTgsMTkwIDk2NywxNDAgOTM2LDkwIDg5NSw1MSA4NDQsMjMgNzkzLC02IDczMCwtMjAgNjU1LC0yMCA1NzgsLTIwIDUxMCwtNSA0NTIsMjQgMzk0LDUzIDM1MCwxMDEgMzE5LDE2OCBMIDMxNCwxNjggQyAzMTUsMTY3IDMxNSwxNjEgMzE2LDE1MCAzMTYsMTM5IDMxNiwxMjYgMzE3LDExMCAzMTcsOTQgMzE3LDc2IDMxOCw1NyAzMTgsMzcgMzE4LDE3IDMxOCwtMiBMIDMxOCwtNDI1IDEzOCwtNDI1IDEzOCw4NjEgQyAxMzgsODg3IDEzOCw5MTIgMTM4LDkzNiAxMzcsOTYwIDEzNyw5ODIgMTM2LDEwMDIgMTM1LDEwMjEgMTM1LDEwMzggMTM0LDEwNTIgMTMzLDEwNjYgMTMzLDEwNzYgMTMyLDEwODIgTCAzMDYsMTA4MiBDIDMwNywxMDgwIDMwOCwxMDczIDMwOSwxMDYxIDMxMCwxMDQ5IDMxMSwxMDM1IDMxMiwxMDE4IDMxMywxMDAxIDMxNCw5ODIgMzE1LDk2MyAzMTYsOTQ0IDMxNiw5MjUgMzE2LDkwOCBMIDMyMCw5MDggQyAzMzcsOTQzIDM1Niw5NzIgMzc3LDk5NyAzOTgsMTAyMSA0MjMsMTA0MSA0NTAsMTA1NyA0NzcsMTA3MiA1MDgsMTA4NCA1NDIsMTA5MSA1NzUsMTA5OCA2MTMsMTEwMSA2NTUsMTEwMSA3MzAsMTEwMSA3OTMsMTA4OCA4NDQsMTA2MSA4OTUsMTAzNCA5MzYsOTk3IDk2Nyw5NDkgOTk4LDkwMCAxMDIwLDg0MiAxMDMzLDc3NCAxMDQ2LDcwNSAxMDUzLDYyOSAxMDUzLDU0NiBaIE0gODY0LDU0MiBDIDg2NCw2MDkgODYwLDY2OCA4NTIsNzIwIDg0NCw3NzIgODMwLDgxNiA4MTEsODUyIDc5MSw4ODggNzY1LDkxNSA3MzIsOTM0IDY5OSw5NTMgNjU4LDk2MiA2MDksOTYyIDU2OSw5NjIgNTMxLDk1NiA0OTYsOTQ1IDQ2MSw5MzQgNDMwLDkxMiA0MDQsODgwIDM3Nyw4NDggMzU2LDgwNCAzNDEsNzQ4IDMyNiw2OTEgMzE4LDYxOCAzMTgsNTI4IDMxOCw0NTEgMzI0LDM4NyAzMzcsMzM0IDM1MCwyODEgMzY4LDIzOCAzOTMsMjA1IDQxNywxNzIgNDQ3LDE0OSA0ODMsMTM1IDUxOSwxMjAgNTYwLDExMyA2MDcsMTEzIDY1NywxMTMgNjk5LDEyMyA3MzIsMTQyIDc2NSwxNjEgNzkxLDE4OSA4MTEsMjI2IDgzMCwyNjMgODQ0LDMwOCA4NTIsMzYxIDg2MCw0MTQgODY0LDQ3NCA4NjQsNTQyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9Im8iIGhvcml6LWFkdi14PSI5ODAiIGQ9Ik0gMTA1Myw1NDIgQyAxMDUzLDM1MyAxMDExLDIxMiA5MjgsMTE5IDg0NSwyNiA3MjQsLTIwIDU2NSwtMjAgNDkwLC0yMCA0MjIsLTkgMzYzLDE0IDMwNCwzNyAyNTQsNzEgMjEzLDExOCAxNzIsMTY1IDE0MCwyMjMgMTE5LDI5NCA5NywzNjQgODYsNDQ3IDg2LDU0MiA4Niw5MTUgMjQ4LDExMDIgNTcxLDExMDIgNjU1LDExMDIgNzI4LDEwOTAgNzg5LDEwNjcgODUwLDEwNDQgOTAwLDEwMDkgOTM5LDk2MiA5NzgsOTE1IDEwMDYsODU3IDEwMjUsNzg3IDEwNDQsNzE3IDEwNTMsNjM1IDEwNTMsNTQyIFogTSA4NjQsNTQyIEMgODY0LDYyNiA4NTgsNjk1IDg0NSw3NTAgODMyLDgwNSA4MTMsODQ4IDc4OCw4ODEgNzYzLDkxNCA3MzIsOTM3IDY5Niw5NTAgNjYwLDk2MyA2MTksOTY5IDU3NCw5NjkgNTI4LDk2OSA0ODcsOTYyIDQ1MCw5NDkgNDEzLDkzNSAzODEsOTEyIDM1NSw4NzkgMzI5LDg0NiAzMDksODAyIDI5Niw3NDcgMjgyLDY5MiAyNzUsNjI0IDI3NSw1NDIgMjc1LDQ1OCAyODIsMzg5IDI5NywzMzQgMzEyLDI3OSAzMzIsMjM1IDM1OCwyMDIgMzgzLDE2OSA0MTQsMTQ2IDQ0OSwxMzMgNDg0LDEyMCA1MjIsMTEzIDU2MywxMTMgNjA5LDExMyA2NTEsMTIwIDY4OCwxMzMgNzI1LDE0NiA3NTcsMTY4IDc4MywyMDEgODA5LDIzNCA4MjksMjc4IDg0MywzMzMgODU3LDM4OCA4NjQsNDU4IDg2NCw1NDIgWiIvPgogICA8Z2x5cGggdW5pY29kZT0ibiIgaG9yaXotYWR2LXg9Ijg3NCIgZD0iTSA4MjUsMCBMIDgyNSw2ODYgQyA4MjUsNzM5IDgyMSw3ODMgODE0LDgxOCA4MDYsODUzIDc5Myw4ODIgNzc2LDkwNCA3NTksOTI1IDczNiw5NDEgNzA4LDk1MCA2NzksOTU5IDY0NCw5NjMgNjAyLDk2MyA1NTksOTYzIDUyMSw5NTYgNDg3LDk0MSA0NTIsOTI2IDQyMyw5MDQgMzk5LDg3NiAzNzQsODQ3IDM1NSw4MTIgMzQyLDc3MSAzMjksNzI5IDMyMiw2ODEgMzIyLDYyNyBMIDMyMiwwIDE0MiwwIDE0Miw4NTEgQyAxNDIsODc0IDE0Miw4OTggMTQyLDkyMyAxNDEsOTQ4IDE0MSw5NzEgMTQwLDk5NCAxMzksMTAxNiAxMzksMTAzNSAxMzgsMTA1MSAxMzcsMTA2NyAxMzcsMTA3NyAxMzYsMTA4MiBMIDMwNiwxMDgyIEMgMzA3LDEwNzkgMzA3LDEwNzAgMzA4LDEwNTUgMzA5LDEwNDAgMzEwLDEwMjQgMzExLDEwMDUgMzEyLDk4NiAzMTIsOTY2IDMxMyw5NDcgMzE0LDkyNyAzMTQsOTEwIDMxNCw4OTcgTCAzMTcsODk3IEMgMzM0LDkyOCAzNTMsOTU3IDM3NCw5ODIgMzk1LDEwMDcgNDE5LDEwMjkgNDQ2LDEwNDcgNDczLDEwNjQgNTA1LDEwNzggNTQwLDEwODggNTc1LDEwOTcgNjE2LDExMDIgNjYzLDExMDIgNzIzLDExMDIgNzc1LDEwOTUgODE4LDEwODAgODYxLDEwNjUgODk3LDEwNDMgOTI1LDEwMTIgOTUzLDk4MSA5NzQsOTQyIDk4Nyw4OTQgMTAwMCw4NDUgMTAwNiw3ODggMTAwNiw3MjEgTCAxMDA2LDAgODI1LDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0ibSIgaG9yaXotYWR2LXg9IjE0NTciIGQ9Ik0gNzY4LDAgTCA3NjgsNjg2IEMgNzY4LDczOSA3NjUsNzgzIDc1OCw4MTggNzUxLDg1MyA3NDAsODgyIDcyNSw5MDQgNzA5LDkyNSA2ODgsOTQxIDY2Myw5NTAgNjM4LDk1OSA2MDcsOTYzIDU3MCw5NjMgNTMyLDk2MyA0OTgsOTU2IDQ2Nyw5NDEgNDM2LDkyNiA0MTAsOTA0IDM4OSw4NzYgMzY3LDg0NyAzNTAsODEyIDMzOSw3NzEgMzI3LDcyOSAzMjEsNjgxIDMyMSw2MjcgTCAzMjEsMCAxNDIsMCAxNDIsODUxIEMgMTQyLDg3NCAxNDIsODk4IDE0Miw5MjMgMTQxLDk0OCAxNDEsOTcxIDE0MCw5OTQgMTM5LDEwMTYgMTM5LDEwMzUgMTM4LDEwNTEgMTM3LDEwNjcgMTM3LDEwNzcgMTM2LDEwODIgTCAzMDYsMTA4MiBDIDMwNywxMDc5IDMwNywxMDcwIDMwOCwxMDU1IDMwOSwxMDQwIDMxMCwxMDI0IDMxMSwxMDA1IDMxMiw5ODYgMzEyLDk2NiAzMTMsOTQ3IDMxNCw5MjcgMzE0LDkxMCAzMTQsODk3IEwgMzE3LDg5NyBDIDMzMyw5MjggMzUwLDk1NyAzNjksOTgyIDM4OCwxMDA3IDQxMCwxMDI5IDQzNSwxMDQ3IDQ2MCwxMDY0IDQ4OCwxMDc4IDUyMSwxMDg4IDU1MywxMDk3IDU5MCwxMTAyIDYzMywxMTAyIDcxNSwxMTAyIDc4MCwxMDg2IDgyOCwxMDUzIDg3NSwxMDIwIDkwOCw5NjggOTI3LDg5NyBMIDkzMCw4OTcgQyA5NDYsOTI4IDk2NCw5NTcgOTg0LDk4MiAxMDA0LDEwMDcgMTAyNywxMDI5IDEwNTQsMTA0NyAxMDgxLDEwNjQgMTExMSwxMDc4IDExNDQsMTA4OCAxMTc3LDEwOTcgMTIxNSwxMTAyIDEyNTgsMTEwMiAxMzEzLDExMDIgMTM2MCwxMDk1IDE0MDAsMTA4MCAxNDM5LDEwNjUgMTQ3MiwxMDQzIDE0OTcsMTAxMiAxNTIyLDk4MSAxNTQxLDk0MiAxNTUzLDg5NCAxNTY1LDg0NSAxNTcxLDc4OCAxNTcxLDcyMSBMIDE1NzEsMCAxMzkzLDAgMTM5Myw2ODYgQyAxMzkzLDczOSAxMzkwLDc4MyAxMzgzLDgxOCAxMzc2LDg1MyAxMzY1LDg4MiAxMzUwLDkwNCAxMzM0LDkyNSAxMzEzLDk0MSAxMjg4LDk1MCAxMjYzLDk1OSAxMjMyLDk2MyAxMTk1LDk2MyAxMTU3LDk2MyAxMTIzLDk1NiAxMDkyLDk0MiAxMDYxLDkyNyAxMDM1LDkwNiAxMDE0LDg3OCA5OTIsODUwIDk3NSw4MTUgOTY0LDc3MyA5NTIsNzMxIDk0Niw2ODIgOTQ2LDYyNyBMIDk0NiwwIDc2OCwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImwiIGhvcml6LWFkdi14PSIxODciIGQ9Ik0gMTM4LDAgTCAxMzgsMTQ4NCAzMTgsMTQ4NCAzMTgsMCAxMzgsMCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJrIiBob3Jpei1hZHYteD0iOTAxIiBkPSJNIDgxNiwwIEwgNDUwLDQ5NCAzMTgsMzg1IDMxOCwwIDEzOCwwIDEzOCwxNDg0IDMxOCwxNDg0IDMxOCw1NTcgNzkzLDEwODIgMTAwNCwxMDgyIDU2NSw2MTcgMTAyNywwIDgxNiwwIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImkiIGhvcml6LWFkdi14PSIxODciIGQ9Ik0gMTM3LDEzMTIgTCAxMzcsMTQ4NCAzMTcsMTQ4NCAzMTcsMTMxMiAxMzcsMTMxMiBaIE0gMTM3LDAgTCAxMzcsMTA4MiAzMTcsMTA4MiAzMTcsMCAxMzcsMCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJoIiBob3Jpei1hZHYteD0iODc0IiBkPSJNIDMxNyw4OTcgQyAzMzcsOTM0IDM1OSw5NjUgMzgyLDk5MSA0MDUsMTAxNiA0MzEsMTAzNyA0NTksMTA1NCA0ODcsMTA3MSA1MTgsMTA4MyA1NTEsMTA5MSA1ODQsMTA5OCA2MjIsMTEwMiA2NjMsMTEwMiA3MzIsMTEwMiA3ODksMTA5MyA4MzQsMTA3NCA4NzgsMTA1NSA5MTMsMTAyOSA5MzksOTk2IDk2NCw5NjIgOTgyLDkyMiA5OTIsODc1IDEwMDEsODI4IDEwMDYsNzc3IDEwMDYsNzIxIEwgMTAwNiwwIDgyNSwwIDgyNSw2ODYgQyA4MjUsNzMyIDgyMiw3NzIgODE3LDgwNyA4MTEsODQyIDgwMCw4NzEgNzg0LDg5NCA3NjgsOTE3IDc0NSw5MzQgNzE2LDk0NiA2ODcsOTU3IDY0OSw5NjMgNjAyLDk2MyA1NTksOTYzIDUyMSw5NTUgNDg3LDk0MCA0NTIsOTI1IDQyMyw5MDMgMzk5LDg3NSAzNzQsODQ3IDM1NSw4MTMgMzQyLDc3MyAzMjksNzMzIDMyMiw2ODggMzIyLDYzOCBMIDMyMiwwIDE0MiwwIDE0MiwxNDg0IDMyMiwxNDg0IDMyMiwxMDk4IEMgMzIyLDEwNzYgMzIyLDEwNTQgMzIxLDEwMzIgMzIwLDEwMTAgMzIwLDk5MCAzMTksOTcxIDMxOCw5NTIgMzE3LDkzNyAzMTYsOTI0IDMxNSw5MTEgMzE1LDkwMiAzMTQsODk3IEwgMzE3LDg5NyBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJnIiBob3Jpei1hZHYteD0iOTI3IiBkPSJNIDU0OCwtNDI1IEMgNDg2LC00MjUgNDMxLC00MTkgMzgzLC00MDYgMzM1LC0zOTMgMjk0LC0zNzUgMjYwLC0zNTIgMjI2LC0zMjggMTk4LC0zMDAgMTc3LC0yNjcgMTU2LC0yMzQgMTQwLC0xOTggMTMxLC0xNTggTCAzMTIsLTEzMiBDIDMyNCwtMTgyIDM1MSwtMjIwIDM5MiwtMjQ4IDQzMywtMjc0IDQ4NiwtMjg4IDU1MywtMjg4IDU5NCwtMjg4IDYzMSwtMjgyIDY2NCwtMjcxIDY5NywtMjYwIDcyNiwtMjQxIDc0OSwtMjE3IDc3MiwtMTkxIDc5MCwtMTU5IDgwMywtMTE5IDgxNiwtNzkgODIyLC0zMCA4MjIsMjcgTCA4MjIsMjAxIDgyMCwyMDEgQyA4MDcsMTc0IDc5MCwxNDggNzcxLDEyMyA3NTEsOTggNzI3LDc1IDY5OSw1NiA2NzAsMzcgNjM3LDIxIDYwMCwxMCA1NjMsLTIgNTIwLC04IDQ3MiwtOCA0MDMsLTggMzQ1LDQgMjk2LDI3IDI0Nyw1MCAyMDcsODQgMTc2LDEzMCAxNDUsMTc2IDEyMiwyMzMgMTA4LDMwMiA5MywzNzAgODYsNDQ5IDg2LDUzOSA4Niw2MjYgOTMsNzA0IDEwOCw3NzMgMTIyLDg0MiAxNDUsOTAxIDE3OCw5NTAgMjEwLDk5OCAyNTIsMTAzNSAzMDQsMTA2MSAzNTUsMTA4NiA0MTgsMTA5OSA0OTIsMTA5OSA1NjksMTA5OSA2MzUsMTA4MiA2OTIsMTA0NyA3NDgsMTAxMiA3OTEsOTYyIDgyMiw4OTcgTCA4MjQsODk3IEMgODI0LDkxNCA4MjUsOTMyIDgyNiw5NTMgODI3LDk3NCA4MjgsOTkzIDgyOSwxMDEyIDgzMCwxMDMwIDgzMSwxMDQ2IDgzMiwxMDU5IDgzMywxMDcyIDgzNSwxMDgwIDgzNiwxMDgyIEwgMTAwNywxMDgyIEMgMTAwNiwxMDc2IDEwMDYsMTA2NiAxMDA1LDEwNTIgMTAwNCwxMDM3IDEwMDQsMTAyMCAxMDAzLDEwMDAgMTAwMiw5ODAgMTAwMiw5NTggMTAwMiw5MzQgMTAwMSw5MDkgMTAwMSw4ODQgMTAwMSw4NTggTCAxMDAxLDMxIEMgMTAwMSwtMTIwIDk2NCwtMjM0IDg5MCwtMzExIDgxNSwtMzg3IDcwMSwtNDI1IDU0OCwtNDI1IFogTSA4MjIsNTQxIEMgODIyLDYxNiA4MTQsNjgxIDc5OCw3MzUgNzgxLDc4OCA3NjAsODMyIDczMyw4NjYgNzA2LDkwMCA2NzYsOTI1IDY0Miw5NDEgNjA3LDk1NyA1NzIsOTY1IDUzNiw5NjUgNDkwLDk2NSA0NTEsOTU3IDQxOCw5NDEgMzg1LDkyNSAzNTcsOTAwIDMzNiw4NjYgMzE0LDgzMSAyOTgsNzg3IDI4OCw3MzQgMjc3LDY4MCAyNzIsNjE2IDI3Miw1NDEgMjcyLDQ2MyAyNzcsMzk4IDI4OCwzNDUgMjk4LDI5MiAzMTQsMjQ5IDMzNSwyMTYgMzU2LDE4MyAzODMsMTYwIDQxNiwxNDYgNDQ5LDEzMiA0ODgsMTI1IDUzMywxMjUgNTY5LDEyNSA2MDQsMTMzIDYzOSwxNDggNjczLDE2MyA3MDQsMTg4IDczMSwyMjEgNzU4LDI1NCA3ODAsMjk3IDc5NywzNTAgODE0LDQwMyA4MjIsNDY2IDgyMiw1NDEgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iZiIgaG9yaXotYWR2LXg9IjU1NyIgZD0iTSAzNjEsOTUxIEwgMzYxLDAgMTgxLDAgMTgxLDk1MSAyOSw5NTEgMjksMTA4MiAxODEsMTA4MiAxODEsMTIwNCBDIDE4MSwxMjQzIDE4NSwxMjgwIDE5MiwxMzE0IDE5OSwxMzQ3IDIxMywxMzc3IDIzMywxNDAyIDI1MiwxNDI3IDI3OSwxNDQ2IDMxMywxNDYxIDM0NywxNDc1IDM5MSwxNDgyIDQ0NSwxNDgyIDQ2NiwxNDgyIDQ4OSwxNDgxIDUxMiwxNDc5IDUzNSwxNDc3IDU1NSwxNDc0IDU3MiwxNDcwIEwgNTcyLDEzMzMgQyA1NjEsMTMzNSA1NDgsMTMzNyA1MzMsMTMzOSA1MTgsMTM0MCA1MDQsMTM0MSA0OTIsMTM0MSA0NjUsMTM0MSA0NDQsMTMzNyA0MjcsMTMzMCA0MTAsMTMyMyAzOTYsMTMxMiAzODcsMTI5OSAzNzcsMTI4NSAzNzAsMTI2OCAzNjcsMTI0OCAzNjMsMTIyOCAzNjEsMTIwNSAzNjEsMTE3OSBMIDM2MSwxMDgyIDU3MiwxMDgyIDU3Miw5NTEgMzYxLDk1MSBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJlIiBob3Jpei1hZHYteD0iOTgwIiBkPSJNIDI3Niw1MDMgQyAyNzYsNDQ2IDI4MiwzOTQgMjk0LDM0NyAzMDUsMjk5IDMyMywyNTggMzQ4LDIyNCAzNzIsMTg5IDQwMywxNjMgNDQxLDE0NCA0NzksMTI1IDUyNSwxMTUgNTc4LDExNSA2NTYsMTE1IDcxOSwxMzEgNzY2LDE2MiA4MTMsMTkzIDg0NCwyMzMgODYxLDI4MSBMIDEwMTksMjM2IEMgMTAwOCwyMDYgOTkyLDE3NiA5NzIsMTQ2IDk1MSwxMTUgOTI0LDg4IDg5MCw2NCA4NTYsMzkgODE0LDE5IDc2Myw0IDcxMiwtMTIgNjUwLC0yMCA1NzgsLTIwIDQxOCwtMjAgMjk2LDI4IDIxMywxMjMgMTI5LDIxOCA4NywzNjAgODcsNTQ4IDg3LDY0OSAxMDAsNzM1IDEyNSw4MDYgMTUwLDg3NiAxODUsOTMzIDIyOSw5NzcgMjczLDEwMjEgMzI0LDEwNTMgMzgzLDEwNzMgNDQyLDEwOTIgNTA0LDExMDIgNTcxLDExMDIgNjYyLDExMDIgNzM4LDEwODcgNzk5LDEwNTggODYwLDEwMjkgOTA5LDk4OCA5NDYsOTM3IDk4Myw4ODUgMTAwOSw4MjQgMTAyNSw3NTQgMTA0MCw2ODQgMTA0OCw2MDggMTA0OCw1MjcgTCAxMDQ4LDUwMyAyNzYsNTAzIFogTSA4NjIsNjQxIEMgODUyLDc1NSA4MjMsODM4IDc3NSw4OTEgNzI3LDk0MyA2NTgsOTY5IDU2OCw5NjkgNTM4LDk2OSA1MDcsOTY0IDQ3NCw5NTUgNDQxLDk0NSA0MTAsOTI4IDM4Miw5MDMgMzU0LDg3OCAzMzAsODQ1IDMxMSw4MDMgMjkyLDc2MCAyODEsNzA2IDI3OCw2NDEgTCA4NjIsNjQxIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImQiIGhvcml6LWFkdi14PSI5MjciIGQ9Ik0gODIxLDE3NCBDIDc4OCwxMDUgNzQ0LDU1IDY4OSwyNSA2MzQsLTUgNTY1LC0yMCA0ODQsLTIwIDM0NywtMjAgMjQ3LDI2IDE4MywxMTggMTE4LDIxMCA4NiwzNDkgODYsNTM2IDg2LDkxMyAyMTksMTEwMiA0ODQsMTEwMiA1NjYsMTEwMiA2MzQsMTA4NyA2ODksMTA1NyA3NDQsMTAyNyA3ODgsOTc5IDgyMSw5MTQgTCA4MjMsOTE0IEMgODIzLDkyMSA4MjMsOTMxIDgyMyw5NDYgODIyLDk2MCA4MjIsOTc1IDgyMiw5OTEgODIxLDEwMDYgODIxLDEwMjEgODIxLDEwMzUgODIxLDEwNDkgODIxLDEwNTkgODIxLDEwNjUgTCA4MjEsMTQ4NCAxMDAxLDE0ODQgMTAwMSwyMjMgQyAxMDAxLDE5NyAxMDAxLDE3MiAxMDAyLDE0OCAxMDAyLDEyNCAxMDAyLDEwMiAxMDAzLDgyIDEwMDQsNjIgMTAwNCw0NSAxMDA1LDMxIDEwMDYsMTYgMTAwNiw2IDEwMDcsMCBMIDgzNSwwIEMgODM0LDcgODMzLDE2IDgzMiwyOSA4MzEsNDEgODMwLDU1IDgyOSw3MSA4MjgsODcgODI3LDEwNCA4MjYsMTIyIDgyNSwxMzkgODI1LDE1NyA4MjUsMTc0IEwgODIxLDE3NCBaIE0gMjc1LDU0MiBDIDI3NSw0NjcgMjgwLDQwMyAyODksMzUwIDI5OCwyOTcgMzEzLDI1MyAzMzQsMjE5IDM1NSwxODQgMzgxLDE1OSA0MTMsMTQzIDQ0NSwxMjcgNDg0LDExOSA1MzAsMTE5IDU3NywxMTkgNjE5LDEyNyA2NTYsMTQyIDY5MiwxNTcgNzIyLDE4MiA3NDcsMjE3IDc3MSwyNTEgNzg5LDI5NiA4MDIsMzUxIDgxNSw0MDYgODIxLDQ3NCA4MjEsNTU0IDgyMSw2MzEgODE1LDY5NiA4MDIsNzQ5IDc4OSw4MDIgNzcxLDg0NCA3NDYsODc3IDcyMSw5MTAgNjkxLDkzMyA2NTYsOTQ4IDYyMCw5NjIgNTc5LDk2OSA1MzIsOTY5IDQ4OCw5NjkgNDUwLDk2MSA0MTgsOTQ2IDM4Niw5MzEgMzU5LDkwNiAzMzgsODcyIDMxNyw4MzggMzAxLDc5NCAyOTEsNzQwIDI4MCw2ODUgMjc1LDYxOSAyNzUsNTQyIFoiLz4KICAgPGdseXBoIHVuaWNvZGU9ImMiIGhvcml6LWFkdi14PSI5MDEiIGQ9Ik0gMjc1LDU0NiBDIDI3NSw0ODQgMjgwLDQyNyAyODksMzc1IDI5OCwzMjMgMzEzLDI3OCAzMzQsMjQxIDM1NSwyMDMgMzg0LDE3NCA0MTksMTUzIDQ1NCwxMzIgNDk3LDEyMiA1NDgsMTIyIDYxMiwxMjIgNjY2LDEzOSA3MDksMTczIDc1MiwyMDYgNzc4LDI1OCA3ODgsMzI4IEwgOTcwLDMyOCBDIDk2NCwyODMgOTUxLDIzOSA5MzEsMTk3IDkxMSwxNTUgODg0LDExOCA4NTAsODYgODE1LDU0IDc3MywyOCA3MjQsOSA2NzUsLTEwIDYxOCwtMjAgNTUzLC0yMCA0NjgsLTIwIDM5NiwtNiAzMzcsMjMgMjc4LDUyIDIzMCw5MSAxOTMsMTQyIDE1NiwxOTIgMTI5LDI1MSAxMTIsMzIwIDk1LDM4OCA4Nyw0NjIgODcsNTQyIDg3LDYxNSA5Myw2NzkgMTA1LDczNSAxMTcsNzkwIDEzNCw4MzkgMTU2LDg4MSAxNzcsOTIyIDIwMyw5NTcgMjMyLDk4NiAyNjEsMTAxNCAyOTMsMTAzNyAzMjgsMTA1NCAzNjIsMTA3MSAzOTgsMTA4MyA0MzYsMTA5MSA0NzQsMTA5OCA1MTIsMTEwMiA1NTEsMTEwMiA2MTIsMTEwMiA2NjYsMTA5NCA3MTMsMTA3NyA3NjAsMTA2MCA4MDEsMTAzOCA4MzYsMTAwOSA4NzAsOTgwIDg5OCw5NDUgOTE5LDkwNiA5NDAsODY3IDk1NSw4MjQgOTY0LDc3OSBMIDc3OSw3NjUgQyA3NzAsODI1IDc0Niw4NzMgNzA4LDkwOCA2NzAsOTQzIDYxNiw5NjEgNTQ2LDk2MSA0OTUsOTYxIDQ1Miw5NTMgNDE4LDkzNiAzODMsOTE5IDM1NSw4OTMgMzM0LDg1OSAzMTMsODI0IDI5OCw3ODEgMjg5LDcyOSAyODAsNjc3IDI3NSw2MTYgMjc1LDU0NiBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSJiIiBob3Jpei1hZHYteD0iOTUzIiBkPSJNIDEwNTMsNTQ2IEMgMTA1MywxNjkgOTIwLC0yMCA2NTUsLTIwIDU3MywtMjAgNTA1LC01IDQ1MSwyNSAzOTYsNTQgMzUyLDEwMiAzMTgsMTY4IEwgMzE2LDE2OCBDIDMxNiwxNTEgMzE2LDEzMyAzMTUsMTE0IDMxNCw5NSAzMTMsNzggMzEyLDYyIDMxMSw0NiAzMTAsMzIgMzA5LDIxIDMwOCwxMCAzMDcsMyAzMDYsMCBMIDEzMiwwIEMgMTMzLDYgMTMzLDE2IDEzNCwzMSAxMzUsNDUgMTM1LDYyIDEzNiw4MiAxMzcsMTAyIDEzNywxMjQgMTM4LDE0OCAxMzgsMTcyIDEzOCwxOTcgMTM4LDIyMyBMIDEzOCwxNDg0IDMxOCwxNDg0IDMxOCwxMDYxIEMgMzE4LDEwNDEgMzE4LDEwMjIgMzE4LDEwMDQgMzE3LDk4NSAzMTcsOTY5IDMxNiw5NTUgMzE1LDkzOCAzMTUsOTIzIDMxNCw5MDggTCAzMTgsOTA4IEMgMzUxLDk3NyAzOTYsMTAyNyA0NTEsMTA1NyA1MDYsMTA4NyA1NzQsMTEwMiA2NTUsMTEwMiA3OTIsMTEwMiA4OTIsMTA1NiA5NTcsOTY0IDEwMjEsODcyIDEwNTMsNzMzIDEwNTMsNTQ2IFogTSA4NjQsNTQwIEMgODY0LDYxNSA4NTksNjc5IDg1MCw3MzIgODQxLDc4NSA4MjYsODI5IDgwNSw4NjQgNzg0LDg5OCA3NTgsOTIzIDcyNiw5MzkgNjk0LDk1NSA2NTUsOTYzIDYwOSw5NjMgNTYyLDk2MyA1MjAsOTU1IDQ4NCw5NDAgNDQ3LDkyNSA0MTcsOTAwIDM5Myw4NjYgMzY4LDgzMiAzNTAsNzg3IDMzNyw3MzIgMzI0LDY3NyAzMTgsNjA5IDMxOCw1MjkgMzE4LDQ1MiAzMjQsMzg3IDMzNywzMzQgMzUwLDI4MSAzNjgsMjM5IDM5MywyMDYgNDE3LDE3MyA0NDcsMTQ5IDQ4MywxMzUgNTE5LDEyMCA1NjAsMTEzIDYwNywxMTMgNjUxLDExMyA2ODksMTIxIDcyMSwxMzYgNzUzLDE1MSA3ODAsMTc2IDgwMSwyMTAgODIyLDI0NCA4MzgsMjg4IDg0OSwzNDMgODU5LDM5NyA4NjQsNDYzIDg2NCw1NDAgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iYSIgaG9yaXotYWR2LXg9IjEwNjAiIGQ9Ik0gNDE0LC0yMCBDIDMwNSwtMjAgMjI0LDkgMTY5LDY2IDExNCwxMjQgODcsMjAzIDg3LDMwMyA4NywzNzUgMTAxLDQzNCAxMjgsNDgwIDE1NSw1MjYgMTkwLDU2MiAyMzQsNTg4IDI3Nyw2MTQgMzI3LDYzMiAzODMsNjQyIDQzOSw2NTIgNDk2LDY1NyA1NTQsNjU3IEwgNzk3LDY1NyA3OTcsNzE3IEMgNzk3LDc2MiA3OTIsODAwIDc4Myw4MzIgNzc0LDg2MyA3NTksODg5IDc0MCw5MDggNzIxLDkyOCA2OTcsOTQyIDY2OCw5NTEgNjM5LDk2MCA2MDQsOTY1IDU2NSw5NjUgNTMwLDk2NSA0OTksOTYzIDQ3MSw5NTggNDQzLDk1MyA0MTksOTQ0IDM5OCw5MzEgMzc3LDkxOCAzNjEsOTAwIDM0OCw4NzggMzM1LDg1NSAzMjcsODI3IDMyMyw3OTMgTCAxMzUsODEwIEMgMTQyLDg1MyAxNTQsODkyIDE3Myw5MjggMTkyLDk2MyAyMTgsOTk0IDI1MywxMDIwIDI4NywxMDQ2IDMzMCwxMDY2IDM4MiwxMDgxIDQzMywxMDk1IDQ5NiwxMTAyIDU2OSwxMTAyIDcwNSwxMTAyIDgwNywxMDcxIDg3NiwxMDA5IDk0NSw5NDYgOTc5LDg1NiA5NzksNzM4IEwgOTc5LDI3MiBDIDk3OSwyMTkgOTg2LDE3OSAxMDAwLDE1MiAxMDE0LDEyNSAxMDQxLDExMSAxMDgwLDExMSAxMDkwLDExMSAxMTAwLDExMiAxMTEwLDExMyAxMTIwLDExNCAxMTMwLDExNiAxMTM5LDExOCBMIDExMzksNiBDIDExMTYsMSAxMDk0LC0zIDEwNzIsLTYgMTA0OSwtOSAxMDI1LC0xMCAxMDAwLC0xMCA5NjYsLTEwIDkzNywtNSA5MTMsNCA4ODgsMTMgODY4LDI2IDg1Myw0NSA4MzgsNjMgODI2LDg2IDgxOCwxMTMgODEwLDE0MCA4MDUsMTcxIDgwMywyMDcgTCA3OTcsMjA3IEMgNzc4LDE3MiA3NTcsMTQxIDczNCwxMTMgNzExLDg1IDY4NCw2MSA2NTMsNDIgNjIyLDIyIDU4OCw3IDU0OSwtNCA1MTAsLTE1IDQ2NSwtMjAgNDE0LC0yMCBaIE0gNDU1LDExNSBDIDUxMiwxMTUgNTYzLDEyNSA2MDYsMTQ2IDY0OSwxNjcgNjg0LDE5NCA3MTMsMjI2IDc0MSwyNTkgNzYyLDI5NCA3NzYsMzMyIDc5MCwzNzEgNzk3LDQwOCA3OTcsNDQzIEwgNzk3LDUzMSA2MDAsNTMxIEMgNTU2LDUzMSA1MTQsNTI4IDQ3NSw1MjIgNDM1LDUxNyA0MDAsNTA2IDM3MCw0ODkgMzQwLDQ3MiAzMTYsNDQ5IDI5OSw0MTggMjgxLDM4OCAyNzIsMzQ5IDI3MiwzMDAgMjcyLDI0MSAyODgsMTk1IDMyMCwxNjMgMzUxLDEzMSAzOTYsMTE1IDQ1NSwxMTUgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iUyIgaG9yaXotYWR2LXg9IjExOTIiIGQ9Ik0gMTI3MiwzODkgQyAxMjcyLDMzMCAxMjYxLDI3NSAxMjM4LDIyNSAxMjE1LDE3NSAxMTc5LDEzMiAxMTMxLDk2IDEwODMsNTkgMTAyMywzMSA5NTAsMTEgODc3LC0xMCA3OTAsLTIwIDY5MCwtMjAgNTE1LC0yMCAzNzgsMTEgMjgwLDcyIDE4MiwxMzMgMTIwLDIyMiA5MywzMzggTCAyNzgsMzc1IEMgMjg3LDMzOCAzMDIsMzA1IDMyMSwyNzUgMzQwLDI0NSAzNjcsMjE5IDQwMCwxOTggNDMzLDE3NiA0NzMsMTU5IDUyMiwxNDcgNTcxLDEzNSA2MjksMTI5IDY5NywxMjkgNzU0LDEyOSA4MDYsMTM0IDg1MywxNDQgOTAwLDE1MyA5NDEsMTY4IDk3NSwxODggMTAwOSwyMDggMTAzNiwyMzQgMTA1NSwyNjYgMTA3NCwyOTcgMTA4MywzMzUgMTA4MywzNzkgMTA4Myw0MjUgMTA3Myw0NjIgMTA1Miw0OTEgMTAzMSw1MjAgMTAwMSw1NDMgOTYzLDU2MiA5MjUsNTgxIDg4MCw1OTYgODI3LDYwOSA3NzQsNjIyIDcxNiw2MzUgNjUyLDY1MCA2MTMsNjU5IDU3Myw2NjggNTM0LDY3OSA0OTQsNjg5IDQ1Niw3MDEgNDIwLDcxNiAzODMsNzMwIDM0OSw3NDcgMzE3LDc2NiAyODUsNzg1IDI1Nyw4MDkgMjM0LDgzNiAyMTEsODYzIDE5Miw4OTQgMTc5LDkzMCAxNjYsOTY1IDE1OSwxMDA2IDE1OSwxMDUzIDE1OSwxMTIwIDE3MywxMTc3IDIwMCwxMjI1IDIyNywxMjcyIDI2NCwxMzExIDMxMiwxMzQyIDM2MCwxMzczIDQxNywxMzk1IDQ4MiwxNDA5IDU0NywxNDIzIDYxOCwxNDMwIDY5NCwxNDMwIDc4MSwxNDMwIDg1NiwxNDIzIDkxOCwxNDEwIDk4MCwxMzk2IDEwMzIsMTM3NSAxMDc1LDEzNDggMTExOCwxMzIxIDExNTIsMTI4NyAxMTc4LDEyNDcgMTIwMywxMjA2IDEyMjQsMTE1OSAxMjM5LDExMDYgTCAxMDUxLDEwNzMgQyAxMDQyLDExMDcgMTAyOCwxMTM3IDEwMTEsMTE2NCA5OTMsMTE5MSA5NzAsMTIxMyA5NDEsMTIzMSA5MTIsMTI0OSA4NzgsMTI2MyA4MzcsMTI3MiA3OTYsMTI4MSA3NDcsMTI4NiA2OTIsMTI4NiA2MjcsMTI4NiA1NzIsMTI4MCA1MjgsMTI2OSA0ODMsMTI1NyA0NDgsMTI0MSA0MjEsMTIyMSAzOTQsMTIwMSAzNzQsMTE3OCAzNjMsMTE1MSAzNTEsMTEyNCAzNDUsMTA5NCAzNDUsMTA2MyAzNDUsMTAyMSAzNTYsOTg3IDM3Nyw5NjAgMzk4LDkzMyA0MjYsOTEwIDQ2Miw4OTIgNDk4LDg3NCA1NDAsODU5IDU4Nyw4NDcgNjM0LDgzNSA2ODUsODIzIDczOCw4MTEgNzgxLDgwMSA4MjUsNzkxIDg2OCw3ODEgOTExLDc3MCA5NTIsNzU4IDk5MSw3NDQgMTAzMCw3MjkgMTA2Nyw3MTIgMTEwMiw2OTMgMTEzNiw2NzQgMTE2Niw2NTAgMTE5MSw2MjIgMTIxNiw1OTQgMTIzNiw1NjEgMTI1MSw1MjMgMTI2NSw0ODUgMTI3Miw0NDAgMTI3MiwzODkgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iTyIgaG9yaXotYWR2LXg9IjE0MzAiIGQ9Ik0gMTQ5NSw3MTEgQyAxNDk1LDYwMSAxNDc5LDUwMSAxNDQ4LDQxMSAxNDE2LDMyMSAxMzcwLDI0NCAxMzEwLDE4MCAxMjUwLDExNiAxMTc3LDY3IDEwOTAsMzIgMTAwMywtMyA5MDUsLTIwIDc5NSwtMjAgNjc5LC0yMCA1NzcsLTIgNDkwLDM1IDQwMyw3MSAzMzAsMTIyIDI3MiwxODcgMjE0LDI1MiAxNzAsMzI5IDE0MSw0MTggMTEyLDUwNyA5Nyw2MDUgOTcsNzExIDk3LDgyMSAxMTIsOTIwIDE0MywxMDA5IDE3NCwxMDk4IDIxOSwxMTczIDI3OCwxMjM2IDMzNywxMjk4IDQxMSwxMzQ2IDQ5OCwxMzgwIDU4NSwxNDEzIDY4NCwxNDMwIDc5NywxNDMwIDkwOSwxNDMwIDEwMDksMTQxMyAxMDk2LDEzNzkgMTE4MywxMzQ1IDEyNTYsMTI5NyAxMzE1LDEyMzQgMTM3NCwxMTcxIDE0MTgsMTA5NiAxNDQ5LDEwMDcgMTQ4MCw5MTggMTQ5NSw4MjAgMTQ5NSw3MTEgWiBNIDEzMDAsNzExIEMgMTMwMCw3OTYgMTI4OSw4NzMgMTI2OCw5NDIgMTI0NiwxMDExIDEyMTQsMTA3MSAxMTcyLDExMjAgMTEyOSwxMTY5IDEwNzcsMTIwNyAxMDE0LDEyMzQgOTUxLDEyNjEgODc5LDEyNzQgNzk3LDEyNzQgNzEzLDEyNzQgNjM5LDEyNjEgNTc2LDEyMzQgNTEzLDEyMDcgNDYwLDExNjkgNDE4LDExMjAgMzc1LDEwNzEgMzQ0LDEwMTEgMzIzLDk0MiAzMDIsODczIDI5MSw3OTYgMjkxLDcxMSAyOTEsNjI2IDMwMiw1NDkgMzI0LDQ3OSAzNDUsNDA4IDM3NywzNDggNDIwLDI5NyA0NjIsMjQ2IDUxNSwyMDYgNTc4LDE3OCA2NDEsMTQ5IDcxMywxMzUgNzk1LDEzNSA4ODMsMTM1IDk1OSwxNDkgMTAyMywxNzggMTA4NiwyMDcgMTEzOSwyNDcgMTE4MCwyOTggMTIyMSwzNDkgMTI1MSw0MDkgMTI3MSw0ODAgMTI5MCw1NTEgMTMwMCw2MjggMTMwMCw3MTEgWiIvPgogICA8Z2x5cGggdW5pY29kZT0iQyIgaG9yaXotYWR2LXg9IjEzMjQiIGQ9Ik0gNzkyLDEyNzQgQyA3MTIsMTI3NCA2NDEsMTI2MSA1ODAsMTIzNCA1MTgsMTIwNyA0NjYsMTE2OSA0MjUsMTEyMCAzODMsMTA3MSAzNTEsMTAxMSAzMzAsOTQyIDMwOSw4NzMgMjk4LDc5NiAyOTgsNzExIDI5OCw2MjYgMzEwLDU0OSAzMzMsNDc5IDM1Niw0MDggMzg5LDM0OCA0MzIsMjk3IDQ3NSwyNDYgNTI3LDIwNyA1OTAsMTc5IDY1MiwxNTEgNzIyLDEzNyA4MDAsMTM3IDg1NSwxMzcgOTA1LDE0NCA5NTAsMTU5IDk5NSwxNzMgMTAzNSwxOTMgMTA3MiwyMTkgMTEwOCwyNDUgMTE0MCwyNzYgMTE2OSwzMTIgMTE5OCwzNDcgMTIyMywzODcgMTI0NSw0MzAgTCAxNDAxLDM1MiBDIDEzNzYsMjk5IDEzNDQsMjUwIDEzMDcsMjA1IDEyNzAsMTYwIDEyMjYsMTIwIDExNzYsODcgMTEyNSw1NCAxMDY4LDI4IDEwMDUsOSA5NDEsLTEwIDg3MCwtMjAgNzkxLC0yMCA2NzcsLTIwIDU3NywtMiA0OTIsMzUgNDA2LDcxIDMzNCwxMjIgMjc3LDE4NyAyMTksMjUyIDE3NiwzMjkgMTQ3LDQxOCAxMTgsNTA3IDEwNCw2MDUgMTA0LDcxMSAxMDQsODIxIDExOSw5MjAgMTUwLDEwMDkgMTgwLDEwOTggMjI0LDExNzMgMjgzLDEyMzYgMzQxLDEyOTggNDEzLDEzNDYgNDk4LDEzODAgNTgzLDE0MTMgNjgxLDE0MzAgNzkwLDE0MzAgOTQwLDE0MzAgMTA2NSwxNDAxIDExNjYsMTM0MiAxMjY3LDEyODMgMTM0MSwxMTk2IDEzODgsMTA4MSBMIDEyMDcsMTAyMSBDIDExOTQsMTA1NCAxMTc2LDEwODYgMTE1MywxMTE3IDExMzAsMTE0NyAxMTAyLDExNzQgMTA2OCwxMTk3IDEwMzQsMTIyMCA5OTQsMTIzOSA5NDksMTI1MyA5MDMsMTI2NyA4NTEsMTI3NCA3OTIsMTI3NCBaIi8+CiAgIDxnbHlwaCB1bmljb2RlPSIgIiBob3Jpei1hZHYteD0iNTU2Ii8+CiAgPC9mb250PgogPC9kZWZzPgogPGRlZnMgY2xhc3M9IlRleHRTaGFwZUluZGV4Ij4KICA8ZyBvb286c2xpZGU9ImlkMSIgb29vOmlkLWxpc3Q9ImlkMyBpZDQgaWQ1IGlkNiBpZDcgaWQ4IGlkOSBpZDEwIGlkMTEgaWQxMiBpZDEzIGlkMTQgaWQxNSBpZDE2IGlkMTcgaWQxOCBpZDE5Ii8+CiA8L2RlZnM+CiA8ZGVmcyBjbGFzcz0iRW1iZWRkZWRCdWxsZXRDaGFycyI+CiAgPGcgaWQ9ImJ1bGxldC1jaGFyLXRlbXBsYXRlKDU3MzU2KSIgdHJhbnNmb3JtPSJzY2FsZSgwLjAwMDQ4ODI4MTI1LC0wLjAwMDQ4ODI4MTI1KSI+CiAgIDxwYXRoIGQ9Ik0gNTgwLDExNDEgTCAxMTYzLDU3MSA1ODAsMCAtNCw1NzEgNTgwLDExNDEgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoNTczNTQpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSA4LDExMjggTCAxMTM3LDExMjggMTEzNywwIDgsMCA4LDExMjggWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAxNDYpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAxNzQsMCBMIDYwMiw3MzkgMTc0LDE0ODEgMTQ1Niw3MzkgMTc0LDAgWiBNIDEzNTgsNzM5IEwgMzA5LDEzNDYgNjU5LDczOSAxMzU4LDczOSBaIi8+CiAgPC9nPgogIDxnIGlkPSJidWxsZXQtY2hhci10ZW1wbGF0ZSgxMDEzMikiIHRyYW5zZm9ybT0ic2NhbGUoMC4wMDA0ODgyODEyNSwtMC4wMDA0ODgyODEyNSkiPgogICA8cGF0aCBkPSJNIDIwMTUsNzM5IEwgMTI3NiwwIDcxNywwIDEyNjAsNTQzIDE3NCw1NDMgMTc0LDkzNiAxMjYwLDkzNiA3MTcsMTQ4MSAxMjc0LDE0ODEgMjAxNSw3MzkgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAwMDcpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAwLC0yIEMgLTcsMTQgLTE2LDI3IC0yNSwzNyBMIDM1Niw1NjcgQyAyNjIsODIzIDIxNSw5NTIgMjE1LDk1NCAyMTUsOTc5IDIyOCw5OTIgMjU1LDk5MiAyNjQsOTkyIDI3Niw5OTAgMjg5LDk4NyAzMTAsOTkxIDMzMSw5OTkgMzU0LDEwMTIgTCAzODEsOTk5IDQ5Miw3NDggNzcyLDEwNDkgODM2LDEwMjQgODYwLDEwNDkgQyA4ODEsMTAzOSA5MDEsMTAyNSA5MjIsMTAwNiA4ODYsOTM3IDgzNSw4NjMgNzcwLDc4NCA3NjksNzgzIDcxMCw3MTYgNTk0LDU4NCBMIDc3NCwyMjMgQyA3NzQsMTk2IDc1MywxNjggNzExLDEzOSBMIDcyNywxMTkgQyA3MTcsOTAgNjk5LDc2IDY3Miw3NiA2NDEsNzYgNTcwLDE3OCA0NTcsMzgxIEwgMTY0LC03NiBDIDE0MiwtMTEwIDExMSwtMTI3IDcyLC0xMjcgMzAsLTEyNyA5LC0xMTAgOCwtNzYgMSwtNjcgLTIsLTUyIC0yLC0zMiAtMiwtMjMgLTEsLTEzIDAsLTIgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoMTAwMDQpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAyODUsLTMzIEMgMTgyLC0zMyAxMTEsMzAgNzQsMTU2IDUyLDIyOCA0MSwzMzMgNDEsNDcxIDQxLDU0OSA1NSw2MTYgODIsNjcyIDExNiw3NDMgMTY5LDc3OCAyNDAsNzc4IDI5Myw3NzggMzI4LDc0NyAzNDYsNjg0IEwgMzY5LDUwOCBDIDM3Nyw0NDQgMzk3LDQxMSA0MjgsNDEwIEwgMTE2MywxMTE2IEMgMTE3NCwxMTI3IDExOTYsMTEzMyAxMjI5LDExMzMgMTI3MSwxMTMzIDEyOTIsMTExOCAxMjkyLDEwODcgTCAxMjkyLDk2NSBDIDEyOTIsOTI5IDEyODIsOTAxIDEyNjIsODgxIEwgNDQyLDQ3IEMgMzkwLC02IDMzOCwtMzMgMjg1LC0zMyBaIi8+CiAgPC9nPgogIDxnIGlkPSJidWxsZXQtY2hhci10ZW1wbGF0ZSg5Njc5KSIgdHJhbnNmb3JtPSJzY2FsZSgwLjAwMDQ4ODI4MTI1LC0wLjAwMDQ4ODI4MTI1KSI+CiAgIDxwYXRoIGQ9Ik0gODEzLDAgQyA2MzIsMCA0ODksNTQgMzgzLDE2MSAyNzYsMjY4IDIyMyw0MTEgMjIzLDU5MiAyMjMsNzczIDI3Niw5MTYgMzgzLDEwMjMgNDg5LDExMzAgNjMyLDExODQgODEzLDExODQgOTkyLDExODQgMTEzNiwxMTMwIDEyNDUsMTAyMyAxMzUzLDkxNiAxNDA3LDc3MiAxNDA3LDU5MiAxNDA3LDQxMiAxMzUzLDI2OCAxMjQ1LDE2MSAxMTM2LDU0IDk5MiwwIDgxMywwIFoiLz4KICA8L2c+CiAgPGcgaWQ9ImJ1bGxldC1jaGFyLXRlbXBsYXRlKDgyMjYpIiB0cmFuc2Zvcm09InNjYWxlKDAuMDAwNDg4MjgxMjUsLTAuMDAwNDg4MjgxMjUpIj4KICAgPHBhdGggZD0iTSAzNDYsNDU3IEMgMjczLDQ1NyAyMDksNDgzIDE1NSw1MzUgMTAxLDU4NiA3NCw2NDkgNzQsNzIzIDc0LDc5NiAxMDEsODU5IDE1NSw5MTEgMjA5LDk2MyAyNzMsOTg5IDM0Niw5ODkgNDE5LDk4OSA0ODAsOTYzIDUzMSw5MTAgNTgyLDg1OSA2MDgsNzk2IDYwOCw3MjMgNjA4LDY0OCA1ODMsNTg2IDUzMiw1MzUgNDgyLDQ4MyA0MjAsNDU3IDM0Niw0NTcgWiIvPgogIDwvZz4KICA8ZyBpZD0iYnVsbGV0LWNoYXItdGVtcGxhdGUoODIxMSkiIHRyYW5zZm9ybT0ic2NhbGUoMC4wMDA0ODgyODEyNSwtMC4wMDA0ODgyODEyNSkiPgogICA8cGF0aCBkPSJNIC00LDQ1OSBMIDExMzUsNDU5IDExMzUsNjA2IC00LDYwNiAtNCw0NTkgWiIvPgogIDwvZz4KIDwvZGVmcz4KIDxkZWZzIGNsYXNzPSJUZXh0RW1iZWRkZWRCaXRtYXBzIi8+CiA8Zz4KICA8ZyBpZD0iaWQyIiBjbGFzcz0iTWFzdGVyX1NsaWRlIj4KICAgPGcgaWQ9ImJnLWlkMiIgY2xhc3M9IkJhY2tncm91bmQiLz4KICAgPGcgaWQ9ImJvLWlkMiIgY2xhc3M9IkJhY2tncm91bmRPYmplY3RzIi8+CiAgPC9nPgogPC9nPgogPGcgY2xhc3M9IlNsaWRlR3JvdXAiPgogIDxnPgogICA8ZyBpZD0iaWQxIiBjbGFzcz0iU2xpZGUiIGNsaXAtcGF0aD0idXJsKCNwcmVzZW50YXRpb25fY2xpcF9wYXRoKSI+CiAgICA8ZyBjbGFzcz0iUGFnZSI+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLlJlY3RhbmdsZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMyI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODQ1MCw3MDAwIEwgNzAwMCw3MDAwIDcwMDAsMzAwMCA5OTAwLDMwMDAgOTkwMCw3MDAwIDg0NTAsNzAwMCBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLlJlY3RhbmdsZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkNCI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTIwNTAsNzAwMCBMIDEwMTAwLDcwMDAgMTAxMDAsMzAwMCAxNDAwMCwzMDAwIDE0MDAwLDcwMDAgMTIwNTAsNzAwMCBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkVsbGlwc2VTaGFwZSI+CiAgICAgIDxnIGlkPSJpZDUiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDg5OTksMzMwMCBDIDkxMDUsMzMxMiA5MTk1LDMzODMgOTI4OCwzNTMxIDkzODcsMzY5MCA5NDU5LDM4ODkgOTUxNiw0MTY1IDk1NzQsNDQ0MSA5NjAwLDQ3MTIgOTYwMCw1MDMxIDk2MDAsNTM1MCA5NTc0LDU2MjEgOTUxNiw1ODk3IDk0NTksNjE3MyA5NDAyLDYzMjggOTMxOSw2NDc4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiIGQ9Ik0gOTE0MSw2NzAxIEwgOTQwNSw2NTI2IDkyNDgsNjQwMyA5MTQxLDY3MDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5FbGxpcHNlU2hhcGUiPgogICAgICA8ZyBpZD0iaWQ2Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDc5NCw2NzEwIEMgMTA3NDgsNjY2OSAxMDcxMCw2NjE4IDEwNjY4LDY1NDAgMTA1ODMsNjM4MCAxMDUyMSw2MTgxIDEwNDcyLDU5MDUgMTA0MjIsNTYyOCAxMDQwMCw1MzU2IDEwNDAwLDUwMzYgMTA0MDAsNDcxNiAxMDQyMiw0NDQ0IDEwNDcyLDQxNjggMTA1MjEsMzg5MSAxMDU4MywzNjkyIDEwNjY4LDM1MzIgMTA3NDgsMzM4MyAxMDY5MCwzNDkyIDEwNzAxLDM0NzQiLz4KICAgICAgIDxwYXRoIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSIgZD0iTSAxMDkxNiwzMzAwIEwgMTA2MjIsMzQxNiAxMDc1MCwzNTY5IDEwOTE2LDMzMDAgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDciPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDk4OTksNjkwMCBDIDk5NTUsNjkwMCA5OTk5LDY5NDMgOTk5OSw2OTk5IDk5OTksNzA1NSA5OTU1LDcwOTkgOTg5OSw3MDk5IDk4NDMsNzA5OSA5ODAwLDcwNTUgOTgwMCw2OTk5IDk4MDAsNjk0MyA5ODQzLDY5MDAgOTg5OSw2OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSA5ODAwLDY5MDAgTCA5ODAwLDY5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDAxLDcxMDEgTCAxMDAwMSw3MTAxIFoiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuQ3VzdG9tU2hhcGUiPgogICAgICA8ZyBpZD0iaWQ4Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDA5OSwyOTAwIEMgMTAxNTUsMjkwMCAxMDE5OSwyOTQzIDEwMTk5LDI5OTkgMTAxOTksMzA1NSAxMDE1NSwzMDk5IDEwMDk5LDMwOTkgMTAwNDMsMzA5OSAxMDAwMCwzMDU1IDEwMDAwLDI5OTkgMTAwMDAsMjk0MyAxMDA0MywyOTAwIDEwMDk5LDI5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDAwLDI5MDAgTCAxMDAwMCwyOTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDIwMSwzMTAxIEwgMTAyMDEsMzEwMSBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkOSI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTg5OSwyOTAwIEMgOTk1NSwyOTAwIDk5OTksMjk0MyA5OTk5LDI5OTkgOTk5OSwzMDU1IDk5NTUsMzA5OSA5ODk5LDMwOTkgOTg0MywzMDk5IDk4MDAsMzA1NSA5ODAwLDI5OTkgOTgwMCwyOTQzIDk4NDMsMjkwMCA5ODk5LDI5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDk4MDAsMjkwMCBMIDk4MDAsMjkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwMDEsMzEwMSBMIDEwMDAxLDMxMDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDEwIj4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSA5ODk5LDQ5MDAgQyA5OTU1LDQ5MDAgOTk5OSw0OTQzIDk5OTksNDk5OSA5OTk5LDUwNTUgOTk1NSw1MDk5IDk4OTksNTA5OSA5ODQzLDUwOTkgOTgwMCw1MDU1IDk4MDAsNDk5OSA5ODAwLDQ5NDMgOTg0Myw0OTAwIDk4OTksNDkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTgwMCw0OTAwIEwgOTgwMCw0OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDAwMSw1MTAxIEwgMTAwMDEsNTEwMSBaIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTEiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMDk5LDQ5MDAgQyAxMDE1NSw0OTAwIDEwMTk5LDQ5NDMgMTAxOTksNDk5OSAxMDE5OSw1MDU1IDEwMTU1LDUwOTkgMTAwOTksNTA5OSAxMDA0Myw1MDk5IDEwMDAwLDUwNTUgMTAwMDAsNDk5OSAxMDAwMCw0OTQzIDEwMDQzLDQ5MDAgMTAwOTksNDkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwMDAsNDkwMCBMIDEwMDAwLDQ5MDAgWiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMjAxLDUxMDEgTCAxMDIwMSw1MTAxIFoiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuQ3VzdG9tU2hhcGUiPgogICAgICA8ZyBpZD0iaWQxMiI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAwOTksNjkwMCBDIDEwMTU1LDY5MDAgMTAxOTksNjk0MyAxMDE5OSw2OTk5IDEwMTk5LDcwNTUgMTAxNTUsNzA5OSAxMDA5OSw3MDk5IDEwMDQzLDcwOTkgMTAwMDAsNzA1NSAxMDAwMCw2OTk5IDEwMDAwLDY5NDMgMTAwNDMsNjkwMCAxMDA5OSw2OTAwIFoiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDAwMCw2OTAwIEwgMTAwMDAsNjkwMCBaIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAyMDEsNzEwMSBMIDEwMjAxLDcxMDEgWiIvPgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5DdXN0b21TaGFwZSI+CiAgICAgIDxnIGlkPSJpZDEzIj4KICAgICAgIDxwYXRoIGZpbGw9InJnYigyNTUsMjU1LDI1NSkiIHN0cm9rZT0ibm9uZSIgZD0iTSA1MTAwLDUyMDAgTCAzNTAwLDUyMDAgMzUwMCwzMDAwIDY3MDAsMzAwMCA2NzAwLDUyMDAgNTEwMCw1MjAwIFoiLz4KICAgICAgIDx0ZXh0IGNsYXNzPSJUZXh0U2hhcGUiPjx0c3BhbiBjbGFzcz0iVGV4dFBhcmFncmFwaCIgZm9udC1mYW1pbHk9IkxpYmVyYXRpb24gU2Fucywgc2Fucy1zZXJpZiIgZm9udC1zaXplPSIzNTNweCIgZm9udC13ZWlnaHQ9IjQwMCI+PHRzcGFuIGNsYXNzPSJUZXh0UG9zaXRpb24iIHg9IjM3NTAiIHk9IjM0MzMiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPlN1YmRpdmlzaW9uIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMzc1MCIgeT0iMzgyNyI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+cG9pbnRzIG5lZWQgdG8gPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIzNzUwIiB5PSI0MjIxIj48dHNwYW4gZmlsbD0icmdiKDAsMCwwKSIgc3Ryb2tlPSJub25lIj5sYW5kIG9uIHRoZSBzYW1lIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMzc1MCIgeT0iNDYxNSI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+bG9jYXRpb24gdG8gPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIzNzUwIiB5PSI1MDA5Ij48dHNwYW4gZmlsbD0icmdiKDAsMCwwKSIgc3Ryb2tlPSJub25lIj5wcmV2ZW50IGNyYWNraW5nPC90c3Bhbj48L3RzcGFuPjwvdHNwYW4+PC90ZXh0PgogICAgICA8L2c+CiAgICAgPC9nPgogICAgIDxnIGNsYXNzPSJjb20uc3VuLnN0YXIuZHJhd2luZy5MaW5lU2hhcGUiPgogICAgICA8ZyBpZD0iaWQxNCI+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjYwMCw0MjAwIEwgNjY1MSw0MjEzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjcwMyw0MjI3IEwgNjc1NCw0MjQwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjgwNiw0MjUzIEwgNjg1Nyw0MjY2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNjkwOCw0MjgwIEwgNjk2MCw0MjkzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzAxMSw0MzA2IEwgNzA2Myw0MzE5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzExNCw0MzMzIEwgNzE2NSw0MzQ2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzIxNyw0MzU5IEwgNzI2OCw0MzcyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzMyMCw0Mzg2IEwgNzM3MSw0Mzk5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzQyMyw0NDEyIEwgNzQ3NCw0NDI2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzUyNSw0NDM5IEwgNzU3Nyw0NDUyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzYyOCw0NDY1IEwgNzY4MCw0NDc5Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzczMSw0NDkyIEwgNzc4Miw0NTA1Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzgzNCw0NTE4IEwgNzg4NSw0NTMyIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gNzkzNyw0NTQ1IEwgNzk4OCw0NTU4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODAzOSw0NTcxIEwgODA5MSw0NTg1Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODE0Miw0NTk4IEwgODE5NCw0NjExIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODI0NSw0NjI1IEwgODI5Niw0NjM4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODM0OCw0NjUxIEwgODM5OSw0NjY0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODQ1MSw0Njc4IEwgODUwMiw0NjkxIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODU1Myw0NzA0IEwgODYwNSw0NzE3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODY1Niw0NzMxIEwgODcwOCw0NzQ0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODc1OSw0NzU3IEwgODgxMSw0NzcwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODg2Miw0Nzg0IEwgODkxMyw0Nzk3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gODk2NSw0ODEwIEwgOTAxNiw0ODI0Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTA2OCw0ODM3IEwgOTExOSw0ODUwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTE3MCw0ODYzIEwgOTIyMiw0ODc3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTI3Myw0ODkwIEwgOTMyNSw0OTAzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTM3Niw0OTE2IEwgOTQyNyw0OTMwIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTQ3OSw0OTQzIEwgOTUzMCw0OTU2Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTU4Miw0OTY5IEwgOTYzMyw0OTgzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gOTY4NCw0OTk2IEwgOTcwMCw1MDAwIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTUiPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyNjUwLDI3MDAgTCAxMDcwMCwyNzAwIDEwNzAwLDE1MDAgMTQ2MDAsMTUwMCAxNDYwMCwyNzAwIDEyNjUwLDI3MDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTA5NTAiIHk9IjIwMjQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPkNvcm5lciBwb2ludHMgc3RhcnQgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMDk1MCIgeT0iMjQxOCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+d2l0aCB0aGUgc2FtZSB2YWx1ZXM8L3RzcGFuPjwvdHNwYW4+PC90c3Bhbj48L3RleHQ+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTYiPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyODUwLDg1MDAgTCAxMDkwMCw4NTAwIDEwOTAwLDczMDAgMTQ4MDAsNzMwMCAxNDgwMCw4NTAwIDEyODUwLDg1MDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9Ijc4MjQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPkNvcm5lciBwb2ludHMgc3RhcnQgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMTE1MCIgeT0iODIxOCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+d2l0aCB0aGUgc2FtZSB2YWx1ZXM8L3RzcGFuPjwvdHNwYW4+PC90c3Bhbj48L3RleHQ+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkN1c3RvbVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTciPgogICAgICAgPHBhdGggZmlsbD0icmdiKDI1NSwyNTUsMjU1KSIgc3Ryb2tlPSJub25lIiBkPSJNIDEyNDAwLDUyMDAgTCAxMDkwMCw1MjAwIDEwOTAwLDMzMDAgMTM5MDAsMzMwMCAxMzkwMCw1MjAwIDEyNDAwLDUyMDAgWiIvPgogICAgICAgPHRleHQgY2xhc3M9IlRleHRTaGFwZSI+PHRzcGFuIGNsYXNzPSJUZXh0UGFyYWdyYXBoIiBmb250LWZhbWlseT0iTGliZXJhdGlvbiBTYW5zLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjM1M3B4IiBmb250LXdlaWdodD0iNDAwIj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjM3ODAiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPk9wcG9zaW5nIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjQxNzQiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPmRpcmVjdGlvbnMgb2YgPC90c3Bhbj48L3RzcGFuPjx0c3BhbiBjbGFzcz0iVGV4dFBvc2l0aW9uIiB4PSIxMTE1MCIgeT0iNDU2OCI+PHRzcGFuIGZpbGw9InJnYigwLDAsMCkiIHN0cm9rZT0ibm9uZSI+ZWRnZSB3YWxraW5nIDwvdHNwYW4+PC90c3Bhbj48dHNwYW4gY2xhc3M9IlRleHRQb3NpdGlvbiIgeD0iMTExNTAiIHk9IjQ5NjIiPjx0c3BhbiBmaWxsPSJyZ2IoMCwwLDApIiBzdHJva2U9Im5vbmUiPmZvciBzdWJkaXZpc2lvbjwvdHNwYW4+PC90c3Bhbj48L3RzcGFuPjwvdGV4dD4KICAgICAgPC9nPgogICAgIDwvZz4KICAgICA8ZyBjbGFzcz0iY29tLnN1bi5zdGFyLmRyYXdpbmcuTGluZVNoYXBlIj4KICAgICAgPGcgaWQ9ImlkMTgiPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMzAwLDI5MDAgTCAxMDM0MSwyODY3Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAzODMsMjgzNCBMIDEwNDI0LDI4MDEiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDQ2NiwyNzY3IEwgMTA1MDcsMjczNCIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNTQ5LDI3MDEgTCAxMDU5MCwyNjY4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA2MzIsMjYzNSBMIDEwNjczLDI2MDIiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDcxNSwyNTY4IEwgMTA3NTYsMjUzNSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNzk3LDI1MDIgTCAxMDgwMCwyNTAwIi8+CiAgICAgIDwvZz4KICAgICA8L2c+CiAgICAgPGcgY2xhc3M9ImNvbS5zdW4uc3Rhci5kcmF3aW5nLkxpbmVTaGFwZSI+CiAgICAgIDxnIGlkPSJpZDE5Ij4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDIwMCw3MTAwIEwgMTAyNDMsNzEzMSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwMjg2LDcxNjIgTCAxMDMzMCw3MTkzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTAzNzMsNzIyMyBMIDEwNDE2LDcyNTQiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDQ1OSw3Mjg1IEwgMTA1MDIsNzMxNiIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwNTQ2LDczNDcgTCAxMDU4OSw3Mzc4Ii8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA2MzIsNzQwOSBMIDEwNjc1LDc0MzkiLz4KICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsMCwwKSIgZD0iTSAxMDcxOCw3NDcwIEwgMTA3NjIsNzUwMSIvPgogICAgICAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwwLDApIiBkPSJNIDEwODA1LDc1MzIgTCAxMDg0OCw3NTYzIi8+CiAgICAgICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLDAsMCkiIGQ9Ik0gMTA4OTEsNzU5NCBMIDEwOTAwLDc2MDAiLz4KICAgICAgPC9nPgogICAgIDwvZz4KICAgIDwvZz4KICAgPC9nPgogIDwvZz4KIDwvZz4KPC9zdmc+" alt="precise"> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Without any qualifiers, implementations are permitted to perform |
| optimizations that effectively modify the order or number of operations used |
| to evaluate an expression, even if those optimizations may produce slightly |
| different results relative to unoptimized code.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>precise</strong> qualifier ensures that operations contributing to a |
| variable’s value are done in their stated order and with operator consistency. |
| The order is determined by operator precedence and parenthesis, as described in |
| “<a href="#operators">Operators</a>”. |
| 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 = <any other mathematically |
| valid combination></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’s responsibility to express the computation in terms of these rules |
| and the compiler’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 “<a href="#the-invariant-qualifier">The |
| Invariant Qualifier</a>”), 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 <k> 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 “<a href="#constant-expressions">Constant Expressions</a>”, |
| 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 “<strong>image</strong>” |
| in their keyword), can be further qualified with one or more of the |
| following memory qualifiers:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Qualifier</th> |
| <th class="tableblock halign-left valign-top">Meaning</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>coherent</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">memory variable where reads and writes are coherent with |
| reads and writes from other shader invocations</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>volatile</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">memory variable whose underlying value may be changed at any |
| point during shader execution by some source other than the |
| current shader invocation</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>restrict</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">memory variable where use of that variable is the only way |
| to read and write the underlying memory in the relevant |
| shader stage</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>readonly</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">memory variable that can be used to read the underlying |
| memory, but cannot be used to write the underlying memory</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>writeonly</strong></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">memory variable that can be used to write the underlying |
| memory, but cannot be used to read the underlying memory</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Memory accesses to image variables declared using the <strong>coherent</strong> qualifier |
| are performed coherently with accesses to the same location from other |
| shader invocations. |
| In particular, when reading a variable declared as <strong>coherent</strong>, the values |
| returned will reflect the results of previously completed writes performed |
| by other shader invocations. |
| When writing a variable declared as <strong>coherent</strong>, the values written will be |
| reflected in subsequent coherent reads performed by other shader |
| invocations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As described in section |
| 7.12 |
| “Shader Memory Access” of the |
| <a href="#references">OpenGL Specification</a>, shader memory reads and writes complete in a |
| largely undefined order. |
| The built-in function <strong>memoryBarrier</strong>() can be used if needed to guarantee |
| the completion and relative ordering of memory accesses performed by a |
| single shader invocation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When accessing memory using variables not declared as <strong>coherent</strong>, the memory |
| accessed by a shader may be cached by the implementation to service future |
| accesses to the same address. |
| Memory stores may be cached in such a way that the values written may not be |
| visible to other shader invocations accessing the same memory. |
| The implementation may cache the values fetched by memory reads and return |
| the same values to any shader invocation accessing the same memory, even if |
| the underlying memory has been modified since the first memory read. |
| While variables not declared as <strong>coherent</strong> may not be useful for |
| communicating between shader invocations, using non-coherent accesses may |
| result in higher performance.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory accesses to image variables declared using the <strong>volatile</strong> qualifier |
| must treat the underlying memory as though it could be read or written at |
| any point during shader execution by some source other than the executing |
| shader invocation. |
| When a volatile variable is read, its value must be re-fetched from the |
| underlying memory, even if the shader invocation performing the read had |
| previously fetched its value from the same memory. |
| When a volatile variable is written, its value must be written to the |
| underlying memory, even if the compiler can conclusively determine that its |
| value will be overwritten by a subsequent write. |
| Since the external source reading or writing a <strong>volatile</strong> variable may be |
| another shader invocation, variables declared as <strong>volatile</strong> are |
| automatically treated as coherent.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory accesses to image variables declared using the <strong>restrict</strong> qualifier |
| may be compiled assuming that the variable used to perform the memory access |
| is the only way to access the underlying memory using the shader stage in |
| question. |
| This allows the compiler to coalesce or reorder loads and stores using |
| <strong>restrict</strong>-qualified image variables in ways that wouldn’t be permitted |
| for image variables not so qualified, because the compiler can assume that |
| the underlying image won’t be read or written by other code. |
| Applications are responsible for ensuring that image memory referenced by |
| variables qualified with <strong>restrict</strong> will not be referenced using other |
| variables in the same scope; otherwise, accesses to <strong>restrict</strong>-qualified |
| variables will have undefined results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory accesses to image variables declared using the <strong>readonly</strong> qualifier |
| may only read the underlying memory, which is treated as read-only memory |
| and cannot be written to. |
| It is a compile-time error to pass an image variable qualified with |
| <strong>readonly</strong> to <strong>imageStore</strong>() or other built-in functions that modify image |
| memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Memory accesses to image variables declared using the <strong>writeonly</strong> qualifier |
| may only write the underlying memory; the underlying memory cannot be read. |
| It is a compile-time error to pass an image variable qualified with |
| <strong>writeonly</strong> to <strong>imageLoad</strong>() or other built-in functions that read image |
| memory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A variable could be qualified as both <strong>readonly</strong> and <strong>writeonly</strong>, disallowing |
| both read and write. Such variables can still be used with some queries, for |
| example <strong>imageSize</strong>() and <strong>.length</strong>().</p> |
| </div> |
| <div class="paragraph"> |
| <p>The memory qualifiers <strong>coherent</strong>, <strong>volatile</strong>, <strong>restrict</strong>, <strong>readonly</strong>, and |
| <strong>writeonly</strong> may be used in the declaration of buffer variables (i.e., |
| members of shader storage blocks). |
| When a buffer variable is declared with a memory qualifier, the behavior |
| specified for memory accesses involving image variables described above |
| applies identically to memory accesses involving that buffer variable. |
| It is a compile-time error to assign to a buffer variable qualified with |
| <strong>readonly</strong> or to read from a buffer variable qualified with <strong>writeonly</strong>. |
| The combination <strong>readonly</strong> <strong>writeonly</strong> is allowed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Additionally, memory qualifiers may be used at the block-level declaration |
| of a shader storage block, including the combination <strong>readonly</strong> <strong>writeonly</strong>. |
| When a block declaration is qualified with a memory qualifier, it is as if |
| all of its members were declared with the same memory qualifier. |
| For example, the block declaration</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">coherent buffer Block { |
| readonly vec4 member1; |
| vec4 member2; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">buffer Block { |
| coherent readonly vec4 member1; |
| coherent vec4 member2; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Memory qualifiers are only supported in the declarations of image variables, |
| buffer variables, and shader storage blocks; it is an error to use such |
| qualifiers in any other declarations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When calling user-defined functions, variables qualified with <strong>coherent</strong>, |
| <strong>volatile</strong>, <strong>readonly</strong>, or <strong>writeonly</strong> may not be passed to functions whose |
| formal parameters lack such qualifiers. |
| (See “<a href="#function-definitions">Function Definitions</a>” 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 "restrict" is allowed</span> |
| funcB(img2); <span class="comment">// illegal, stripping "coherent" is not</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Layout qualifiers cannot be used on formal function parameters, and layout |
| qualification is not included in parameter matching.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that the use of <strong>const</strong> in an image variable declaration is qualifying |
| the const-ness of the variable being declared, not the image it refers to. |
| The qualifier <strong>readonly</strong> qualifies the image memory (as accessed through |
| that variable) while <strong>const</strong> qualifies the variable itself.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="specialization-constant-qualifier">4.11. Specialization-Constant Qualifier</h3> |
| <div class="paragraph"> |
| <p>Specialization constants are used only for SPIR-V and declared using the |
| <strong>constant_id</strong> layout qualifier. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">17</span>) <span class="directive">const</span> <span class="predefined-type">int</span> arraySize = <span class="integer">12</span>;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The above makes a specialization constant with a default value of 12. |
| The number 17 is an example author-chosen id by which the API or other tools |
| can later refer to this specific specialization constant. |
| If it is never changed before final lowering, it will retain the value of |
| 12. |
| It is a compile-time error to use the <strong>constant_id</strong> qualifier on anything |
| but SPIR-V generation of a scalar <strong>bool</strong>, <strong>int</strong>, <strong>uint</strong>, <strong>float</strong>, or |
| <strong>double</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Built-in constants can be declared to be specialization constants. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">31</span>) gl_MaxClipDistances; <span class="comment">// add specialization_id</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The declaration uses just the name of the previously declared built-in |
| variable, with a <strong>constant_id</strong> layout-qualifier declaration. |
| It is a compile-time error to do this after the constant has been used: |
| Constants are strictly either non-specialization constants or specialization |
| constants, not both.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in constant vector <em>gl_WorkGroupSize</em> can be specialized using the |
| <strong>local_size_{xyz}_id</strong> qualifiers, to individually give the components an id. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x_id = <span class="integer">18</span>, local_size_z_id = <span class="integer">19</span>) in;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This leaves <em>gl_WorkGroupSize.y</em> as a non-specialization constant, with |
| <em>gl_WorkGroupSize</em> being a partially specialized vector. |
| Its <em>x</em> and <em>z</em> components can be later specialized, after generating |
| SPIR-V, using the ids 18 and 19. |
| These ids are declared independently from declaring the workgroup size:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(local_size_x = <span class="integer">32</span>, local_size_y = <span class="integer">32</span>) in; <span class="comment">// size is (32,32,1)</span> |
| layout(local_size_x_id = <span class="integer">18</span>) in; <span class="comment">// constant_id for x</span> |
| layout(local_size_z_id = <span class="integer">19</span>) in; <span class="comment">// constant_id for z</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Existing rules for declaring <strong>local_size_x</strong>, <strong>local_size_y</strong>, and |
| <strong>local_size_z</strong> are not changed. |
| For the local-size ids, it is a compile-time error to provide different id |
| values for the same local-size id, or to provide them after any use. |
| Otherwise, order, placement, number of statements, and replication do not |
| cause errors.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Two arrays sized with specialization constants are the same type only if |
| sized with the same symbol, and involving no operations. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">layout(constant_id = <span class="integer">51</span>) <span class="directive">const</span> <span class="predefined-type">int</span> aSize = <span class="integer">20</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> pad = <span class="integer">2</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> total = aSize + pad; <span class="comment">// specialization constant</span> |
| <span class="predefined-type">int</span> a[total], b[total]; <span class="comment">// a and b have the same type</span> |
| <span class="predefined-type">int</span> c[<span class="integer">22</span>]; <span class="comment">// different type than a or b</span> |
| <span class="predefined-type">int</span> d[aSize + pad]; <span class="comment">// different type than a, b, or c</span> |
| <span class="predefined-type">int</span> e[aSize + <span class="integer">2</span>]; <span class="comment">// different type than a, b, c, or d</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Types containing arrays sized with a specialization constant cannot be |
| compared, assigned as aggregates, declared with an initializer, or used as |
| an initializer. |
| They can, however, be passed as arguments to functions having formal |
| parameters of the same type. |
| Only the outer-most dimension of a variable declared as an array of arrays |
| can be a specialization constant, otherwise a compile-time error results.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Arrays inside a block may be sized with a specialization constant, but the |
| block will have a static layout. |
| Changing the specialized size will not re-layout the block. |
| In the absence of explicit offsets, the layout will be based on the default |
| size of the array.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="order-of-qualification">4.12. Order and Repetition of Qualification</h3> |
| <div class="paragraph"> |
| <p>When multiple qualifiers are present in a declaration, they may appear in |
| any order, but they must all appear before the type. |
| The <strong>layout</strong> qualifier is the only qualifier that can appear more than once. |
| Further, a declaration can have at most one storage qualifier, at most one |
| auxiliary storage qualifier, and at most one interpolation qualifier. |
| If <strong>inout</strong> is used, neither <strong>in</strong> nor <strong>out</strong> may be used. |
| Multiple memory qualifiers can be used. |
| Any violation of these rules will cause a compile-time error.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="empty-declarations">4.13. Empty Declarations</h3> |
| <div class="paragraph"> |
| <p><em>Empty declarations</em> are declarations without a variable name, meaning no |
| object is instantiated by the declaration. |
| Generally, empty declarations are allowed. |
| Some are useful when declaring structures, while many others have no effect. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span>; <span class="comment">// No effect</span> |
| <span class="keyword">struct</span> S {<span class="predefined-type">int</span> x;}; <span class="comment">// Defines a struct S</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The combinations of qualifiers that cause compile-time or link-time errors |
| are the same whether or not the declaration is empty, for example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">invariant in <span class="predefined-type">float</span> x; <span class="comment">// Error. An input cannot be invariant.</span> |
| invariant in <span class="predefined-type">float</span>; <span class="comment">// Error even though no variable is declared.</span></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="operators-and-expressions">5. Operators and Expressions</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="operators">5.1. Operators</h3> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language has the following operators.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Precedence</th> |
| <th class="tableblock halign-left valign-top">Operator Class</th> |
| <th class="tableblock halign-left valign-top">Operators</th> |
| <th class="tableblock halign-left valign-top">Associativity</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1 (highest)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">parenthetical grouping</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">( )</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">NA</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">array subscript<br> |
| function call and constructor structure<br> |
| field or method selector, swizzle<br> |
| post fix increment and decrement</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">[ ]<br> |
| ( )<br> |
| .<br> |
| ++ --</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">prefix increment and decrement<br> |
| unary</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">++ --<br> |
| + - ~ !</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Right to Left</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">multiplicative</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">* / %</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">additive</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">+ -</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Left to Right</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">bit-wise shift</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><< >></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">< > <= >=</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">&</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">&&</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> |
| %= <<= >>=<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">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 “<a href="#structure-and-array-operations">Structure and |
| Array Operations</a>”.</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 |
| “<a href="#function-definitions">Function Definitions</a>”.</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 “<a href="#shading-language-grammar">Shading Language Grammar</a>” for details.) |
| The parameters are used to initialize the constructed value. |
| Constructors can be used to request a data type conversion to change from |
| one scalar type to another scalar type, or to build larger types out of |
| smaller types, or to reduce a larger type to a smaller type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, constructors are not built-in functions with predetermined |
| prototypes. |
| For arrays and structures, there must be exactly one argument in the |
| constructor for each element or member. |
| For the other types, the arguments must provide a sufficient number of |
| components to perform the initialization, and it is a compile-time error to |
| include so many arguments that they cannot all be used. |
| Detailed rules follow. |
| The prototypes actually listed below are merely a subset of examples.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="conversion-and-scalar-constructors">5.4.1. Conversion and Scalar Constructors</h4> |
| <div class="paragraph"> |
| <p>Converting between scalar types is done as the following prototypes |
| indicate:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="predefined-type">int</span>(uint) <span class="comment">// converts an unsigned integer to a signed integer</span> |
| <span class="predefined-type">int</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to an int</span> |
| <span class="predefined-type">int</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to an int</span> |
| <span class="predefined-type">int</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a signed integer</span> |
| uint(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to an unsigned integer</span> |
| uint(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to an unsigned integer</span> |
| uint(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to an unsigned integer</span> |
| uint(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to an unsigned integer</span> |
| <span class="predefined-type">bool</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a Boolean</span> |
| <span class="predefined-type">bool</span>(uint) <span class="comment">// converts an unsigned integer value to a Boolean value</span> |
| <span class="predefined-type">bool</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to a Boolean</span> |
| <span class="predefined-type">bool</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a Boolean</span> |
| <span class="predefined-type">float</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a float</span> |
| <span class="predefined-type">float</span>(uint) <span class="comment">// converts an unsigned integer value to a float value</span> |
| <span class="predefined-type">float</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to a float</span> |
| <span class="predefined-type">float</span>(<span class="predefined-type">double</span>) <span class="comment">// converts a double value to a float</span> |
| <span class="predefined-type">double</span>(<span class="predefined-type">int</span>) <span class="comment">// converts a signed integer value to a double</span> |
| <span class="predefined-type">double</span>(uint) <span class="comment">// converts an unsigned integer value to a double</span> |
| <span class="predefined-type">double</span>(<span class="predefined-type">bool</span>) <span class="comment">// converts a Boolean value to a double</span> |
| <span class="predefined-type">double</span>(<span class="predefined-type">float</span>) <span class="comment">// converts a float value to a double</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When constructors are used to convert a floating-point type to an integer |
| type, the fractional part of the floating-point value is dropped. |
| It is undefined to convert a negative floating-point value to an <strong>uint</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Integer values having more bits of precision than a single-precision |
| floating-point mantissa will lose precision when converted to <strong>float</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When a constructor is used to convert any integer or floating-point type to |
| a <strong>bool</strong>, 0 and 0.0 are converted to <strong>false</strong>, and non-zero values are |
| converted to <strong>true</strong>. |
| When a constructor is used to convert a <strong>bool</strong> to any integer or |
| floating-point type, <strong>false</strong> is converted to 0 or 0.0, and <strong>true</strong> is |
| converted to 1 or 1.0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The constructor <strong>int</strong>(<strong>uint</strong>) preserves the bit pattern in the argument, |
| which will change the argument’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’s value. |
| If there is a single scalar parameter to a matrix constructor, it is used to |
| initialize all the components on the matrix’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’s components will be |
| constructed in order from the components of the arguments. |
| The arguments will be consumed left to right, and each argument will have |
| all its components consumed, in order, before any components from the next |
| argument are consumed. |
| Similarly for constructing a matrix from multiple scalars or vectors, or a |
| mixture of these. |
| Matrix components will be constructed and consumed in column major order. |
| In these cases, there must be enough components provided in the arguments to |
| provide an initializer for every component in the constructed value. |
| It is a compile-time error to provide extra arguments beyond this last used |
| argument.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a matrix is constructed from a matrix, then each component (column <em>i</em>, |
| row <em>j</em>) in the result that has a corresponding component (column <em>i</em>, row |
| <em>j</em>) in the argument will be initialized from there. |
| All other components will be initialized to the identity matrix. |
| If a matrix argument is given to a matrix constructor, it is |
| a compile-time error to have any other arguments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the basic type (<strong>bool</strong>, <strong>int</strong>, |
| <strong>float</strong>, or <strong>double</strong>) |
| of a parameter to a |
| constructor does not match the basic type of the object being constructed, |
| the scalar construction rules (above) are used to convert the parameters.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Some useful vector constructors are as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec3(<span class="predefined-type">float</span>) <span class="comment">// initializes each component of the vec3 with the float</span> |
| vec4(ivec4) <span class="comment">// makes a vec4 with component-wise conversion</span> |
| vec4(mat2) <span class="comment">// the vec4 is column 0 followed by column 1</span> |
| vec2(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>) <span class="comment">// initializes a vec2 with 2 floats</span> |
| ivec3(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>, <span class="predefined-type">int</span>) <span class="comment">// initializes an ivec3 with 3 ints</span> |
| bvec4(<span class="predefined-type">int</span>, <span class="predefined-type">int</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>) <span class="comment">// uses 4 Boolean conversions</span> |
| vec2(vec3) <span class="comment">// drops the third component of a vec3</span> |
| vec3(vec4) <span class="comment">// drops the fourth component of a vec4</span> |
| vec3(vec2, <span class="predefined-type">float</span>) <span class="comment">// vec3.x = vec2.x, vec3.y = vec2.y, vec3.z = float</span> |
| vec3(<span class="predefined-type">float</span>, vec2) <span class="comment">// vec3.x = float, vec3.y = vec2.x, vec3.z = vec2.y</span> |
| vec4(vec3, <span class="predefined-type">float</span>) |
| vec4(<span class="predefined-type">float</span>, vec3) |
| vec4(vec2, vec2)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Some examples of these are:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 color = vec4(<span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>, <span class="float">0</span><span class="float">.0</span>, <span class="float">1</span><span class="float">.0</span>); |
| vec4 rgba = vec4(<span class="float">1</span><span class="float">.0</span>); <span class="comment">// sets each component to 1.0</span> |
| vec3 rgb = vec3(color); <span class="comment">// drop the 4th component</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To initialize the diagonal of a matrix with all other elements set to zero:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat2(<span class="predefined-type">float</span>) |
| mat3(<span class="predefined-type">float</span>) |
| mat4(<span class="predefined-type">float</span>)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>That is, <em>result[i][j]</em> is set to the <em>float</em> argument for all \(i |
| = j\) and set to 0 for all \(i \neq j\).</p> |
| </div> |
| <div class="paragraph"> |
| <p>To initialize a matrix by specifying vectors or scalars, the components are |
| assigned to the matrix elements in column-major order.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat2(vec2, vec2); <span class="comment">// one column per argument</span> |
| mat3(vec3, vec3, vec3); <span class="comment">// one column per argument</span> |
| mat4(vec4, vec4, vec4, vec4); <span class="comment">// one column per argument</span> |
| mat3x2(vec2, vec2, vec2); <span class="comment">// one column per argument</span> |
| dmat2(dvec2, dvec2); |
| dmat3(dvec3, dvec3, dvec3); |
| dmat4(dvec4, dvec4, dvec4, dvec4); |
| mat2(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// second column</span> |
| mat3(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// second column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// third column</span> |
| mat4(<span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// first column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// second column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="comment">// third column</span> |
| <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>, <span class="predefined-type">float</span>); <span class="comment">// fourth column</span> |
| mat2x3(vec2, <span class="predefined-type">float</span>, <span class="comment">// first column</span> |
| vec2, <span class="predefined-type">float</span>); <span class="comment">// second column</span> |
| dmat2x4(dvec3, <span class="predefined-type">double</span>, <span class="comment">// first column</span> |
| <span class="predefined-type">double</span>, dvec3); <span class="comment">// second column</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A wide range of other possibilities exist, to construct a matrix from |
| vectors and scalars, as long as enough components are present to initialize |
| the matrix. |
| To construct a matrix from a matrix:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat3x3(mat4x4); <span class="comment">// takes the upper-left 3x3 of the mat4x4</span> |
| mat2x3(mat4x2); <span class="comment">// takes the upper-left 2x2 of the mat4x4, last row is 0,0</span> |
| mat4x4(mat3x3); <span class="comment">// puts the mat3x3 in the upper-left, sets the lower right</span> |
| <span class="comment">// component to 1, and the rest to 0</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="structure-constructors">5.4.3. Structure Constructors</h4> |
| <div class="paragraph"> |
| <p>Once a structure is defined, and its type is given a name, a constructor is |
| available with the same name to construct instances of that structure. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">struct</span> light { |
| <span class="predefined-type">float</span> intensity; |
| vec3 position; |
| }; |
| |
| light lightVar = light(<span class="float">3</span><span class="float">.0</span>, vec3(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>));</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The arguments to the constructor will be used to set the structure’s |
| members, in order, using one argument per member. |
| Each argument must be the same type as the member it |
| sets, or be a type that can be converted to the member’s type according to |
| section “<a href="#implicit-conversions">Implicit Conversions</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Structure constructors can be used as initializers or in expressions.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="array-constructors">5.4.4. Array Constructors</h4> |
| <div class="paragraph"> |
| <p>Array types can also be used as constructor names, which can then be used in |
| expressions or initializers. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">float</span> c[<span class="integer">3</span>] = <span class="predefined-type">float</span>[<span class="integer">3</span>](<span class="float">5</span><span class="float">.0</span>, <span class="float">7</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); |
| <span class="directive">const</span> <span class="predefined-type">float</span> d[<span class="integer">3</span>] = <span class="predefined-type">float</span>[](<span class="float">5</span><span class="float">.0</span>, <span class="float">7</span><span class="float">.2</span>, <span class="float">1</span><span class="float">.1</span>); |
| |
| <span class="predefined-type">float</span> g; |
| ... |
| <span class="predefined-type">float</span> a[<span class="integer">5</span>] = <span class="predefined-type">float</span>[<span class="integer">5</span>](g, <span class="integer">1</span>, g, <span class="float">2</span><span class="float">.3</span>, g); |
| <span class="predefined-type">float</span> b[<span class="integer">3</span>]; |
| |
| b = <span class="predefined-type">float</span>[<span class="integer">3</span>](g, g + <span class="float">1</span><span class="float">.0</span>, g + <span class="float">2</span><span class="float">.0</span>);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>There must be exactly the same number of arguments as the size of the array |
| being constructed. |
| If no size is present in the constructor, then the array is explicitly sized |
| to the number of arguments provided. |
| The arguments are assigned in order, starting at element 0, to the elements |
| of the constructed array. |
| Each argument must be the same type as the element type of the |
| array, or be |
| a type that can be converted to the element type of the array according to |
| “<a href="#implicit-conversions">Implicit Conversions</a>”.</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’s first argument must be a texture type</p> |
| </li> |
| <li> |
| <p>the constructor’s second argument must be a scalar of type <strong>sampler</strong> |
| or <strong>samplerShadow</strong></p> |
| </li> |
| <li> |
| <p>the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) |
| of the texture type must match that of the constructed type |
| (that is, the suffixes of the type of the first argument and the |
| type of the constructor will be spelled the same way)</p> |
| </li> |
| <li> |
| <p>there is no control flow construct (e.g., <code>?:</code>) that consumes any sampler type</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Note: Shadow mismatches are allowed between constructors and the second argument. |
| Texture-combined non-shadow samplers can be constructed from <strong>samplerShadow</strong> and |
| texture-combined shadow samplers can be constructed from <strong>sampler</strong>.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="vector-components">5.5. Vector and Scalar Components and Length</h3> |
| <div class="paragraph"> |
| <p>The names of the components of a vector |
| or scalar |
| are denoted by a single letter. |
| As a notational convenience, several letters are associated with each |
| component based on common usage of position, color or texture coordinate |
| vectors. |
| The individual components can be selected by following the variable name |
| with period (<strong>.</strong>) and then the component name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The component names supported are:</p> |
| </div> |
| <table class="tableblock frame-all grid-all fit-content"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ x, y, z, w }</em></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent points or normals</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ r, g, b, a }</em></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent colors</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><em>{ s, t, p, q }</em></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Useful when accessing vectors that represent texture coordinates</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The component names <em>x</em>, <em>r</em>, and <em>s</em> are, for example, synonyms for the |
| same (first) component in a vector. |
| They are also the names of the only component in a scalar.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that the third component of the texture coordinate set |
| has been renamed <em>p</em> so as to avoid the confusion with <em>r</em> (for |
| red) in a color.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Accessing components beyond those declared for the type is |
| a compile-time error so, for example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec2 pos; |
| <span class="predefined-type">float</span> height; |
| pos.x <span class="comment">// is legal</span> |
| pos.z <span class="comment">// is illegal</span> |
| height.x <span class="comment">// is legal</span> |
| height.y <span class="comment">// is illegal</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The component selection syntax allows multiple components to be selected by |
| appending their names (from the same name set) after the period (<strong>.</strong>).</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 v4; |
| v4.rgba; <span class="comment">// is a vec4 and the same as just using v4,</span> |
| v4.rgb; <span class="comment">// is a vec3,</span> |
| v4.b; <span class="comment">// is a float,</span> |
| v4.xy; <span class="comment">// is a vec2,</span> |
| v4.xgba; <span class="comment">// is illegal - the component names do not come from the same set</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>No more than 4 components can be selected.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 v4; |
| v4.xyzwxy; <span class="comment">// is illegal since it has 6 components</span> |
| (v4.xyzwxy).xy; <span class="comment">// is illegal since the intermediate value has 6</span> |
| components</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The order of the components can be different to swizzle them, or replicated:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 pos = vec4(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>); |
| vec4 swiz = pos.wzyx; <span class="comment">// swiz = (4.0, 3.0, 2.0, 1.0)</span> |
| vec4 dup = pos.xxyy; <span class="comment">// dup = (1.0, 1.0, 2.0, 2.0)</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This notation is more concise than the constructor syntax. |
| To form an r-value, it can be applied to any expression that results in a |
| vector or scalar r-value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The component group notation can occur on the left hand side of an |
| expression.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 pos = vec4(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>); |
| pos.xw = vec2(<span class="float">5</span><span class="float">.0</span>, <span class="float">6</span><span class="float">.0</span>); <span class="comment">// pos = (5.0, 2.0, 3.0, 6.0)</span> |
| pos.wx = vec2(<span class="float">7</span><span class="float">.0</span>, <span class="float">8</span><span class="float">.0</span>); <span class="comment">// pos = (8.0, 2.0, 3.0, 7.0)</span> |
| pos.xx = vec2(<span class="float">3</span><span class="float">.0</span>, <span class="float">4</span><span class="float">.0</span>); <span class="comment">// illegal - 'x' used twice</span> |
| pos.xy = vec3(<span class="float">1</span><span class="float">.0</span>, <span class="float">2</span><span class="float">.0</span>, <span class="float">3</span><span class="float">.0</span>); <span class="comment">// illegal - mismatch between vec2 and vec3</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To form an l-value, swizzling must further be applied to an l-value and |
| contain no duplicate components. It results in an l-value of scalar or |
| vector type, depending on number of components specified.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Array subscripting syntax can also be applied to vectors (but not to |
| scalars) to provide numeric indexing. |
| So in</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 pos;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><em>pos[2]</em> refers to the third element of <em>pos</em> and is equivalent to <em>pos.z</em>. |
| This allows variable indexing into a vector, as well as a generic way of |
| accessing components. |
| Any integer expression can be used as the subscript. |
| The first component is at index zero. |
| Reading from or writing to a vector using a constant integral expression |
| with a value that is negative or greater than or equal to the size of the |
| vector results in a compile-time error. |
| When indexing with non-constant expressions, behavior is undefined if the |
| index is negative, or greater than or equal to the size of the vector.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>length</strong>() method may be applied to vectors (but not scalars). |
| The result is the number of components in the vector. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec3 v; |
| <span class="directive">const</span> <span class="predefined-type">int</span> L = v.length();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>sets the constant <em>L</em> to 3. |
| The type returned by <strong>.length</strong>() on a vector is <strong>int</strong>, and the value |
| returned is a constant expression.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="matrix-components">5.6. Matrix Components</h3> |
| <div class="paragraph"> |
| <p>The components of a matrix can be accessed using array subscripting syntax. |
| Applying a single subscript to a matrix treats the matrix as an array of |
| column vectors, and selects a single column, whose type is a vector of the |
| same size as the (column size of the) matrix. |
| The leftmost column is column 0. |
| A second subscript would then operate on the resulting vector, as defined |
| earlier for vectors. |
| Hence, two subscripts select a column and then a row.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat4 m; |
| m[<span class="integer">1</span>] = vec4(<span class="float">2</span><span class="float">.0</span>); <span class="comment">// sets the second column to all 2.0</span> |
| m[<span class="integer">0</span>][<span class="integer">0</span>] = <span class="float">1</span><span class="float">.0</span>; <span class="comment">// sets the upper left element to 1.0</span> |
| m[<span class="integer">2</span>][<span class="integer">3</span>] = <span class="float">2</span><span class="float">.0</span>; <span class="comment">// sets the 4th element of the third column to 2.0</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Behavior is undefined when accessing a component outside the bounds of a |
| matrix with a non-constant expression. |
| It is a compile-time error to access a matrix with a constant expression |
| that is outside the bounds of the matrix.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>length</strong>() method may be applied to matrices. |
| The result is the number of columns of the matrix. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat3x4 v; |
| <span class="directive">const</span> <span class="predefined-type">int</span> L = v.length();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>sets the constant <em>L</em> to 3. |
| The type returned by <strong>.length</strong>() on a matrix is <strong>int</strong>, and the value |
| returned is a constant expression.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="structure-and-array-operations">5.7. Structure and Array Operations</h3> |
| <div class="paragraph"> |
| <p>The members of a structure and the <strong>length</strong>() method of an array are |
| selected using the period (<strong>.</strong>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>In total, only the following operators are allowed to operate on arrays and |
| structures as whole entities:</p> |
| </div> |
| <table class="tableblock frame-all grid-all fit-content"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">field selector</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>.</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">equality</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>==</strong> <strong>!=</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">assignment</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>=</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Ternary operator</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>?:</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Sequence operator</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>,</strong></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">indexing (arrays only)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><strong>[</strong> <strong>]</strong></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The equality operators and assignment operator are only allowed if the two |
| operands are same size and type. |
| The operands cannot contain any opaque types. |
| Structure types must be of the same declared structure. |
| Both array operands must be |
| explicitly |
| sized. |
| When using the equality operators, two structures are equal if and only if |
| all the members are component-wise equal, and two arrays are equal if and |
| only if all the elements are element-wise equal.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Array elements are accessed using the array subscript operator (<strong>[ ]</strong>). |
| An example of accessing an array element is</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">diffuseColor += lightIntensity[<span class="integer">3</span>] * NdotL;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Array indices start at zero. |
| Array elements are accessed using an expression whose type is <strong>int</strong> or |
| <strong>uint</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Behavior is undefined if a shader subscripts an array with an index less |
| than 0 or greater than or equal to the size the array was declared with.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Arrays can also be accessed with the method operator (<strong>.</strong>) and the <strong>length</strong> |
| method to query the size of the array:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">lightIntensity.length() <span class="comment">// return the size of the array</span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="assignments">5.8. Assignments</h3> |
| <div class="paragraph"> |
| <p>Assignments of values to variable names are done with the assignment |
| operator (<strong>=</strong>):</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><em>lvalue-expression</em> = <em>rvalue-expression</em></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>lvalue-expression</em> evaluates to an l-value. |
| The assignment operator stores the value of <em>rvalue-expression</em> into the |
| l-value and returns an r-value with the type and precision of |
| <em>lvalue-expression</em>. |
| The <em>lvalue-expression</em> and <em>rvalue-expression</em> must have the same |
| type, or the expression must have a type in the table in section |
| “<a href="#implicit-conversions">Implicit Conversions</a>” that converts to the type |
| of <em>lvalue-expression</em>, in which case an implicit conversion will be done on |
| the <em>rvalue-expression</em> before the assignment is done. |
| Any other desired type-conversions must be specified explicitly via a |
| constructor. |
| It is a compile-time error if the l-value is not writable. |
| Variables that are built-in types, entire structures or arrays, structure |
| members, l-values with the field selector (<strong>.</strong>) applied to select components |
| or swizzles without repeated fields, l-values within parentheses, and |
| l-values dereferenced with the array subscript operator (<strong>[ ]</strong>) are all |
| l-values. |
| Other binary or unary expressions, function names, swizzles with repeated |
| fields, and constants cannot be l-values. |
| The ternary operator (<strong>?:</strong>) is also not allowed as an l-value. |
| Using an incorrect expression as an l-value results in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Expressions on the left of an assignment are evaluated before expressions on |
| the right of the assignment.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The other assignment operators are</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>add into (<strong>+=</strong>)</p> |
| </li> |
| <li> |
| <p>subtract from (<strong>-=</strong>)</p> |
| </li> |
| <li> |
| <p>multiply into (<strong>*=</strong>)</p> |
| </li> |
| <li> |
| <p>divide into (<strong>/=</strong>)</p> |
| </li> |
| <li> |
| <p>modulus into (<strong>%=</strong>)</p> |
| </li> |
| <li> |
| <p>left shift by (<strong><<=</strong>)</p> |
| </li> |
| <li> |
| <p>right shift by (<strong>>>=</strong>)</p> |
| </li> |
| <li> |
| <p>and into (<strong>&=</strong>)</p> |
| </li> |
| <li> |
| <p>inclusive-or into (<strong>|=</strong>)</p> |
| </li> |
| <li> |
| <p>exclusive-or into (<strong>^=</strong>)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>where the general expression</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><em>lvalue</em> <em>op</em>= <em>expression</em></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>is equivalent to</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"></dt> |
| <dd> |
| <p><em>lvalue</em> = <em>lvalue</em> <em>op</em> <em>expression</em></p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>lvalue</em> is the value returned by <em>lvalue-expression</em>, <em>op</em> is as |
| described below, and the <em>lvalue-expression</em> and <em>expression</em> must satisfy |
| the semantic requirements of both <em>op</em> and equals (<strong>=</strong>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Reading a variable before writing (or initializing) it is legal, however the |
| value is undefined.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="expressions">5.9. Expressions</h3> |
| <div class="paragraph"> |
| <p>Expressions in the shading language are built from the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Constants of type <strong>bool</strong>, all integral types, all floating-point types, |
| all vector types, and all matrix types.</p> |
| </li> |
| <li> |
| <p>Constructors of all types.</p> |
| </li> |
| <li> |
| <p>Variable names of all types.</p> |
| </li> |
| <li> |
| <p>An array, vector, or matrix expression with the <strong>length</strong>() method |
| applied.</p> |
| </li> |
| <li> |
| <p>Subscripted arrays.</p> |
| </li> |
| <li> |
| <p>Function calls that return values. |
| In some cases, function calls returning <strong>void</strong> are also allowed in |
| expressions as specified below.</p> |
| </li> |
| <li> |
| <p>Component field selectors and array subscript results.</p> |
| </li> |
| <li> |
| <p>Parenthesized expressions. |
| Any expression, including expressions with void type can be |
| parenthesized. |
| Parentheses can be used to group operations. |
| Operations within parentheses are done before operations across |
| parentheses.</p> |
| </li> |
| <li> |
| <p>The arithmetic binary operators add (<strong>+</strong>), subtract (<strong>-</strong>), multiply |
| (<strong>*</strong>), and divide (<strong>/</strong>) operate on integer and floating-point scalars, |
| vectors, and matrices. |
| If the fundamental types in the operands do not match, then the |
| conversions from “<a href="#implicit-conversions">Implicit Conversions</a>” are |
| applied to create matching types. |
| All arithmetic binary operators result in the same fundamental type |
| (signed integer, unsigned integer, single-precision floating-point, or |
| double-precision floating-point) as the operands they operate on, after |
| operand type conversion. |
| After conversion, the following cases are valid</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The two operands are scalars. |
| In this case the operation is applied, resulting in a scalar.</p> |
| </li> |
| <li> |
| <p>One operand is a scalar, and the other is a vector or matrix. |
| In this case, the scalar operation is applied independently to each |
| component of the vector or matrix, resulting in the same size vector or |
| matrix.</p> |
| </li> |
| <li> |
| <p>The two operands are vectors of the same size. |
| In this case, the operation is done component-wise resulting in the |
| same size vector.</p> |
| </li> |
| <li> |
| <p>The operator is add (<strong>+</strong>), subtract (<strong>-</strong>), or divide (<strong>/</strong>), and the |
| operands are matrices with the same number of rows and the same number |
| of columns. |
| In this case, the operation is done component-wise resulting in the |
| same size matrix.</p> |
| </li> |
| <li> |
| <p>The operator is multiply (<strong>*</strong>), where both operands are matrices or one |
| operand is a vector and the other a matrix. |
| A right vector operand is treated as a column vector and a left vector |
| operand as a row vector. |
| In all these cases, it is required that the number of columns of the |
| left operand is equal to the number of rows of the right operand. |
| Then, the multiply (<strong>*</strong>) operation does a linear algebraic multiply, |
| yielding an object that has the same number of rows as the left operand |
| and the same number of columns as the right operand. |
| “<a href="#vector-and-matrix-operations">Vector and Matrix Operations</a>” |
| explains in more detail how vectors and matrices are operated on.</p> |
| <div class="openblock"> |
| <div class="content"> |
| <div class="paragraph"> |
| <p>All other cases result in a compile-time error.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Use the built-in functions <strong>dot</strong>, <strong>cross</strong>, <strong>matrixCompMult</strong>, and |
| <strong>outerProduct</strong>, to get, respectively, vector dot product, vector cross |
| product, matrix component-wise multiplication, and the matrix product of a |
| column vector times a row vector.</p> |
| </div> |
| </div> |
| </div> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>The operator modulus (<strong>%</strong>) operates on signed or unsigned integers or |
| integer vectors. |
| If the fundamental types in the operands do not match, then the |
| conversions from “<a href="#implicit-conversions">Implicit Conversions</a>” are |
| applied to create matching types. |
| The operands cannot be vectors of differing size; this is |
| a compile-time error. |
| If one operand is a scalar and the other vector, then the scalar is |
| applied component-wise to the vector, resulting in the same type as the |
| vector. |
| If both are vectors of the same size, the result is computed |
| component-wise. |
| The resulting value is undefined for any component computed with a |
| second operand that is zero, while results for other components with |
| non-zero second operands remain defined. |
| If both operands are non-negative, then the remainder is non-negative. |
| Results are undefined if one or both operands are negative. |
| The operator modulus (<strong>%</strong>) is not defined for any other data types |
| (non-integer types).</p> |
| </li> |
| <li> |
| <p>The arithmetic unary operators negate (<strong>-</strong>), post- and pre-increment and |
| decrement (<strong>--</strong> and <strong>++</strong>) operate on integer or floating-point values |
| (including vectors and matrices). |
| All unary operators work component-wise on their operands. |
| These result with the same type they operated on. |
| For post- and pre-increment and decrement, the expression must be a writable |
| l-value. |
| Pre-increment and pre-decrement add or subtract 1 or 1.0 to the contents |
| of the expression they operate on, and the value of the pre-increment or |
| pre-decrement expression is the resulting value of that modification. |
| Post-increment and post-decrement expressions add or subtract 1 or 1.0 |
| to the contents of the expression they operate on, but the resulting |
| expression has the expression’s value before the post-increment or |
| post-decrement was executed.</p> |
| </li> |
| <li> |
| <p>The relational operators greater than (<strong>></strong>), less than (<strong><</strong>), greater |
| than or equal (<strong>>=</strong>), and less than or equal (<strong><=</strong>) operate only on |
| scalar integer and scalar floating-point expressions. |
| The result is scalar Boolean. |
| Either the operands' types must match, or the conversions from section |
| “<a href="#implicit-conversions">Implicit Conversions</a>” will be applied to |
| obtain matching types. |
| To do component-wise relational comparisons on vectors, use the built-in |
| functions <strong>lessThan</strong>, <strong>lessThanEqual</strong>, <strong>greaterThan</strong>, and |
| <strong>greaterThanEqual.</strong></p> |
| </li> |
| <li> |
| <p>The equality operators <strong>equal</strong> (<strong>==</strong>), and not equal (<strong>!=</strong>) operate on |
| all types except opaque types, aggregates that contain opaque types, |
| subroutine uniforms, and aggregates that contain subroutine uniforms. |
| They result in a scalar Boolean. |
| If the operand types do not match, then there must be a conversion from |
| “<a href="#implicit-conversions">Implicit Conversions</a>” applied to one operand |
| that can make them match, in which case this conversion is done. |
| For vectors, matrices, structures, and arrays, all components, members, |
| or elements of one operand must equal the corresponding components, |
| members, or elements in the other operand for the operands to be |
| considered equal. |
| To get a vector of component-wise equality results for vectors, use the |
| built-in functions <strong>equal</strong> and <strong>notEqual</strong>.</p> |
| </li> |
| <li> |
| <p>The logical binary operators and (<strong>&&</strong>), or (<strong>||</strong>), and exclusive or |
| (<strong>^^</strong>) operate only on two Boolean expressions and result in a Boolean |
| expression. |
| And (<strong>&&</strong>) will only evaluate the right hand operand if the left hand |
| operand evaluated to <strong>true</strong>. |
| Or (<strong>||</strong>) will only evaluate the right hand operand if the left hand |
| operand evaluated to <strong>false</strong>. |
| Exclusive or (<strong>^^</strong>) will always evaluate both operands.</p> |
| </li> |
| <li> |
| <p>The logical unary operator not (<strong>!</strong>). |
| It operates only on a Boolean expression and results in a Boolean |
| expression. |
| To operate on a vector, use the built-in function <strong>not</strong>.</p> |
| </li> |
| <li> |
| <p>The sequence (<strong>,</strong>) operator that operates on expressions by returning |
| the type and value of the right-most expression in a comma separated |
| list of expressions. |
| All expressions are evaluated, in order, from left to right. |
| The operands to the sequence operator may have <strong>void</strong> type. |
| Opaque types cannot be used with the sequence (,) operator.</p> |
| </li> |
| <li> |
| <p>The ternary selection operator (<strong>?:</strong>). |
| It operates on three expressions (<em>exp1</em> <strong>?</strong> <em>exp2</em> <strong>:</strong> <em>exp3</em>). |
| This operator evaluates the first expression, which must result in a |
| scalar Boolean. |
| If the result is true, it selects to evaluate the second expression, |
| otherwise it selects to evaluate the third expression. |
| Only one of the second and third expressions is evaluated. |
| The second and third expressions cannot be opaque types, |
| or there will be a compile-time error. |
| Otherwise, |
| the second and third expressions can be any type, including <strong>void</strong>, as |
| long their types match, or there is a conversion in section |
| “<a href="#implicit-conversions">Implicit Conversions</a>” that can be applied to |
| one of the expressions to make their types match. |
| This resulting matching type is the type of the entire expression.</p> |
| </li> |
| <li> |
| <p>The one’s complement operator (<strong>~</strong>). |
| The operand must be of type signed or unsigned integer or integer |
| vector, and the result is the one’s complement of its operand; each bit |
| of each component is complemented, including any sign bits.</p> |
| </li> |
| <li> |
| <p>The shift operators (<strong><<</strong>) and (<strong>>></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’s base type. |
| The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted |
| by E2 bits. |
| The value of E1 >> 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>&</strong>), exclusive-or (<strong>^</strong>), and inclusive-or |
| (<strong>|</strong>). |
| The operands must be of type signed or unsigned integers or integer |
| vectors. |
| The operands cannot be vectors of differing size; this is a compile-time error. |
| If one operand is a scalar and the other a vector, the scalar is applied |
| component-wise to the vector, resulting in the same type as the vector. |
| If the fundamental types in the operands do not match, then the |
| conversions from “<a href="#implicit-conversions">Implicit Conversions</a>” are |
| applied to create matching types, and this will be the resulting |
| fundamental type. |
| For and (<strong>&</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 |
| “<a href="#shading-language-grammar">Shading Language Grammar</a>”.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="vector-and-matrix-operations">5.10. Vector and Matrix Operations</h3> |
| <div class="paragraph"> |
| <p>With a few exceptions, operations are component-wise. |
| Usually, when an operator operates on a vector or matrix, it is operating |
| independently on each component of the vector or matrix, in a component-wise |
| fashion. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u; |
| <span class="predefined-type">float</span> f; |
| v = u + f;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will be equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">v.x = u.x + f; |
| v.y = u.y + f; |
| v.z = u.z + f;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>And</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u, w; |
| w = v + u;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>will be equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">w.x = v.x + u.x; |
| w.y = v.y + u.y; |
| w.z = v.z + u.z;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>and likewise for most operators and all integer and floating-point vector |
| and matrix types. |
| The exceptions are matrix multiplied by vector, vector multiplied by matrix, |
| and matrix multiplied by matrix. |
| These do not operate component-wise, but rather perform the correct linear |
| algebraic multiply.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec3 v, u; |
| mat3 m; |
| u = v * m;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">u.x = dot(v, m[<span class="integer">0</span>]); <span class="comment">// m[0] is the left column of m</span> |
| u.y = dot(v, m[<span class="integer">1</span>]); <span class="comment">// dot(a,b) is the inner (dot) product of a and b</span> |
| u.z = dot(v, m[<span class="integer">2</span>]);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>And</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">u = m * v;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">u.x = m[<span class="integer">0</span>].x * v.x + m[<span class="integer">1</span>].x * v.y + m[<span class="integer">2</span>].x * v.z; |
| u.y = m[<span class="integer">0</span>].y * v.x + m[<span class="integer">1</span>].y * v.y + m[<span class="integer">2</span>].y * v.z; |
| u.z = m[<span class="integer">0</span>].z * v.x + m[<span class="integer">1</span>].z * v.y + m[<span class="integer">2</span>].z * v.z;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>And</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">mat3 m, n, r; |
| r = m * n;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>is equivalent to</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">r[<span class="integer">0</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">0</span>].z; |
| r[<span class="integer">1</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">1</span>].z; |
| r[<span class="integer">2</span>].x = m[<span class="integer">0</span>].x * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].x * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].x * n[<span class="integer">2</span>].z; |
| r[<span class="integer">0</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">0</span>].z; |
| r[<span class="integer">1</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">1</span>].z; |
| r[<span class="integer">2</span>].y = m[<span class="integer">0</span>].y * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].y * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].y * n[<span class="integer">2</span>].z; |
| r[<span class="integer">0</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">0</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">0</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">0</span>].z; |
| r[<span class="integer">1</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">1</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">1</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">1</span>].z; |
| r[<span class="integer">2</span>].z = m[<span class="integer">0</span>].z * n[<span class="integer">2</span>].x + m[<span class="integer">1</span>].z * n[<span class="integer">2</span>].y + m[<span class="integer">2</span>].z * n[<span class="integer">2</span>].z;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>and similarly for other sizes of vectors and matrices.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="out-of-bounds-accesses">5.11. Out-of-Bounds Accesses</h3> |
| <div class="paragraph"> |
| <p>In the subsections described above for array, vector, matrix and structure |
| accesses, any out-of-bounds access produced undefined behavior. |
| However, if robust buffer access is enabled via the API, such |
| accesses will be bound within the memory extent of the active program. |
| It will not be possible to access memory from other programs, and accesses |
| will not result in abnormal program termination. |
| Out-of-bounds reads return undefined values, which include values from other |
| variables of the active program or zero. |
| Out-of-bounds writes may be discarded or overwrite other variables of the |
| active program, depending on the value of the computed index and how this |
| relates to the extent of the active program’s memory. |
| Applications that require defined behavior for out-of-bounds accesses should |
| range check all computed indices before dereferencing an array.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="specialization-constant-operations">5.12. Specialization-Constant Operations</h3> |
| <div class="paragraph"> |
| <p>Specialization-constant operations are only available when targeting SPIR-V.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Only some operations discussed in this section may be applied to a |
| specialization constant and still yield a result that is a specialization |
| constant. |
| The operations that do so are listed below. |
| When a specialization constant is operated on with one of these operators |
| and with another constant or specialization constant, the result is |
| implicitly a specialization constant.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>int</strong>(), <strong>uint</strong>(), and <strong>bool</strong>() constructors for type conversions from |
| any of the following types to any of the following types:</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>int</strong></p> |
| </li> |
| <li> |
| <p><strong>uint</strong></p> |
| </li> |
| <li> |
| <p><strong>bool</strong></p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>vector versions of the above conversion constructors</p> |
| </li> |
| <li> |
| <p>allowed implicit conversions of the above</p> |
| </li> |
| <li> |
| <p>swizzles (e.g. <code>foo.yx</code>)</p> |
| </li> |
| <li> |
| <p>the following when applied to integer or unsigned integer types:</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>unary negative (<strong>-</strong>)</p> |
| </li> |
| <li> |
| <p>binary operations (<strong>+</strong>, <strong>-</strong>, <strong>*</strong>, <strong>/</strong>, <strong>%</strong>)</p> |
| </li> |
| <li> |
| <p>shift (<strong><<</strong>, <strong>>></strong>)</p> |
| </li> |
| <li> |
| <p>bitwise operations (<strong>&</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>></strong>, <strong>>=</strong>, <strong><</strong>, <strong>⇐</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>&&</strong>, <strong>||</strong>, <strong>^^</strong>)</p> |
| </li> |
| <li> |
| <p>comparison (<strong>==</strong>, <strong>!=</strong>)</p> |
| </li> |
| </ul> |
| </div> |
| </li> |
| <li> |
| <p>the ternary operator (<strong>?:</strong>)</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="statements-and-structure">6. Statements and Structure</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The fundamental building blocks of the OpenGL Shading Language are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>statements and declarations</p> |
| </li> |
| <li> |
| <p>function definitions</p> |
| </li> |
| <li> |
| <p>selection (<strong>if</strong>-<strong>else</strong> and <strong>switch</strong>-<strong>case</strong>-<strong>default</strong>)</p> |
| </li> |
| <li> |
| <p>iteration (<strong>for</strong>, <strong>while</strong>, and <strong>do</strong>-<strong>while</strong>)</p> |
| </li> |
| <li> |
| <p>jumps (<strong>discard</strong>, <strong>return</strong>, <strong>break</strong>, and <strong>continue</strong>)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The overall structure of a shader is as follows</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>translation-unit</em> : </dt> |
| <dd> |
| <p><em>global-declaration</em><br> |
| <em>translation-unit</em> <em>global-declaration</em></p> |
| </dd> |
| <dt class="hdlist1"><em>global-declaration</em> : </dt> |
| <dd> |
| <p><em>function-definition</em><br> |
| <em>declaration</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>That is, a shader is a sequence of declarations and function bodies. |
| Function bodies are defined as</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>function-definition</em> : </dt> |
| <dd> |
| <p><em>function-prototype</em> <strong>{</strong> <em>statement-list</em> <strong>}</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>statement-list</em> : </dt> |
| <dd> |
| <p><em>statement</em><br> |
| <em>statement-list</em> <em>statement</em></p> |
| </dd> |
| <dt class="hdlist1"><em>statement</em> : </dt> |
| <dd> |
| <p><em>compound-statement</em><br> |
| <em>simple-statement</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Curly braces are used to group sequences of statements into compound |
| statements.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>compound-statement</em> : </dt> |
| <dd> |
| <p><strong>{</strong> <em>statement-list</em> <strong>}</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>simple-statement</em> : </dt> |
| <dd> |
| <p><em>declaration-statement</em><br> |
| <em>expression-statement</em><br> |
| <em>selection-statement</em><br> |
| <em>iteration-statement</em><br> |
| <em>jump-statement</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Simple declaration, expression, and jump statements end in a semi-colon.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This above is slightly simplified, and the complete grammar specified in |
| “<a href="#shading-language-grammar">Shading Language Grammar</a>” should be used as |
| the definitive specification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Declarations and expressions have already been discussed.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="function-definitions">6.1. Function Definitions</h3> |
| <div class="paragraph"> |
| <p>As indicated by the grammar above, a valid shader is a sequence of global |
| declarations and function definitions. |
| A function is declared as the following example shows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// prototype</span> |
| returnType functionName (type0 arg0, type1 arg1, ..., typen argn);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>and a function is defined like</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// definition</span> |
| returnType functionName (type0 arg0, type1 arg1, ..., typen argn) |
| { |
| <span class="comment">// do some computation</span> |
| <span class="keyword">return</span> returnValue; |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>where <em>returnType</em> must be present and cannot be void, or:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> functionName (type0 arg0, type1 arg1, ..., typen argn) |
| { |
| <span class="comment">// do some computation</span> |
| <span class="keyword">return</span>; <span class="comment">// optional</span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If the type of <em>returnValue</em> does not match <em>returnType</em>, there must be an |
| implicit conversion in “<a href="#implicit-conversions">Implicit Conversions</a>” |
| that converts the type of <em>returnValue</em> to <em>returnType</em>, or a compile-time |
| error will result.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Each of the <em>typeN</em> must include a type and can optionally include parameter |
| qualifiers. |
| The formal argument names (<em>args</em> above) in the declarations are optional |
| for both the declaration and definition forms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A function is called by using its name followed by a list of arguments in |
| parentheses.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Arrays are allowed as arguments and as the return type. |
| In both cases, the array must be |
| explicitly |
| sized. |
| An array is passed or returned by using just its name, without brackets, and |
| the size of the array must match the size specified in the function’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 “<a href="#shading-language-grammar">Shading Language Grammar</a>” 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 “( )” is declared. |
| The idiom “(<strong>void</strong>)” as a parameter list is provided for convenience.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Function names can be overloaded. |
| The same function name can be used for multiple functions, as long as the |
| parameter types differ. |
| If a function name is declared twice with the same parameter types, then the |
| return types and all qualifiers must also match, and it is the same function |
| being declared.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">vec4 f(in vec4 x, out vec4 y); <span class="comment">// (A)</span> |
| vec4 f(in vec4 x, out uvec4 y); <span class="comment">// (B) okay, different argument type</span> |
| vec4 f(in ivec4 x, out dvec4 y); <span class="comment">// (C) okay, different argument type</span> |
| <span class="predefined-type">int</span> f(in vec4 x, out vec4 y); <span class="comment">// error, only return type differs</span> |
| vec4 f(in vec4 x, in vec4 y); <span class="comment">// error, only qualifier differs</span> |
| vec4 f(<span class="directive">const</span> in vec4 x, out vec4 y); <span class="comment">// error, only qualifier differs</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When function calls are resolved, an exact type match for all the arguments |
| is sought. |
| If an exact match is found, all other functions are ignored, and the exact |
| match is used. |
| If no exact match is found, then the implicit conversions in section |
| “<a href="#implicit-conversions">Implicit Conversions</a>” will be applied to find a |
| match. |
| Mismatched types on input parameters (<strong>in</strong> or <strong>inout</strong> or default) <strong>must</strong> |
| have a conversion from the calling argument type to the formal parameter |
| type. |
| Mismatched types on output parameters (<strong>out</strong> or <strong>inout</strong>) must have a |
| conversion from the formal parameter type to the calling argument type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If implicit conversions can be used to find more than one matching function, |
| a single best-matching function is sought. |
| To determine a best match, the conversions between calling argument and |
| formal parameter types are compared for each function argument and pair of |
| matching functions. |
| After these comparisons are performed, each pair of matching functions are |
| compared. |
| A function declaration <em>A</em> is considered a better match than function |
| declaration <em>B</em> if</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>for at least one function argument, the conversion for that argument in |
| <em>A</em> is better than the corresponding conversion in <em>B</em>; and</p> |
| </li> |
| <li> |
| <p>there is no function argument for which the conversion in <em>B</em> is better |
| than the corresponding conversion in <em>A</em>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If a single function declaration is considered a better match than every |
| other matching function declaration, it will be used. |
| Otherwise, a compile-time semantic error for an ambiguous overloaded |
| function call occurs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To determine whether the conversion for a single argument in one match is |
| better than that for another match, the following rules are applied, in |
| order:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>An exact match is better than a match involving any implicit conversion.</p> |
| </li> |
| <li> |
| <p>A match involving an implicit conversion from <strong>float</strong> to <strong>double</strong> is |
| better than a match involving any other implicit conversion.</p> |
| </li> |
| <li> |
| <p>A match involving an implicit conversion from either <strong>int</strong> or <strong>uint</strong> to |
| <strong>float</strong> is better than a match involving an implicit conversion from |
| either <strong>int</strong> or <strong>uint</strong> to <strong>double</strong>.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>If none of the rules above apply to a particular pair of conversions, |
| neither conversion is considered better than the other.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the example function prototypes (A), (B), and © above, the following |
| examples show how the rules apply to different sets of calling argument |
| types:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">f(vec4, vec4) <span class="comment">// exact match of vec4 f(in vec4 x, out vec4 y)</span> |
| f(vec4, uvec4) <span class="comment">// exact match of vec4 f(in vec4 x, out uvec4 y)</span> |
| f(vec4, ivec4) <span class="comment">// matched to vec4 f(in vec4 x, out vec4 y)</span> |
| <span class="comment">// (C) not relevant, can't convert vec4 to</span> |
| <span class="comment">// ivec4. (A) better than (B) for 2nd</span> |
| <span class="comment">// argument (rule 3), same on first argument.</span> |
| f(ivec4, vec4); <span class="comment">// NOT matched. All three match by implicit</span> |
| <span class="comment">// conversion. (C) is better than (A) and (B)</span> |
| <span class="comment">// on the first argument. (A) is better than</span> |
| <span class="comment">// (B) and (C).</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>User-defined functions can have multiple declarations, but only one |
| definition.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A shader can redefine built-in functions. |
| If a built-in function is redeclared in a shader (i.e., a prototype is |
| visible) before a call to it, then the linker will only attempt to resolve |
| that call within the set of shaders that are linked with it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function <em>main</em> is used as the entry point to a shader executable. |
| A shader need not contain a function named <em>main</em>, but one shader in a set |
| of shaders linked together to form a single shader executable must, or a |
| link-time error results. |
| This function takes no arguments, returns no value, and must be declared as |
| type <strong>void</strong>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> main() |
| { |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The function <em>main</em> can contain uses of <strong>return</strong>. |
| See “<a href="#jumps">Jumps</a>” for more details.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time or link-time error to declare or define a function |
| <strong>main</strong> with any other parameters or return type.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="function-calling-conventions">6.1.1. Function Calling Conventions</h4> |
| <div class="paragraph"> |
| <p>Functions are called by value-return. |
| This means input arguments are copied into the function at call time, and |
| output arguments are copied back to the caller before function exit. |
| Because the function works with local copies of parameters, there are no |
| issues regarding aliasing of variables within a function. |
| To control what parameters are copied in and/or out through a function |
| definition or declaration:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The keyword <strong>in</strong> is used as a qualifier to denote a parameter is to be |
| copied in, but not copied out.</p> |
| </li> |
| <li> |
| <p>The keyword <strong>out</strong> is used as a qualifier to denote a parameter is to be |
| copied out, but not copied in. |
| This should be used whenever possible to avoid unnecessarily copying |
| parameters in.</p> |
| </li> |
| <li> |
| <p>The keyword <strong>inout</strong> is used as a qualifier to denote the parameter is to |
| be both copied in and copied out. |
| It means the same thing as specifying both <strong>in</strong> and <strong>out</strong>.</p> |
| </li> |
| <li> |
| <p>A function parameter declared with no such qualifier means the same |
| thing as specifying <strong>in</strong>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>All arguments are evaluated at call time, exactly once, in order, from left |
| to right. |
| Evaluation of an <strong>in</strong> parameter results in a value that is copied to the |
| formal parameter. |
| Evaluation of an <strong>out</strong> parameter results in an l-value that is used to copy |
| out a value when the function returns. |
| Evaluation of an <strong>inout</strong> parameter results in both a value and an l-value; |
| the value is copied to the formal parameter at call time and the l-value is |
| used to copy out a value when the function returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The order in which output parameters are copied back to the caller is |
| undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the function matching described in the previous section required argument |
| type conversions, these conversions are applied at copy-in and copy-out |
| times.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In a function, writing to an input-only parameter is allowed. |
| Only the function’s copy is modified. |
| This can be prevented by declaring a parameter with the <strong>const</strong> qualifier.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When calling a function, expressions that do not evaluate to l-values cannot |
| be passed to parameters declared as <strong>out</strong> or <strong>inout</strong>, or a compile-time error |
| results.</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>function-prototype</em> : </dt> |
| <dd> |
| <p><em>precision-qualifier</em> <em>type</em> <em>function-name</em> <strong>(</strong> <em>parameter-qualifiers</em> |
| <em>precision-qualifier</em> <em>type</em> <em>name</em> <em>array-specifier</em> <strong>,</strong> …​ |
| <strong>)</strong></p> |
| </dd> |
| <dt class="hdlist1"><em>type</em> : </dt> |
| <dd> |
| <p>any basic type, array type, structure name, or structure definition</p> |
| </dd> |
| <dt class="hdlist1"><em>parameter-qualifiers</em> : </dt> |
| <dd> |
| <p><em>empty</em><br> |
| list of <em>parameter-qualifier</em></p> |
| </dd> |
| <dt class="hdlist1"><em>parameter-qualifier</em> : </dt> |
| <dd> |
| <p><strong>const</strong><br> |
| <strong>in</strong><br> |
| <strong>out</strong><br> |
| <strong>inout</strong><br> |
| <strong>precise</strong><br> |
| <em>memory-qualifier</em><br> |
| <em>precision-qualifier</em></p> |
| </dd> |
| <dt class="hdlist1"><em>name</em> : </dt> |
| <dd> |
| <p>empty<br> |
| identifier</p> |
| </dd> |
| <dt class="hdlist1"><em>array-specifier</em> : </dt> |
| <dd> |
| <p>empty<br> |
| <strong>[</strong> <em>integral-constant-expression</em> <strong>]</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>const</strong> qualifier cannot be used with <strong>out</strong> or <strong>inout</strong>, or |
| a compile-time error results. |
| The above is used both for function declarations (i.e., prototypes) and for |
| function definitions. |
| Hence, function definitions can have unnamed arguments.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Recursion is not allowed, not even statically. |
| Static recursion is present if the static function-call graph of a program |
| contains cycles. |
| This includes all potential function calls through variables declared as |
| <strong>subroutine</strong> <strong>uniform</strong> (described below). |
| It is a compile-time or link-time error if a single compilation unit |
| (shader) contains either static recursion or the potential for recursion |
| through subroutine variables.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="subroutines">6.1.2. Subroutines</h4> |
| <div class="paragraph"> |
| <p>Subroutines provide a mechanism allowing shaders to be compiled in a manner |
| where the target of one or more function calls can be changed at run-time |
| without requiring any shader recompilation. |
| For example, a single shader may be compiled with support for multiple |
| illumination algorithms to handle different kinds of lights or surface |
| materials. |
| An application using such a shader may switch illumination algorithms by |
| changing the value of its subroutine uniforms. |
| To use subroutines, a subroutine type is declared, one or more functions are |
| associated with that subroutine type, and a subroutine variable of that type |
| is declared. |
| The function currently assigned to the variable function is then called by |
| using function calling syntax replacing a function name with the name of the |
| subroutine variable. |
| Subroutine variables are uniforms, and are assigned to specific functions |
| only through commands (<strong>UniformSubroutinesuiv</strong>) in the OpenGL API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subroutine functionality is not available when generating SPIR-V.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subroutine types are declared using a statement similar to a function |
| declaration, with the <strong>subroutine</strong> keyword, as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">subroutine returnType subroutineTypeName(type0 arg0, type1 arg1, |
| ..., typen argn);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>As with function declarations, the formal argument names (<em>args</em> above) are |
| optional. |
| Functions are associated with subroutine types of matching declarations by |
| defining the function with the <strong>subroutine</strong> keyword and a list of subroutine |
| types the function matches:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">subroutine(subroutineTypeName0, ..., subroutineTypeNameN) |
| returnType functionName(type0 arg0, type1 arg1, ..., typen argn) |
| { ... } <span class="comment">// function body</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error if arguments and return type don’t match between |
| the function and each associated subroutine type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Functions declared with <strong>subroutine</strong> must include a body. |
| An overloaded function cannot be declared with <strong>subroutine</strong>; a program will |
| fail to compile or link if any shader or stage contains two or more |
| functions with the same name if the name is associated with a subroutine |
| type.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A function declared with <strong>subroutine</strong> can also be called directly with a |
| static use of <em>functionName</em>, as is done with non-subroutine function |
| declarations and calls.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subroutine type variables are required to be <em>subroutine uniforms</em>, and are |
| declared with a specific subroutine type in a subroutine uniform variable |
| declaration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">subroutine uniform subroutineTypeName subroutineVarName;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Subroutine uniform variables are called the same way functions are called. |
| When a subroutine variable (or an element of a subroutine variable array) is |
| associated with a particular function, all function calls through that |
| variable will call that particular function.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unlike other uniform variables, subroutine uniform variables are scoped to |
| the shader execution stage the variable is declared in.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Subroutine variables may be declared as explicitly-sized arrays, which can |
| be indexed only with dynamically uniform expressions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time error to use the <strong>subroutine</strong> keyword in any places |
| other than (as shown above) to</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>declare a subroutine type at global scope,</p> |
| </li> |
| <li> |
| <p>declare a function as a subroutine, or</p> |
| </li> |
| <li> |
| <p>declare a subroutine variable at global scope.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="selection">6.2. Selection</h3> |
| <div class="paragraph"> |
| <p>Conditional control flow in the shading language is done by either <strong>if</strong>, |
| <strong>if</strong>-<strong>else</strong>, or <strong>switch</strong> statements:</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>selection-statement</em> : </dt> |
| <dd> |
| <p><strong>if</strong> <strong>(</strong> <em>bool-expression</em> <strong>)</strong> <em>statement</em><br> |
| <strong>if</strong> <strong>(</strong> <em>bool-expression</em> <strong>)</strong> <em>statement</em> <strong>else</strong> <em>statement</em><br> |
| <strong>switch</strong> <strong>(</strong> <em>init-expression</em> <strong>)</strong> <strong>{</strong> <em>switch-statement-list<sub>opt</sub></em> <strong>}</strong></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Where <em>switch-statement-list</em> is a nested scope containing a list of zero or |
| more <em>switch-statement</em> and other statements defined by the language, where |
| <em>switch-statement</em> adds some forms of labels. |
| That is</p> |
| </div> |
| <div class="openblock bnf"> |
| <div class="content"> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><em>switch-statement-list</em> : </dt> |
| <dd> |
| <p><em>switch-statement</em><br> |
| <em>switch-statement-list</em> <em>switch-statement</em></p> |
| </dd> |
| <dt class="hdlist1"><em>switch-statement</em> : </dt> |
| <dd> |
| <p><strong>case</strong> <em>constant-expression</em> <strong>:</strong><br> |
| <strong>default</strong> <strong>:</strong> <em>statement</em></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note the above grammar’s purpose is to aid discussion in this section; the |
| normative grammar is in “<a href="#shading-language-grammar">Shading Language |
| Grammar</a>”.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If an <strong>if</strong>-expression evaluates to <strong>true</strong>, then the first <em>statement</em> is |
| executed. |
| If it evaluates to <strong>false</strong> and there is an <strong>else</strong> part then the second |
| <em>statement</em> is executed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Any expression whose type evaluates to a Boolean can be used as the |
| conditional expression <em>bool-expression</em>. |
| Vector types are not accepted as the expression to <strong>if</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Conditionals can be nested.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The type of <em>init-expression</em> in a <strong>switch</strong> statement must be a scalar |
| integer. |
| The type of the <em>constant-expression</em> value in a case label also must be a |
| scalar integer. |
| When any pair of these values is tested for “equal value” and the types do |
| not match, an implicit conversion will be done to convert the <strong>int</strong> to a |
| <strong>uint</strong> (see “<a href="#implicit-conversions">Implicit Conversions</a>”) before the |
| compare is done. |
| If a <strong>case</strong> label has a <em>constant-expression</em> of equal value to |
| <em>init-expression</em>, execution will continue after that label. |
| Otherwise, if there is a <strong>default</strong> label, execution will continue after that |
| label. |
| Otherwise, execution skips the rest of the switch statement. |
| It is a compile-time error to have more than one <strong>default</strong> or a replicated |
| <em>constant-expression</em>. |
| A <strong>break</strong> statement not nested in a loop or other switch statement (either |
| not nested or nested only in <strong>if</strong> or <strong>if</strong>-<strong>else</strong> statements) will also skip |
| the rest of the switch statement. |
| Fall through labels are allowed, but it is a compile-time error to have no |
| statement between a label and the end of the switch statement. |
| No statements are allowed in a switch statement before the first <strong>case</strong> |
| statement.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>case</strong> and <strong>default</strong> labels can only appear within a <strong>switch</strong> statement. |
| No <strong>case</strong> or <strong>default</strong> labels can be nested inside other statements or |
| compound statements within their corresponding <strong>switch</strong>.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="iteration">6.3. Iteration</h3> |
| <div class="paragraph"> |
| <p>For, while, and do loops are allowed as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="keyword">for</span> (init-expression; condition-expression; loop-expression) |
| sub-statement |
| <span class="keyword">while</span> (condition-expression) |
| sub-statement |
| <span class="keyword">do</span> |
| statement |
| <span class="keyword">while</span> (condition-expression)</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>See “<a href="#shading-language-grammar">Shading Language Grammar</a>” for the |
| definitive specification of loops.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>for</strong> loop first evaluates the <em>init-expression</em>, then the |
| <em>condition-expression</em>. |
| If the <em>condition-expression</em> evaluates to <strong>true</strong>, then the body of the loop |
| is executed. |
| After the body is executed, a <strong>for</strong> loop will then evaluate the |
| <em>loop-expression</em>, and then loop back to evaluate the |
| <em>condition-expression</em>, repeating until the <em>condition-expression</em> evaluates |
| to <strong>false</strong>. |
| The loop is then exited, skipping its body and skipping its |
| <em>loop-expression</em>. |
| Variables modified by the <em>loop-expression</em> maintain their value after the |
| loop is exited, provided they are still in scope. |
| Variables declared in <em>init-expression</em> or <em>condition-expression</em> are only |
| in scope until the end of the sub-statement of the <strong>for</strong> loop.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>while</strong> loop first evaluates the <em>condition-expression</em>. |
| If <strong>true</strong>, then the body is executed. |
| This is then repeated, until the <em>condition-expression</em> evaluates to |
| <strong>false</strong>, exiting the loop and skipping its body. |
| Variables declared in the <em>condition-expression</em> are only in scope until the |
| end of the sub-statement of the <strong>while</strong> loop.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>do</strong>-<strong>while</strong> loop first executes the body, then executes the |
| <em>condition-expression</em>. |
| This is repeated until <em>condition-expression</em> evaluates to <strong>false</strong>, and then |
| the loop is exited.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Expressions for <em>condition-expression</em> must evaluate to a Boolean.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Both the <em>condition-expression</em> and the <em>init-expression</em> can declare and |
| initialize a variable, except in the <strong>do</strong>-<strong>while</strong> loop, which cannot declare |
| a variable in its <em>condition-expression</em>. |
| The variable’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 “goto” 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 < <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’s alpha value and discard the fragment |
| based on that test. |
| However, it should be noted that coverage testing occurs after the fragment |
| shader runs, and the coverage test can change the alpha value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>return</strong> jump causes immediate exit of the current function. |
| If it has <em>expression</em> then that is the return value for the function.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The function <em>main</em> can use <strong>return</strong>. |
| This simply causes <em>main</em> to exit in the same way as when the end of the |
| function had been reached. |
| It does not imply a use of <strong>discard</strong> in a fragment shader. |
| Using <strong>return</strong> in <em>main</em> before defining outputs will have the same behavior |
| as reaching the end of <em>main</em> before defining outputs.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="built-in-variables">7. Built-In Variables</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="built-in-language-variables">7.1. Built-In Language Variables</h3> |
| <div class="paragraph"> |
| <p>Some operations occur outside shader functionality and need to provide |
| values to or receive values from shader executables. |
| Shaders communicate with fixed-function pipeline stages, and |
| optionally with other shader executables, through the use of built-in input |
| and output variables.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="vertex-shader-special-variables">7.1.1. Vertex Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>The built-in vertex shader variables are intrinsically declared as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in <span class="predefined-type">int</span> gl_VertexID; <span class="comment">// only present when not targeting Vulkan</span> |
| in <span class="predefined-type">int</span> gl_InstanceID; <span class="comment">// only present when not targeting Vulkan</span> |
| in <span class="predefined-type">int</span> gl_VertexIndex; <span class="comment">// only present when targeting Vulkan</span> |
| in <span class="predefined-type">int</span> gl_InstanceIndex; <span class="comment">// only present when targeting Vulkan</span> |
| in <span class="predefined-type">int</span> gl_DrawID; |
| in <span class="predefined-type">int</span> gl_BaseVertex; |
| in <span class="predefined-type">int</span> gl_BaseInstance; |
| |
| out gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_Position</em> is intended for writing the homogeneous vertex |
| position. |
| It can be written at any time during shader execution. |
| This value will be used by primitive assembly, clipping, culling, and other |
| fixed functionality operations, if present, that operate on primitives after |
| vertex processing has occurred. |
| Its value is undefined after the vertex processing stage if the vertex |
| shader executable does not write <em>gl_Position</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_PointSize</em> is intended for a shader to write the size of |
| the point to be rasterized. |
| It is measured in pixels. |
| If <em>gl_PointSize</em> is not written to, its value is undefined in subsequent |
| pipe stages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_ClipDistance</em> is intended for writing clip distances, and |
| provides the forward compatible mechanism for controlling user clipping. |
| The element <em>gl_ClipDistance[i]</em> specifies a clip distance for each plane |
| <em>i</em>. |
| A distance of 0 means the vertex is on the plane, a positive distance means |
| the vertex is inside the clip plane, and a negative distance means the point |
| is outside the clip plane. |
| The clip distances will be linearly interpolated across the primitive and |
| the portion of the primitive with interpolated distances less than 0 will be |
| clipped.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>gl_ClipDistance</em> array is predeclared as unsized and must be explicitly |
| sized by the shader either redeclaring it with a size or implicitly sized by |
| indexing it only with constant integral expressions. |
| This needs to size the array to include all the clip planes that are enabled |
| via the API; if the size does not include all enabled planes, |
| results are undefined. |
| The size can be at most <em>gl_MaxClipDistances</em>. |
| The number of varying components (see <em>gl_MaxVaryingComponents)</em> consumed by |
| <em>gl_ClipDistance</em> will match the size of the array, no matter how many |
| planes are enabled. |
| The shader must also set all values in <em>gl_ClipDistance</em> that have been |
| enabled via the API, or results are undefined. |
| Values written into <em>gl_ClipDistance</em> for planes that are not enabled have |
| no effect.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_CullDistance</em> provides a mechanism for controlling user |
| culling. |
| The element <em>gl_CullDistance[i]</em> specifies a cull distance for plane <em>i</em>. |
| A distance of 0 means the vertex is on the plane, a positive distance means |
| the vertex is inside the cull volume, and a negative distance means the |
| point is outside the cull volume. |
| Primitives whose vertices all have a negative cull distance for plane <em>i</em> |
| will be discarded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <em>gl_CullDistance</em> array is predeclared as unsized and must be sized by |
| the shader either redeclaring it with a size or indexing it only with |
| constant integral expressions. |
| The size determines the number and set of enabled cull distances and can be |
| at most <em>gl_MaxCullDistances</em>. |
| The number of varying components (see <em>gl_MaxVaryingComponents</em>) consumed by |
| <em>gl_CullDistance</em> will match the size of the array. |
| Shaders writing <em>gl_CullDistance</em> must write all enabled distances, or |
| culling results are undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As an output variable, <em>gl_CullDistance</em> provides the place for the shader |
| to write these distances. |
| As an input in all but the fragment language, it reads the values written in |
| the previous shader stage. |
| In the fragment language, <em>gl_CullDistance</em> array contains linearly |
| interpolated values for the vertex values written by a shader to the |
| <em>gl_CullDistance</em> vertex output variable.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is a compile-time or link-time error for the set of shaders forming a |
| program to have the sum of the sizes of the <em>gl_ClipDistance</em> and |
| <em>gl_CullDistance</em> arrays to be larger than |
| <em>gl_MaxCombinedClipAndCullDistances</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_VertexID</em> is a vertex shader input variable that holds an |
| integer index for the vertex, as defined under “Shader Inputs” in section |
| 11.1.3.9 “Shader Inputs” of the <a href="#references">OpenGL Specification</a>. |
| It is only present when not targeting Vulkan. |
| Even when present, the value of <em>gl_VertexID</em> is not always defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_InstanceID</em> is a vertex shader input variable that holds |
| the instance number of the current primitive in an instanced draw call (see |
| “Shader Inputs” in section 11.1.3.9 “Shader Inputs” of the |
| <a href="#references">OpenGL Specification</a>). |
| It is only present when not targeting Vulkan. |
| If the current primitive does not come from an instanced draw call, the |
| value of <em>gl_InstanceID</em> is zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_VertexIndex</em> is a vertex language input variable that |
| holds an integer index for the vertex, relative to a base. |
| It is only present when targeting Vulkan. |
| Even when present, the value of <em>gl_VertexIndex</em> is not always defined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_InstanceIndex</em> is a vertex language input variable that |
| holds the instance number of the current primitive in an instanced draw |
| call, relative to a base. |
| It is only present when targeting Vulkan. |
| If the current primitive does not come from an instanced draw call, |
| the value of gl_InstanceIndex is zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_DrawID</em> is a vertex shader input variable that holds the |
| integer index of the drawing command to which the current vertex belongs |
| (see “Shader Inputs” in section 11.1.3.9 of the <a href="#references">OpenGL Specification</a>). |
| If the vertex is not invoked by a <strong>Multi</strong>* form of a draw command, then the |
| value of <em>gl_DrawID</em> is zero.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_BaseVertex</em> is a vertex shader input variable that holds |
| the integer value passed to the baseVertex parameter of the command that |
| resulted in the current shader invocation (see “Shader Inputs” in section |
| 11.1.3.9 of the <a href="#references">OpenGL Specification</a>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_BaseInstance</em> is a vertex shader input variable that holds |
| the integer value passed to the baseInstance parameter of the command that |
| resulted in the current shader invocation (see “Shader Inputs” in section |
| 11.1.3.9 of the <a href="#references">OpenGL Specification</a>).</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="tessellation-control-shader-special-variables">7.1.2. Tessellation Control Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>In the tessellation control shader, built-in variables are intrinsically |
| declared as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| } gl_in[gl_MaxPatchVertices]; |
| |
| in <span class="predefined-type">int</span> gl_PatchVerticesIn; |
| in <span class="predefined-type">int</span> gl_PrimitiveID; |
| in <span class="predefined-type">int</span> gl_InvocationID; |
| |
| out gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| } gl_out[]; |
| |
| patch out <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>]; |
| patch out <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>];</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-control-input-variables">Tessellation Control Input Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> |
| contain the values written in the previous shader stage to the corresponding |
| outputs.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_PatchVerticesIn</em> contains the number of vertices in the input patch |
| being processed by the shader. |
| A single shader can read patches of differing sizes, so the value of |
| <em>gl_PatchVerticesIn</em> may differ between patches.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_PrimitiveID</em> contains the number of primitives processed by the shader |
| since the current set of rendering primitives was started.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_InvocationID</em> contains the number of the output patch vertex assigned to |
| the tessellation control shader invocation. |
| It is assigned integer values in the range [0, N-1], where N is the number |
| of output patch vertices per primitive.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-control-output-variables">Tessellation Control Output Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are |
| used in the same fashion as the corresponding output variables in the vertex |
| shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The values written to <em>gl_TessLevelOuter</em> and <em>gl_TessLevelInner</em> are |
| assigned to the corresponding outer and inner tessellation levels of the |
| output patch. |
| They are used by the tessellation primitive generator to control primitive |
| tessellation and may be read by tessellation evaluation shaders.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="tessellation-evaluation-shader-special-variables">7.1.3. Tessellation Evaluation Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>In the tessellation evaluation shader, built-in variables are intrinsically |
| declared as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| } gl_in[gl_MaxPatchVertices]; |
| |
| in <span class="predefined-type">int</span> gl_PatchVerticesIn; |
| in <span class="predefined-type">int</span> gl_PrimitiveID; |
| in vec3 gl_TessCoord; |
| patch in <span class="predefined-type">float</span> gl_TessLevelOuter[<span class="integer">4</span>]; |
| patch in <span class="predefined-type">float</span> gl_TessLevelInner[<span class="integer">2</span>]; |
| |
| out gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-evaluation-input-variables">Tessellation Evaluation Input Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> |
| contain the values written in the previous shader stage to the corresponding |
| outputs.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_PatchVerticesIn</em> and <em>gl_PrimitiveID</em> are defined in the same fashion as |
| the corresponding input variables in the tessellation control shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_TessCoord</em> specifies a three-component <em>(u,v,w)</em> vector identifying the |
| position of the vertex being processed by the shader relative to the |
| primitive being tessellated. |
| Its values will obey the properties</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_TessCoord.x == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.x) <span class="comment">// two operations performed</span> |
| gl_TessCoord.y == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.y) <span class="comment">// two operations performed</span> |
| gl_TessCoord.z == <span class="float">1</span><span class="float">.0</span> - (<span class="float">1</span><span class="float">.0</span> - gl_TessCoord.z) <span class="comment">// two operations performed</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>to aid in replicating subdivision computations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a tessellation control shader is active, the input variables |
| <em>gl_TessLevelOuter</em> and <em>gl_TessLevelInner</em> are filled with the |
| corresponding outputs written by the tessellation control shader. |
| Otherwise, they are assigned with default tessellation levels specified in |
| section 11.2.3.3 “Tessellation Evaluation Shader Inputs” of the |
| <a href="#references">OpenGL Specification</a>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="tessellation-evaluation-output-variables">Tessellation Evaluation Output Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are |
| used in the same fashion as the corresponding output variables in the vertex |
| shader.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="geometry-shader-special-variables">7.1.4. Geometry Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>In the geometry shader, built-in variables are intrinsically declared as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| } gl_in[]; |
| |
| in <span class="predefined-type">int</span> gl_PrimitiveIDIn; |
| in <span class="predefined-type">int</span> gl_InvocationID; |
| |
| out gl_PerVertex { |
| vec4 gl_Position; |
| <span class="predefined-type">float</span> gl_PointSize; |
| <span class="predefined-type">float</span> gl_ClipDistance[]; |
| <span class="predefined-type">float</span> gl_CullDistance[]; |
| }; |
| |
| out <span class="predefined-type">int</span> gl_PrimitiveID; |
| out <span class="predefined-type">int</span> gl_Layer; |
| out <span class="predefined-type">int</span> gl_ViewportIndex;</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="geometry-shader-input-variables">Geometry Shader Input Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> |
| contain the values written in the previous shader stage to the corresponding |
| outputs.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_PrimitiveIDIn</em> contains the number of primitives processed by the shader |
| since the current set of rendering primitives was started.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_InvocationID</em> contains the invocation number assigned to the geometry |
| shader invocation. |
| It is assigned integer values in the range [0, N-1], where N is the number |
| of geometry shader invocations per primitive.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="geometry-shader-output-variables">Geometry Shader Output Variables</h5> |
| <div class="paragraph"> |
| <p><em>gl_Position</em>, <em>gl_PointSize</em>, <em>gl_ClipDistance</em>, and <em>gl_CullDistance</em> are |
| used in the same fashion as the corresponding output variables in the vertex |
| shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_PrimitiveID</em> is filled with a single integer that serves as a primitive |
| identifier to the fragment shader. |
| This is then available to fragment shaders, which will select the written |
| primitive ID from the provoking vertex of the primitive being shaded. |
| If a fragment shader using <em>gl_PrimitiveID</em> is active and a geometry shader |
| is also active, the geometry shader must write to <em>gl_PrimitiveID</em> or the |
| fragment shader input <em>gl_PrimitiveID</em> is undefined. |
| See section 11.3.4.5 “Geometry Shader Outputs” of the |
| <a href="#references">OpenGL Specification</a> for more information.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_Layer</em> is used to select a specific layer (or face and layer of a cube |
| map) of a multi-layer framebuffer attachment. |
| The actual layer used will come from one of the vertices in the primitive |
| being shaded. |
| Which vertex the layer comes from is determined as discussed in section |
| 11.3.4.6 “Layer and Viewport Selection” of the <a href="#references">OpenGL Specification</a> |
| but may be undefined, so it is best to write the same layer value for all |
| vertices of a primitive. |
| If a shader statically assigns a value to <em>gl_Layer</em>, layered rendering mode |
| is enabled. |
| See section 11.3.4.5 “Geometry Shader Outputs” and section 9.4.9 “Layered |
| Framebuffers” of the <a href="#references">OpenGL Specification</a> for more information. |
| If a shader statically assigns a value to <em>gl_Layer</em>, and there is an |
| execution path through the shader that does not set <em>gl_Layer</em>, then the |
| value of <em>gl_Layer</em> is undefined for executions of the shader that take that |
| path.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The output variable <em>gl_Layer</em> takes on a special value when used with an |
| array of cube map textures. |
| Instead of only referring to the layer, it is used to select a cube map face |
| and a layer. |
| Setting <em>gl_Layer</em> to the value <em>layer*6+face</em> will render to face <em>face</em> of |
| the cube defined in layer <em>layer</em>. |
| The face values are defined in table 9.3 of section 9.4.9 “Layered |
| Framebuffers” of the <a href="#references">OpenGL Specification</a>, |
| but repeated below for clarity.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Face Value</th> |
| <th class="tableblock halign-left valign-top">Resulting Target</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_X</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_Y</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_Y</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_POSITIVE_Z</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">5</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">TEXTURE_CUBE_MAP_NEGATIVE_Z</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>For example, to render to the positive <em>y</em> cube map face located in the 5th |
| layer of the cube map array, <em>gl_Layer</em> should be set to <em>5 * 6 + 2</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The output variable <em>gl_ViewportIndex</em> provides the index of the viewport to |
| which the next primitive emitted from the geometry shader should be drawn. |
| Primitives generated by the geometry shader will undergo viewport |
| transformation and scissor testing using the viewport transformation and |
| scissor rectangle selected by the value of <em>gl_ViewportIndex</em>. |
| The viewport index used will come from one of the vertices in the primitive |
| being shaded. |
| However, which vertex the viewport index comes from is |
| implementation-dependent, so it is best to use the same viewport index for |
| all vertices of the primitive. |
| If a geometry shader does not assign a value to <em>gl_ViewportIndex</em>, viewport |
| transform and scissor rectangle zero will be used. |
| If a geometry shader statically assigns a value to <em>gl_ViewportIndex</em> and |
| there is a path through the shader that does not assign a value to |
| <em>gl_ViewportIndex</em>, the value of <em>gl_ViewportIndex</em> is undefined for |
| executions of the shader that take that path. |
| See section 11.3.4.6 “Layer and Viewport Selection” of the |
| <a href="#references">OpenGL Specification</a> for more information.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="fragment-shader-special-variables">7.1.5. Fragment Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>The built-in special variables that are accessible from a fragment shader |
| are intrinsically declared as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_FragCoord; |
| in <span class="predefined-type">bool</span> gl_FrontFacing; |
| in <span class="predefined-type">float</span> gl_ClipDistance[]; |
| in <span class="predefined-type">float</span> gl_CullDistance[]; |
| in vec2 gl_PointCoord; |
| in <span class="predefined-type">int</span> gl_PrimitiveID; |
| in <span class="predefined-type">int</span> gl_SampleID; |
| in vec2 gl_SamplePosition; |
| in <span class="predefined-type">int</span> gl_SampleMaskIn[]; |
| in <span class="predefined-type">int</span> gl_Layer; |
| in <span class="predefined-type">int</span> gl_ViewportIndex; |
| in <span class="predefined-type">bool</span> gl_HelperInvocation; |
| |
| out <span class="predefined-type">float</span> gl_FragDepth; |
| out <span class="predefined-type">int</span> gl_SampleMask[];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The output of the fragment shader executable is processed by the fixed |
| function operations at the back end of the API pipeline.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The fixed functionality computed depth for a fragment may be obtained by |
| reading <em>gl_FragCoord.z</em>, described below.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Writing to <em>gl_FragDepth</em> will establish the depth value for the fragment |
| being processed. |
| If depth buffering is enabled, and no shader writes <em>gl_FragDepth</em>, then the |
| fixed function value for depth will be used as the fragment’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’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’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 “<a href="#texture-functions">Texture Functions</a>”), and |
| explicitly in the derivative functions in |
| “<a href="#derivative-functions">Derivative Functions</a>”, for example <strong>dFdx</strong>() and |
| <strong>dFdy</strong>().</p> |
| </div> |
| <div class="paragraph"> |
| <p>Fragment shader helper invocations execute the same shader code as |
| non-helper invocations, but will not have side effects that modify the |
| framebuffer or other shader-accessible memory. |
| In particular:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Fragments corresponding to helper invocations are discarded when shader |
| execution is complete, without updating the framebuffer.</p> |
| </li> |
| <li> |
| <p>Stores to image and buffer variables performed by helper invocations |
| have no effect on the underlying image or buffer memory.</p> |
| </li> |
| <li> |
| <p>Atomic operations to image, buffer, or atomic counter variables |
| performed by helper invocations have no effect on the underlying image |
| or buffer memory. |
| The values returned by such atomic operations are undefined.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Helper invocations may be generated for pixels not covered by a primitive |
| being rendered. |
| While fragment shader inputs qualified with <strong>centroid</strong> are normally required |
| to be sampled in the intersection of the pixel and the primitive, the |
| requirement is ignored for such pixels since there is no intersection |
| between the pixel and primitive.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Helper invocations may also be generated for fragments that are covered by a |
| primitive being rendered when the fragment is killed by early fragment tests |
| (using the <strong>early_fragment_tests</strong> qualifier) or where the implementation is |
| able to determine that executing the fragment shader would have no effect |
| other than assisting in computing derivatives for other fragment shader |
| invocations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The set of helper invocations generated when processing any set of |
| primitives is implementation-dependent.</p> |
| </div> |
| <div class="paragraph"> |
| <p><em>gl_ClipDistance</em> contains linearly interpolated values for the vertex- |
| pipeline values written by a shader to the <em>gl_ClipDistance</em> output |
| variable. Only elements in this array that have clipping enabled will |
| have defined values.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The input variable <em>gl_PrimitiveID</em> is filled with the value written to the |
| <em>gl_PrimitiveID</em> geometry shader output, if a geometry shader is present. |
| Otherwise, it is filled with the number of primitives processed by the |
| shader since the current set of rendering primitives was started.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The input variable <em>gl_Layer</em> is filled with the value written to the |
| <em>gl_Layer</em> geometry shader output, if a geometry shader is present. |
| If the geometry stage does not dynamically assign a value to <em>gl_Layer</em>, the |
| value of <em>gl_Layer</em> in the fragment stage will be undefined. |
| If the geometry stage makes no static assignment to <em>gl_Layer</em>, the input |
| value in the fragment stage will be zero. |
| Otherwise, the fragment stage will read the same value written by the |
| geometry stage, even if that value is out of range. |
| If a fragment shader contains a static access to <em>gl_Layer</em>, it will count |
| against the implementation defined limit for the maximum number of inputs to |
| the fragment stage.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The input variable <em>gl_ViewportIndex</em> is filled with the value written to |
| the output variable <em>gl_ViewportIndex</em> in the geometry stage, if a geometry |
| shader is present. |
| If the geometry stage does not dynamically assign a value to |
| <em>gl_ViewportIndex</em>, the value of <em>gl_ViewportIndex</em> in the fragment shader |
| will be undefined. |
| If the geometry stage makes no static assignment to <em>gl_ViewportIndex</em>, the |
| fragment stage will read zero. |
| Otherwise, the fragment stage will read the same value written by the |
| geometry stage, even if that value is out of range. |
| If a fragment shader contains a static access to <em>gl_ViewportIndex</em>, it will |
| count against the implementation defined limit for the maximum number of |
| inputs to the fragment stage.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="compute-shader-special-variables">7.1.6. Compute Shader Special Variables</h4> |
| <div class="paragraph"> |
| <p>In the compute shader, built-in variables are declared as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">// workgroup dimensions</span> |
| in uvec3 gl_NumWorkGroups; |
| <span class="directive">const</span> uvec3 gl_WorkGroupSize; |
| |
| <span class="comment">// workgroup and invocation IDs</span> |
| in uvec3 gl_WorkGroupID; |
| in uvec3 gl_LocalInvocationID; |
| |
| <span class="comment">// derived variables</span> |
| in uvec3 gl_GlobalInvocationID; |
| in uint gl_LocalInvocationIndex;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in variable <em>gl_NumWorkGroups</em> is a compute-shader input variable |
| containing the number of workgroups in each dimension of the dispatch that |
| will execute the compute shader. |
| Its content is equal to the values specified in the <em>num_groups_x</em>, |
| <em>num_groups_y</em>, and <em>num_groups_z</em> parameters passed to the |
| <em>DispatchCompute</em> API entry point.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in constant <em>gl_WorkGroupSize</em> is a compute-shader constant |
| containing the workgroup size of the shader. |
| The size of the workgroup in the <em>X</em>, <em>Y</em>, and <em>Z</em> dimensions is stored in |
| the <em>x</em>, <em>y</em>, and <em>z</em> components. |
| The constants values in <em>gl_WorkGroupSize</em> will match those specified in the |
| required <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong> layout |
| qualifiers for the current shader. |
| This is a constant so that it can be used to size arrays of memory that can |
| be shared within the workgroup. |
| It is a compile-time error to use <em>gl_WorkGroupSize</em> in a shader that does |
| not declare a fixed workgroup size, or before that shader has declared a |
| fixed workgroup size, using <strong>local_size_x</strong>, <strong>local_size_y</strong>, and |
| <strong>local_size_z</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in variable <em>gl_WorkGroupID</em> is a compute-shader input variable |
| containing the three-dimensional index of the workgroup that the |
| current invocation is executing in. |
| The possible values range across the parameters passed into |
| <em>DispatchCompute</em>, i.e., from (0, 0, 0) to (<em>gl_NumWorkGroups.x</em> - 1, |
| <em>gl_NumWorkGroups.y</em> - 1, <em>gl_NumWorkGroups.z</em> -1).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in variable <em>gl_LocalInvocationID</em> is a compute-shader input |
| variable containing the three-dimensional index of the current work item |
| within the workgroup. |
| The possible values for this variable range across the workgroup |
| size, i.e., (0,0,0) to (<em>gl_WorkGroupSize.x</em> - 1, <em>gl_WorkGroupSize.y</em> - 1, |
| <em>gl_WorkGroupSize.z</em> - 1). Use of <em>gl_LocalInvocationID</em> is allowed |
| before declarations of <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in variable <em>gl_GlobalInvocationID</em> is a compute shader input |
| variable containing the global index of the current work item. |
| This value uniquely identifies this invocation from all other invocations |
| across all workgroups initiated by the current <em>DispatchCompute</em> call. |
| This is computed as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_GlobalInvocationID = |
| gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in variable <em>gl_LocalInvocationIndex</em> is a compute shader input |
| variable that contains the one-dimensional representation of the |
| <em>gl_LocalInvocationID</em>. |
| This is computed as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">gl_LocalInvocationIndex = |
| gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + |
| gl_LocalInvocationID.y * gl_WorkGroupSize.x + |
| gl_LocalInvocationID.x;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Use of <em>gl_LocalInvocationIndex</em> is allowed before declarations of |
| <strong>local_size_x</strong>, <strong>local_size_y</strong>, and <strong>local_size_z</strong>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="compatibility-profile-built-in-language-variables">7.1.7. Compatibility Profile Built-In Language Variables</h4> |
| <div class="paragraph"> |
| <p>When using the compatibility profile, the GL can provide fixed functionality |
| behavior for the vertex and fragment programmable pipeline stages. |
| For example, mixing a fixed functionality vertex stage with a programmable |
| fragment stage.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following built-in vertex, tessellation control, tessellation |
| evaluation, and geometry output variables are available to specify inputs |
| for the subsequent programmable shader stage or the fixed functionality |
| fragment stage. |
| A particular one should be written to if any functionality in a |
| corresponding fragment shader or fixed pipeline uses it or state derived |
| from it. |
| Otherwise, behavior is undefined. |
| The following members are added to the output <em>gl_PerVertex</em> block in these |
| languages:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex { <span class="comment">// part of the gl_PerVertex block described in 7.1</span> |
| <span class="comment">// in addition to other gl_PerVertex members...</span> |
| vec4 gl_ClipVertex; |
| vec4 gl_FrontColor; |
| vec4 gl_BackColor; |
| vec4 gl_FrontSecondaryColor; |
| vec4 gl_BackSecondaryColor; |
| vec4 gl_TexCoord[]; |
| <span class="predefined-type">float</span> gl_FogFragCoord; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The output variable <em>gl_ClipVertex</em> provides a place for vertex and geometry |
| shaders to write the coordinate to be used with the user clipping planes. |
| Writing to <em>gl_ClipDistance</em> is the preferred method for user clipping. |
| It is a compile-time or link-time error for the set of shaders forming a |
| program to statically read or write both <em>gl_ClipVertex</em> and either |
| <em>gl_ClipDistance</em> or <em>gl_CullDistance</em>. |
| If neither <em>gl_ClipVertex</em> nor <em>gl_ClipDistance</em> is written, their values |
| are undefined and any clipping against user clip planes is also undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Similarly to what was previously described for the core profile, the |
| <em>gl_PerVertex</em> block can be redeclared in a shader to explicitly include |
| these additional members. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex { |
| vec4 gl_Position; <span class="comment">// will use gl_Position</span> |
| vec4 gl_FrontColor; <span class="comment">// will consume gl_color in the fragment shader</span> |
| vec4 gl_BackColor; |
| vec4 gl_TexCoord[<span class="integer">3</span>]; <span class="comment">// 3 elements of gl_TexCoord will be used</span> |
| }; <span class="comment">// no other aspects of the fixed interface will be used</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The user must ensure the clip vertex and user clipping planes are defined in |
| the same coordinate space. |
| User clip planes work properly only under linear transform. |
| It is undefined what happens under non-linear transform.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The output variables <em>gl_FrontColor</em>, <em>glFrontSecondaryColor</em>, |
| <em>gl_BackColor</em>, and <em>glBackSecondaryColor</em> assign primary and secondary |
| colors for front and back faces of primitives containing the vertex being |
| processed. |
| The output variable <em>gl_TexCoord</em> assigns texture coordinates for the vertex |
| being processed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For <em>gl_FogFragCoord</em>, the value written will be used as the “c” value in |
| section 16.4 “Fog” of the Compatibility profile of the |
| <a href="#references">OpenGL Specification</a>, by the fixed functionality pipeline. |
| For example, if the z-coordinate of the fragment in eye space is desired as |
| “c”, then that’s what the vertex shader executable should write into |
| <em>gl_FogFragCoord</em>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As with all arrays, indices used to subscript <em>gl_TexCoord</em> must either be a |
| constant integral expressions, or this array must be redeclared by the |
| shader with a size. |
| The size can be at most <em>gl_MaxTextureCoords</em>. |
| Using indices close to 0 may aid the implementation in preserving varying |
| resources. |
| The redeclaration of <em>gl_TexCoord</em> can also be done at global scope as, for |
| example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_TexCoord[<span class="integer">3</span>]; |
| out vec4 gl_TexCoord[<span class="integer">4</span>];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>(This treatment is a special case for <em>gl_TexCoord[]</em>, not a general method |
| for redeclaring members of blocks.) It is a compile-time error to redeclare |
| <em>gl_TexCoord[]</em> at global scope if there is a redeclaration of the |
| corresponding built-in block; only one form of redeclaration is allowed |
| within a shader (and hence within a stage, as block redeclarations must |
| match across all shaders using it).</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the tessellation control, evaluation, and geometry shaders, the outputs |
| of the previous stage described above are also available in the input |
| <em>gl_PerVertex</em> block in these languages.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { <span class="comment">// part of the gl_PerVertex block described in 7.1</span> |
| <span class="comment">// in addition to other gl_PerVertex members...</span> |
| vec4 gl_ClipVertex; |
| vec4 gl_FrontColor; |
| vec4 gl_BackColor; |
| vec4 gl_FrontSecondaryColor; |
| vec4 gl_BackSecondaryColor; |
| vec4 gl_TexCoord[]; |
| <span class="predefined-type">float</span> gl_FogFragCoord; |
| } gl_in[];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>These can be redeclared to establish an explicit pipeline interface, the |
| same way as described above for the output block <em>gl_PerVertex</em>, and the |
| input redeclaration must match the output redeclaration of the previous |
| stage. |
| However, when a built-in interface block with an instance name is redeclared |
| (e.g. <em>gl_in</em>), the instance name must be included in the redeclaration. |
| It is a compile-time error to not include the built-in instance name or to |
| change its name. |
| For example,</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerVertex { |
| vec4 gl_ClipVertex; |
| vec4 gl_FrontColor; |
| } gl_in[]; <span class="comment">// must be present and must be "gl_in[]"</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Built-in block arrays predeclared with a size can be redeclared with unsized syntax. |
| This keeps their size equal to the original predeclared size.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Treatment of <em>gl_TexCoord[]</em> redeclaration is also identical to that |
| described for the output block <em>gl_TexCoord[]</em> redeclaration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following fragment input block is also available in a fragment shader |
| when using the compatibility profile:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in gl_PerFragment { |
| in <span class="predefined-type">float</span> gl_FogFragCoord; |
| in vec4 gl_TexCoord[]; |
| in vec4 gl_Color; |
| in vec4 gl_SecondaryColor; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The values in <em>gl_Color</em> and <em>gl_SecondaryColor</em> will be derived |
| automatically by the system from <em>gl_FrontColor</em>, <em>gl_BackColor</em>, |
| <em>gl_FrontSecondaryColor</em>, and <em>gl_BackSecondaryColor</em> based on which face is |
| visible in the primitive producing the fragment. |
| If fixed functionality is used for vertex processing, then <em>gl_FogFragCoord</em> |
| will either be the z-coordinate of the fragment in eye space, or the |
| interpolation of the fog coordinate, as described in section 16.4 “Fog” of |
| the Compatibility profile of the <a href="#references">OpenGL Specification</a>. |
| The <em>gl_TexCoord[]</em> values are the interpolated <em>gl_TexCoord[]</em> values from |
| a vertex shader or the texture coordinates of any fixed pipeline based |
| vertex functionality.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Indices to the fragment shader <em>gl_TexCoord</em> array are as described above in |
| the vertex shader text.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As described above for the input and output <em>gl_PerVertex</em> blocks, the |
| <em>gl_PerFragment</em> block can be redeclared to create an explicit interface to |
| another program. |
| When matching these interfaces between separate programs, members in the |
| <em>gl_PerVertex</em> output block must be declared if and only if the |
| corresponding fragment shader members generated from them are present in the |
| <em>gl_PerFragment</em> input block. |
| These matches are described in detail in section 7.4.1 “Shader Interface |
| Matching” of the <a href="#references">OpenGL Specification</a>. |
| If they don’t match within a program, a link-time error will result. |
| If the mismatch is between two programs, values passed between programs are |
| undefined. |
| Unlike with all other block matching, the order of declaration within |
| <em>gl_PerFragment</em> does not have to match across shaders and does not have to |
| correspond with order of declaration in a matching <em>gl_PerVertex</em> |
| redeclaration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following fragment output variables are available in a fragment shader |
| when using the compatibility profile:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out vec4 gl_FragColor; |
| out vec4 gl_FragData[gl_MaxDrawBuffers];</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Writing to <em>gl_FragColor</em> specifies the fragment color that will be used by |
| the subsequent fixed functionality pipeline. |
| If subsequent fixed functionality consumes fragment color and an execution |
| of the fragment shader executable does not write a value to <em>gl_FragColor</em> |
| then the fragment color consumed is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The variable <em>gl_FragData</em> is an array. |
| Writing to <em>gl_FragData[n]</em> specifies the fragment data that will be used by |
| the subsequent fixed functionality pipeline for data <em>n</em>. |
| If subsequent fixed functionality consumes fragment data and an execution of |
| a fragment shader executable does not write a value to it, then the fragment |
| data consumed is undefined.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a shader statically assigns a value to <em>gl_FragColor</em>, it may not assign |
| a value to any element of <em>gl_FragData</em>. |
| If a shader statically writes a value to any element of <em>gl_FragData</em>, it |
| may not assign a value to <em>gl_FragColor</em>. |
| That is, a shader may assign values to either <em>gl_FragColor</em> or |
| <em>gl_FragData</em>, but not both. |
| Multiple shaders linked together must also consistently write just one of |
| these variables. |
| Similarly, if user-declared output variables are in use (statically assigned |
| to), then the built-in variables <em>gl_FragColor</em> and <em>gl_FragData</em> may not be |
| assigned to. |
| These incorrect usages all generate compile-time or link-time errors.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a shader executes the <strong>discard</strong> keyword, the fragment is discarded, and |
| the values of <em>gl_FragDepth</em> and <em>gl_FragColor</em> become irrelevant.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="compatibility-profile-vertex-shader-built-in-inputs">7.2. Compatibility Profile Vertex Shader Built-In Inputs</h3> |
| <div class="paragraph"> |
| <p>The following predeclared input names can be used from within a vertex |
| shader to access the current values of OpenGL state when using the |
| compatibility profile.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">in vec4 gl_Color; |
| in vec4 gl_SecondaryColor; |
| in vec3 gl_Normal; |
| in vec4 gl_Vertex; |
| in vec4 gl_MultiTexCoord0; |
| in vec4 gl_MultiTexCoord1; |
| in vec4 gl_MultiTexCoord2; |
| in vec4 gl_MultiTexCoord3; |
| in vec4 gl_MultiTexCoord4; |
| in vec4 gl_MultiTexCoord5; |
| in vec4 gl_MultiTexCoord6; |
| in vec4 gl_MultiTexCoord7; |
| in <span class="predefined-type">float</span> gl_FogCoord;</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="built-in-constants">7.3. Built-In Constants</h3> |
| <div class="paragraph"> |
| <p>The following built-in constants are declared in all shaders. |
| The actual values used are implementation-dependent, but must be at least |
| the value shown.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span> |
| <span class="comment">// Implementation-dependent constants. The example values below</span> |
| <span class="comment">// are the minimum values allowed for these maximums.</span> |
| <span class="comment">//</span></code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAttribs = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexUniformVectors = <span class="integer">256</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexOutputComponents = <span class="integer">64</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingComponents = <span class="integer">60</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingVectors = <span class="integer">15</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexImageUniforms = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAtomicCounters = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVertexAtomicCounterBuffers = <span class="integer">0</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessPatchComponents = <span class="integer">120</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxPatchVertices = <span class="integer">32</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessGenLevel = <span class="integer">64</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlInputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlOutputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlTotalOutputComponents = <span class="integer">4096</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlImageUniforms = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounters = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessControlAtomicCounterBuffers = <span class="integer">0</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationInputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationOutputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationImageUniforms = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounters = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTessEvaluationAtomicCounterBuffers = <span class="integer">0</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryInputComponents = <span class="integer">64</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryOutputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryImageUniforms = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryOutputVertices = <span class="integer">256</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryTotalOutputComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryVaryingComponents = <span class="integer">64</span>; <span class="comment">// deprecated</span> |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounters = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxGeometryAtomicCounterBuffers = <span class="integer">0</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentImageUniforms = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentInputComponents = <span class="integer">128</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentUniformVectors = <span class="integer">256</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounters = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxFragmentAtomicCounterBuffers = <span class="integer">1</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxDrawBuffers = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MinProgramTexelOffset = -<span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxProgramTexelOffset = <span class="integer">7</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxImageUnits = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxSamples = <span class="integer">4</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxImageSamples = <span class="integer">0</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxClipDistances = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCullDistances = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxViewports = <span class="integer">16</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeImageUniforms = <span class="integer">8</span>; |
| <span class="directive">const</span> ivec3 gl_MaxComputeWorkGroupCount = { <span class="integer">65535</span>, <span class="integer">65535</span>, <span class="integer">65535</span> }; |
| <span class="directive">const</span> ivec3 gl_MaxComputeWorkGroupSize = { <span class="integer">1024</span>, <span class="integer">1024</span>, <span class="integer">64</span> }; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeUniformComponents = <span class="integer">1024</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeTextureImageUnits = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeAtomicCounters = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxComputeAtomicCounterBuffers = <span class="integer">8</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedTextureImageUnits = <span class="integer">96</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedImageUniforms = <span class="integer">48</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedImageUnitsAndFragmentOutputs = <span class="integer">8</span>; <span class="comment">// deprecated</span> |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedShaderOutputResources = <span class="integer">16</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounters = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedAtomicCounterBuffers = <span class="integer">1</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxCombinedClipAndCullDistances = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxAtomicCounterBindings = <span class="integer">1</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxAtomicCounterBufferSize = <span class="integer">32</span>; |
| |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTransformFeedbackBuffers = <span class="integer">4</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTransformFeedbackInterleavedComponents = <span class="integer">64</span>; |
| |
| <span class="directive">const</span> highp <span class="predefined-type">int</span> gl_MaxInputAttachments = <span class="integer">1</span>; <span class="comment">// only present when targeting Vulkan</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The constant <em>gl_MaxVaryingFloats</em> is removed in the core profile, use |
| <em>gl_MaxVaryingComponents</em> instead.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="compatibility-profile-built-in-constants">7.3.1. Compatibility Profile Built-In Constants</h4> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureUnits = <span class="integer">2</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxTextureCoords = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxClipPlanes = <span class="integer">8</span>; |
| <span class="directive">const</span> <span class="predefined-type">int</span> gl_MaxVaryingFloats = <span class="integer">60</span>;</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="built-in-uniform-state">7.4. Built-In Uniform State</h3> |
| <div class="paragraph"> |
| <p>Built-in uniform state is not available when generating SPIR-V. |
| Otherwise, as an aid to accessing OpenGL processing state, the following |
| uniform variables are built into the OpenGL Shading Language.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span> |
| <span class="comment">// Depth range in window coordinates,</span> |
| <span class="comment">// section 13.6.1 "Controlling the Viewport" in the</span> |
| <span class="comment">// OpenGL Specification.</span> |
| <span class="comment">//</span> |
| <span class="comment">// Note: Depth-range state is only for viewport 0.</span> |
| <span class="comment">//</span> |
| <span class="keyword">struct</span> gl_DepthRangeParameters { |
| <span class="predefined-type">float</span> near; <span class="comment">// n</span> |
| <span class="predefined-type">float</span> far; <span class="comment">// f</span> |
| <span class="predefined-type">float</span> diff; <span class="comment">// f - n</span> |
| }; |
| uniform gl_DepthRangeParameters gl_DepthRange; |
| uniform <span class="predefined-type">int</span> gl_NumSamples;</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>These variables are only guaranteed to be available in the fragment stage. |
| In other stages, their presence and function is implementation-defined.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="compatibility-profile-state">7.4.1. Compatibility Profile State</h4> |
| <div class="paragraph"> |
| <p>These variables are present only in the compatibility profile. |
| They are not available to compute shaders, but are available to all other |
| shaders.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++"><span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| uniform mat4 gl_ModelViewMatrix; |
| uniform mat4 gl_ProjectionMatrix; |
| uniform mat4 gl_ModelViewProjectionMatrix; |
| uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords]; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| uniform mat3 gl_NormalMatrix; <span class="comment">// transpose of the inverse of the</span> |
| <span class="comment">// upper leftmost 3x3 of gl_ModelViewMatrix</span> |
| |
| uniform mat4 gl_ModelViewMatrixInverse; |
| uniform mat4 gl_ProjectionMatrixInverse; |
| uniform mat4 gl_ModelViewProjectionMatrixInverse; |
| uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords]; |
| |
| uniform mat4 gl_ModelViewMatrixTranspose; |
| uniform mat4 gl_ProjectionMatrixTranspose; |
| uniform mat4 gl_ModelViewProjectionMatrixTranspose; |
| uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords]; |
| |
| uniform mat4 gl_ModelViewMatrixInverseTranspose; |
| uniform mat4 gl_ProjectionMatrixInverseTranspose; |
| uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose; |
| uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords]; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| uniform <span class="predefined-type">float</span> gl_NormalScale; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| uniform vec4 gl_ClipPlane[gl_MaxClipPlanes]; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| <span class="keyword">struct</span> gl_PointParameters { |
| <span class="predefined-type">float</span> size; |
| <span class="predefined-type">float</span> sizeMin; |
| <span class="predefined-type">float</span> sizeMax; |
| <span class="predefined-type">float</span> fadeThresholdSize; |
| <span class="predefined-type">float</span> distanceConstantAttenuation; |
| <span class="predefined-type">float</span> distanceLinearAttenuation; |
| <span class="predefined-type">float</span> distanceQuadraticAttenuation; |
| }; |
| |
| uniform gl_PointParameters gl_Point; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| <span class="keyword">struct</span> gl_MaterialParameters { |
| vec4 emission; <span class="comment">// Ecm</span> |
| vec4 ambient; <span class="comment">// Acm</span> |
| vec4 diffuse; <span class="comment">// Dcm</span> |
| vec4 specular; <span class="comment">// Scm</span> |
| <span class="predefined-type">float</span> shininess; <span class="comment">// Srm</span> |
| }; |
| uniform gl_MaterialParameters gl_FrontMaterial; |
| uniform gl_MaterialParameters gl_BackMaterial; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| <span class="keyword">struct</span> gl_LightSourceParameters { |
| vec4 ambient; <span class="comment">// Acli</span> |
| vec4 diffuse; <span class="comment">// Dcli</span> |
| vec4 specular; <span class="comment">// Scli</span> |
| vec4 position; <span class="comment">// Ppli</span> |
| vec4 halfVector; <span class="comment">// Derived: Hi</span> |
| vec3 spotDirection; <span class="comment">// Sdli</span> |
| <span class="predefined-type">float</span> spotExponent; <span class="comment">// Srli</span> |
| <span class="predefined-type">float</span> spotCutoff; <span class="comment">// Crli</span> |
| <span class="comment">// (range: [0.0,90.0], 180.0)</span> |
| <span class="predefined-type">float</span> spotCosCutoff; <span class="comment">// Derived: cos(Crli)</span> |
| <span class="comment">// (range: [1.0,0.0],-1.0)</span> |
| <span class="predefined-type">float</span> constantAttenuation; <span class="comment">// K0</span> |
| <span class="predefined-type">float</span> linearAttenuation; <span class="comment">// K1</span> |
| <span class="predefined-type">float</span> quadraticAttenuation; <span class="comment">// K2</span> |
| }; |
| |
| uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights]; |
| |
| <span class="keyword">struct</span> gl_LightModelParameters { |
| vec4 ambient; <span class="comment">// Acs</span> |
| }; |
| |
| uniform gl_LightModelParameters gl_LightModel; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| <span class="comment">// Derived state from products of light and material.</span> |
| <span class="comment">//</span> |
| |
| <span class="keyword">struct</span> gl_LightModelProducts { |
| vec4 sceneColor; <span class="comment">// Derived. Ecm + Acm * Acs</span> |
| }; |
| |
| uniform gl_LightModelProducts gl_FrontLightModelProduct; |
| uniform gl_LightModelProducts gl_BackLightModelProduct; |
| |
| <span class="keyword">struct</span> gl_LightProducts { |
| vec4 ambient; <span class="comment">// Acm * Acli</span> |
| vec4 diffuse; <span class="comment">// Dcm * Dcli</span> |
| vec4 specular; <span class="comment">// Scm * Scli</span> |
| }; |
| |
| uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights]; |
| uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights]; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| uniform vec4 gl_TextureEnvColor[gl_MaxTextureUnits]; |
| uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords]; |
| uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords]; |
| uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords]; |
| uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords]; |
| uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords]; |
| uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords]; |
| uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords]; |
| uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords]; |
| |
| <span class="comment">//</span> |
| <span class="comment">// compatibility profile only</span> |
| <span class="comment">//</span> |
| <span class="keyword">struct</span> gl_FogParameters { |
| vec4 color; |
| <span class="predefined-type">float</span> density; |
| <span class="predefined-type">float</span> start; |
| <span class="predefined-type">float</span> end; |
| <span class="predefined-type">float</span> scale; <span class="comment">// Derived: 1.0 / (end - start)</span> |
| }; |
| |
| uniform gl_FogParameters gl_Fog;</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="redeclaring-built-in-blocks">7.5. Redeclaring Built-In Blocks</h3> |
| <div class="paragraph"> |
| <p>The <em>gl_PerVertex</em> block can be redeclared in a shader to explicitly |
| indicate what subset of the fixed pipeline interface will be used. |
| This is necessary to establish the interface between multiple programs. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out gl_PerVertex { |
| vec4 gl_Position; <span class="comment">// will use gl_Position</span> |
| <span class="predefined-type">float</span> gl_PointSize; <span class="comment">// will use gl_PointSize</span> |
| vec4 t; <span class="comment">// error, only gl_PerVertex members allowed</span> |
| }; <span class="comment">// no other members of gl_PerVertex will be used</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This establishes the output interface the shader will use with the |
| subsequent pipeline stage. |
| It must be a subset of the built-in members of <em>gl_PerVertex</em>. |
| Such a redeclaration can also add the <strong>invariant</strong> qualifier, interpolation |
| qualifiers, and the layout qualifiers <strong>xfb_offset</strong>, <strong>xfb_buffer</strong>, and |
| <strong>xfb_stride</strong>. |
| It can also add an array size for unsized arrays. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">out layout(xfb_buffer = <span class="integer">1</span>, xfb_stride = <span class="integer">16</span>) gl_PerVertex { |
| vec4 gl_Position; |
| layout(xfb_offset = <span class="integer">0</span>) <span class="predefined-type">float</span> gl_ClipDistance[<span class="integer">4</span>]; |
| };</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Other layout qualifiers, like <strong>location</strong>, cannot be added to such a |
| redeclaration, unless specifically stated.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If a built-in interface block is redeclared, it must appear in the shader |
| before any use of any member included in the built-in declaration, or a |
| compile-time error will result. |
| It is also a compile-time error to redeclare the block more than once or to |
| redeclare a built-in block and then use a member from that built-in block |
| that was not included in the redeclaration. |
| Also, if a built-in interface block is redeclared, no member of the built-in |
| declaration can be redeclared outside the block redeclaration. |
| If multiple shaders using members of a built-in block belonging to the same |
| interface are linked together in the same program, they must all redeclare |
| the built-in block in the same way, as described in |
| “<a href="#interface-blocks">Interface Blocks</a>” for interface block matching, or a |
| link-time error will result. |
| It will also be a link-time error if some shaders in a program redeclare a |
| specific built-in interface block while another shader in that program does |
| not redeclare that interface block yet still uses a member of that interface |
| block. |
| If a built-in block interface is formed across shaders in different |
| programs, the shaders must all redeclare the built-in block in the same way |
| (as described for a single program), or the values passed along the |
| interface are undefined.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="built-in-functions">8. Built-In Functions</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The OpenGL Shading Language defines an assortment of built-in convenience functions for |
| scalar and vector operations. |
| Many of these built-in functions can be used in more than one type of |
| shader, but some are intended to provide a direct mapping to hardware and so |
| are available only for a specific type of shader.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The built-in functions basically fall into three categories:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>They expose some necessary hardware functionality in a convenient way |
| such as accessing a texture map. |
| There is no way in the language for these functions to be emulated by a |
| shader.</p> |
| </li> |
| <li> |
| <p>They represent a trivial operation (clamp, mix, etc.) that is very |
| simple for the user to write, but they are very common and may have |
| direct hardware support. |
| It is a very hard problem for the compiler to map expressions to complex |
| assembler instructions.</p> |
| </li> |
| <li> |
| <p>They represent an operation graphics hardware is likely to accelerate at |
| some point. |
| The trigonometry functions fall into this category.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Many of the functions are similar to the same named ones in common C |
| libraries, but they support vector input as well as the more traditional |
| scalar input.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Applications should be encouraged to use the built-in functions rather than |
| do the equivalent computations in their own shader code since the built-in |
| functions are assumed to be optimal (e.g. perhaps supported directly in |
| hardware).</p> |
| </div> |
| <div class="paragraph"> |
| <p>User code can replace built-in functions with their own if they choose, by |
| simply redeclaring and defining the same name and argument list. |
| Because built-in functions are in a more outer scope than user built-in |
| functions, doing this will hide all built-in functions with the same name as |
| the redeclared function.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the built-in functions are specified below, where the input arguments |
| (and corresponding output) can be <strong>float</strong>, <strong>vec2</strong>, <strong>vec3</strong>, or <strong>vec4</strong>, |
| <em>genFType</em> is used as the argument. |
| Where the input arguments (and corresponding output) can be <strong>int</strong>, <strong>ivec2</strong>, |
| <strong>ivec3</strong>, or <strong>ivec4</strong>, <em>genIType</em> is used as the argument. |
| Where the input arguments (and corresponding output) can be <strong>uint</strong>, <strong>uvec2</strong>, |
| <strong>uvec3</strong>, or <strong>uvec4</strong>, <em>genUType</em> is used as the argument. |
| Where the input arguments (or corresponding output) can be <strong>bool</strong>, <strong>bvec2</strong>, |
| <strong>bvec3</strong>, or <strong>bvec4</strong>, <em>genBType</em> is used as the argument. |
| Where the input arguments (and corresponding output) can be <strong>double</strong>, |
| <strong>dvec2</strong>, <strong>dvec3</strong>, <strong>dvec4</strong>, <em>genDType</em> is used as the argument. |
| For any specific use of a function, the actual types substituted for |
| <em>genFType</em>, <em>genIType</em>, <em>genUType</em>, or <em>genBType</em> have to have the same |
| number of components for all arguments and for the return type. |
| Similarly, <em>mat</em> is used for any matrix basic |
| type with single-precision |
| components and <em>dmat</em> is used for any matrix basic type with |
| double-precision components.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Built-in functions have an effective precision qualification. |
| This qualification cannot be set explicitly and may be different from the |
| precision qualification of the result.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note: In general, as has been noted, precision qualification is ignored |
| unless targeting Vulkan.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The precision qualification of the operation of a built-in function is based |
| on the precision qualification of its formal parameters and actual |
| parameters (input arguments): When a formal parameter specifies a precision |
| qualifier, that is used, otherwise, the precision qualification of the |
| actual (calling) argument is used. |
| The highest precision of these will be the precision of the operation of the |
| built-in function. |
| Generally, this is applied across all arguments to a built-in function, with |
| the exceptions being:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>bitfieldExtract</strong> and <strong>bitfieldInsert</strong> ignore the <em>offset</em> and <em>bits</em> |
| arguments.</p> |
| </li> |
| <li> |
| <p><strong>interpolateAt</strong> functions only look at the <em>interpolant</em> argument.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The precision qualification of the result of a built-in function is |
| determined in one of the following ways:</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the texture sampling, image load and image store functions, the |
| precision of the return type matches the precision of the |
| texture-combined sampler type:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="c++">uniform lowp sampler2D texSampler; |
| highp vec2 coord; |
| ... |
| lowp vec4 col = texture (texSampler, coord); <span class="comment">// texture() returns lowp</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Otherwise:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>For prototypes that do not specify a resulting precision qualifier, the |
| precision will be the same as the precision of the operation (as defined |
| earlier).</p> |
| </li> |
| <li> |
| <p>For prototypes that do specify a resulting precision qualifier, the |
| specified precision qualifier is the precision qualification of the |
| result.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Where the built-in functions in the following sections specify an equation, |
| the entire equation will be evaluated at the operation’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| > 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| > 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 < 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 < 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 < 0</span>.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">genFType <strong>inversesqrt</strong>(genF
|